Debugging Azure IoT Edge modules using Visual Studio Code - visual-studio-code

I can't get local debug of IoT Edge modules working on VS Code, but part of the problem could be that I don't understand what I'm doing in the steps.
I'm following the Microsoft guide here. Can anyone explain to me when I run the command "Azure IoT Edge: Start IoT Edge Hub Simulator for Single Module" in VS Code, why do I need to pass an "input name"? Why doesn the simulator need to know this. I've got multiple input commands on my edge module and the fact I need to pass it is making me question what the simulator actually does. I want to be able to debug multiple inputs.
Also on the same documentation, I can't see how it defines which module I want to run in the simulator. Am I missing something or is the process confusing?

When you Start the IoT Edge Hub Simulator for a Single Module, you spawn two Docker containers. One is the edgeHub and the other is a testing utility. The testing utility acts as a server that you can send HTTP requests to, the requests specify the input name and the data. You can use this to send messages to various inputs on your module. Just looking at that, I understand why it is confusing to supply the input name to the simulator. But when you inspect the edgeHub container, you'll see the following environment values being passed:
"routes__output=FROM /messages/modules/target/outputs/* INTO BrokeredEndpoint(\"/modules/input/inputs/print\")",
"routes__r1=FROM /messages/modules/input/outputs/input2 INTO BrokeredEndpoint(\"/modules/target/inputs/input2\")",
"routes__r2=FROM /messages/modules/input/outputs/foo INTO BrokeredEndpoint(\"/modules/target/inputs/foo\")",
"routes__r3=FROM /messages/modules/input/outputs/input1 INTO BrokeredEndpoint(\"/modules/target/inputs/input1\")"
Just like on a real device, you need routes to talk to your module. The edgeHub container registers these routes with the values you supplied during the starting of the simulator. That input can be a comma-separated list. So if you are using more inputs, feel free to supply them when you start the simulator. Under the covers, that command runs:
iotedgehubdev start -i "input1,input2,foo"
Note: when I was testing this with the latest VS Code Extension, the first time I ran it, the textbox contained: "input1,input2".

Related

How can I pass developer machine hostname to app

After much trial and error, I have failed to come up with a solution for this problem. Hoping someone might know a way.
I want to pass my development machine hostname to the app, without hardcoding it.
My idea was to make a build phase script that captures the hostname and export it
export DEV_MACHINE_HOST=hostname
and then set it as a launch argument on the RUN scheme
-dev-machine $(DEV_MACHINE_HOST)
But to no avail.
Anyone know if this can be done?
Context:
I'm making a dev tool with a local server. I want to send http requests to this tool as long as I'm on the same network, so that it will work on device as well as the simulator.
See Providing custom variables for Info.plist for an example of this. Create a Script Phase that uses PlistBuddy with something like:
/usr/libexec/PlistBuddy \
-c "Add :DevMachineHost string `hostname`" \
"${BUILT_PRODUCTS_DIR}/${EXECUTABLE_FOLDER_PATH}/Info.plist"
And then fetch it with Bundle.main.object(forInfoDictionaryKey:).
Alternately, you can write a script that generates a Swift file that defines a global for you. (But it's more typical to do this with Info.plist.)
A scheme can't do this, because that's just how Xcode launches the app in the debugger. It's not something that's stored with the app or that influences how the app is normally launched.

Cannot view data from GCP Datastore (Firestore) in browser when using emulator

I am using Google's Datastore (which is Firestore's support for the GCP) and the emulator to handle storage locally. Everything works fine as far as storing data. But there does not appear to be any way of actually viewing the data in the browser. I have a feeling that this is not yet implemented because the emulator is still in beta. Has anyone been able to view data in their browser? It should be stressed that this is the emulator provided by the Google Cloud Platform SDK and not the one that Firebase uses for its products. The emulator is started with:
gcloud beta emulators datastore start
As of January 2022
Debugging
Setting up Firebase Datastore Emulator (FDE)
The Firebase Datastore Emulator (FDE) emulates the Google Datastore in App Engine. This is meant to run on Java 8 platforms. When correctly setup, any Datastore operations are done locally and stored to a file called local_db.bin.
The documentation for using the Firebase Datastore Emulator can be found at:
https://cloud.google.com/datastore/docs/tools/datastore-emulator
It should be noted that this documentaton contains errors and is missing some important settings. To use Firebase Datastore Emulator, install the emulator by running the following command from a terminal:
gcloud components install cloud-datastore-emulator
Start the emulator in a terminal:
gcloud beta emulators datastore start --data-dir=fbdatastore --host-port=localhost:8100
The official documentation does not indicate to use the --host-port flag. If you leave this flag out, a random port will be selected. But experience has shown that letting the port be randomly selected can result in exceptions generated by the client library used to access the local datastore - even when the port is correctly set in the environment variables.
The --data-dir flag indicates the directory where the local database file is stored. Here, it is specified as fbdatastore but you can use any folder located anywhere. You should make sure that the folder already exists before you start the emulator. In the example shown here, no path is included. This means that when you start the emulator, the directory specified by --data-dir should be in the same folder where you are launching the emulator.
The emulator will only create the local_db.bin file when you initially write data to it. If you don't write any data, it will not be created. Even it isn't created, the client APIs will still work correctly when reading from it, typically returning null values for any entities that you attempt to access. No exception will be thrown if the database file does not exist.
If the --data-dir is set to fbdatastore as used here, the local_db.bin file will be created under:
fbdatastore/WEB-INF/appengine-generated/local_db.bin
After the emulator has started, you can verify that it is running but opening a browser window and navigating to the url:
http://localhost:8100
This will only display the text "ok".
Before you can start debugging the app, several environment variables need to be set. You need to open a new terminal window and execute the following commands to set several variables:
export DATASTORE_DATASET=[project-id]
export DATASTORE_EMULATOR_HOST=localhost:8100
export DATASTORE_EMULATOR_HOST_PATH=localhost:8100/datastore
export DATASTORE_HOST=http://localhost:8100
export DATASTORE_PROJECT_ID=[project-id]
export DATASTORE_USE_PROJECT_ID_AS_APP_ID=true
The client libraries for the Datastore expect the app id to be used. But it was found that using only the app id didn't work. The environment variable DATASTORE_USE_PROJECT_ID_AS_APP_ID needs to be set as well. This is not specified in the documentation.
It should be noted that the official docs show the following:
export DATASTORE_DATASET=my-project-id
export DATASTORE_EMULATOR_HOST=::1:8432
export DATASTORE_EMULATOR_HOST_PATH=::1:8432/datastore
export DATASTORE_HOST=http://::1:8432
export DATASTORE_PROJECT_ID=my-project-id
For MacOS, this is wrong. The variables with values set to ::1 is wrong. Using this will cause exceptions and probably prevent the emulator from even loading. The ::1 needs to be replaced with localhost, as shown above.
You can just copy the 6 lines shown above and paste them into a terminal and hit Enter. But it is easier to just place these into a bash file and execute it. These need to be set before the local development server is started. The following bash file will set the environment variables and then start the development server:
export DATASTORE_DATASET=[project-id]
export DATASTORE_EMULATOR_HOST=localhost:8100
export DATASTORE_EMULATOR_HOST_PATH=localhost:8100/datastore
export DATASTORE_HOST=http://localhost:8100
export DATASTORE_PROJECT_ID=[project-id]
export DATASTORE_USE_PROJECT_ID_AS_APP_ID=true
java_dev_appserver.sh --address=0.0.0.0 --port=8080 --disable_update_check --jvm_flag=-Xdebug --jvm_flag=-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 build/exploded-website
Replace [project-id] with the project id shown in your Googel Cloud Platform console (don't include the square brackets).
The address parameter for java_dev_appserver.sh is set here to 8000. You will need to set this in your IDE. Also, the port for java_dev_appserver.sh is set to 8080. You can set this to whatever works on your system and doesn't conflict with any existing ports used elsewhere. The last parameter for java_dev_appserver.sh is the location of your war files, which is the compiled app. Here, it is located at build/web-site. Replace this with the location of your own build files.
To view the datastore locally in your browser, navigate to:
http://localhost:8080/_ah/admin/datastore
Details on the command parameters used to start the emulator can be found at:
https://cloud.google.com/sdk/gcloud/reference/beta/emulators/datastore/start
As far as I can understand what you want to do is to add data in the Datastore emulator running on your console and be able to see this data in the UI right?
Vieweing the data in the UI actually incurs in expenses for you because Datastore have to query the data to be able to display it on the UI.
I can still recommend you to create a Feature Request if you want to be able to see the entries form the Datastore emulator for free in the UI

How do I get Robotframework (in Eclipse) to respond to terminal prompt

I'm currently running Robotframework in Eclipse on Windows 10 OS. I'm using an external python library that allows students and teachers to use this extracted library to connect to our hardware devices. I'm automating the extractions from the main site package made by our developers. If more than one device is plugged into the USB ports on the PC, then the code does the following:
x = input("Select one device:")
selected = int(x)
This causes a terminal prompt so the user has to type in a 0, or 1 for example, then hit the ENTER key. User response will allow the code to further process a connect to the selected device. Note, this prompt is not a GUI. So when I run Robotframework, it will execute the steps up to the point where it's prompting.
It seems like this should be pretty easy, but I can't seem to figure it out. Since you're inside a piece of code that's waiting for input, how do you make RobotFramework do something with it?
Edit: It occurs to me that maybe there's a way to execute a delayed Robotframework step that starts an external python command after a specified time, to throw a '0' and a RETURN key response. I had a python file made from an import of pynput.py library which appears to work from the command line execution (prints a 0, or a 1, and a return line feed). There's gotta be an easier way I'd think, but I don't know what it is.
Edit: Can I run a keyword from a listener that watches for the command prompt and the keyword runs another python file to feed the prompt? If I get this to work, then all I have to do is leave the devices on the USB port (or hub for that matter), and select the devices I want to do further testing on. Our devices are supported Blooth tooth as well but I need to run both USB and BLE tests to verify our Python extractions the teachers and students can use.
Edit: The other option is to use a software programmable hub and select the USB with a specific device on it, but I'm trying to avoid that.
OK, I solved it using Robotframework background process. I wrote a small python file that gets executed from the process. It has a 5 second timer (more than I need) and then Robotframework runs the next Test Case step. The Python file then does some keyboard presses, selecting the port and an ENTER key which goes out to the console (feeding the input prompt). It connects the sensor.
So in my Robotframework Test Case I do the following:
*** Test Case ***
smoke_test
Start process . Python . usbportselect
open usb
The Python program called from the process looks like this:
import time
import pynput
from pynput.keyboard import Key, Controller
keyboard = Controller()
def choose_usb(portvalue)
keyboard.press(portvalue)
keyboard.release(portvalue)
keyboard.press(Key.enter)
keyboard.release(Key.enter)
time.sleep(5)
choose_usb('0')
Note: I'm pretty sure this won't fix all the problems with using processes, but it's at least a start and a way to feed input to a prompt resulted from a future Test Case step

Why do Selenium tests behave different on different machines?

I couldn't find much information on Google regarding this topic. Below, I have provided three results from the same Selenium tests. Why am I getting different results when running the tests from different places?
INFO:
So our architecture: Bitbucket, Bamboo Stage 1 (Build, Deploy to QA), Bamboo Stage 2 (start Amazon EC2 instance "Test", run tests from Test against recently deployed QA)
Using Chrome Webdriver.
For all three of the variations I am using the same QA URL that our application is deployed on.
I am running all tests Parallelizable per fixture
The EC2 instance is running Windows Server 2012 R2 with the Chrome browser installed
I have made sure that the test solution has been properly deployed to the EC2 "test" instance. It is indeed the exact same solution and builds correctly.
First, Local:
Second, from EC2 Via SSM Script that invokes the tests:
Note that the PowerShell script calls the nunit3-console.exe just like it would be utilized in my third example using the command line.
Lastly, RDP in on EC2 and run tests from the command line:
This has me perplexed... Any reasons why Selenium is running different on different machines?
This really should be a comment, but I can't comment yet so...
I don't know enough about the application you are testing to say for sure, but this seems like something I've seen testing the application I'm working on.
I have seen two issues. First, Selenium is checking for the element before it's created. Sometimes it works and sometimes it fails, it just depends on how quickly the page loads when the test runs. There's no rhyme or reason to it. Second, the app I'm testing is pretty dumb. When you touch a field, enter data and move on to the next, it, effectively, posts all editable fields back to the database and refreshes all the fields. So, Selenium enters the value, moves to the next field and pops either a stale element error or can't find element error depending on when in the post/refresh cycle it attempts to interact with the element.
The solution I have found is moderately ugly, I tried the wait until, but because it's the same element name, it's already visible and is grabbed immediately which returns a stale element. As a result, the only thing that I have found is that by using explicit waits between calls, I can get it to run correctly consistently. Below is an example of what I have to do with the app I'm testing. (I am aware that I can condense the code, I am working within the style manual for my company)
Thread.Sleep(2000);
By nBaseLocator = By.XPath("//*[#id='attr_seq_1240']");
IWebElement baseRate = driver.FindElement(nBaseLocator);
baseRate.SendKeys(Keys.Home + xBaseRate + Keys.Tab);
If this doesn't help, please tell us more about the app and how it's functioning so we can help you find a solution.
#Florent B. Thank you!
EDIT: This ended up not working...
The tests are still running different when called remotely with a powershell script. But, the tests are running locally on both the ec2 instance and my machine correctly.
So the headless command switch allowed me to replicate my failed tests locally.
Next I found out that a headless chrome browser is used during the tests when running via script on an EC2 instance... That is automatic, so the tests where indeed running and the errors where valid.
Finally, I figured out that the screen size is indeed the culprit as it was stuck to a size of 600/400 (600/400?)
So after many tries, the only usable screen size option for Windows, C# and ChromeDriver 2.32 is to set your webDriver options when you initiate you driver:
ChromeOptions chromeOpt = new ChromeOptions();
chromeOpt.AddArguments("--headless");
chromeOpt.AddArgument("--window-size=1920,1080");
chromeOpt.AddArguments("--disable-gpu");
webDriver = new ChromeDriver(chromeOpt);
FINISH EDIT:
Just to update
Screen size is large enough.
Still attempting to solve the issue. Anyone else ran into this?
AWS SSM Command -> Powershell -> Run Selenium Tests with Start-Process -> Any test that requires an element fails because ElementNotFound or ElementNotVisible exceptions.
Using POM for tests. FindsBy filter in c# is not finding elements.
Running tests locally on EC2 run fine from cmd, powershell and Powershell ISE.
The tests do not work correctly when executing with the AWS SSM Command. Cannot find any resources to fix problem.

iot-core custom oem image/ffu: crashing only in custom oem/ffu image. Bottom line: looking for a unique board ID

We have an iot-core UWP, headless app that runs fine (for months, hundreds of devices) when deployed directly from Visual Studio 2015 or as an App onto the retail iot-core distribution. In order to avoid over-air-update problems caused by recent automatic iot-core updates, we are trying to get a custom oem image/ffu built and deployed to the microsoft store. However, even after walking through the documentation/examples in detail, our app is still crashing when we deploy our oem image/ffu.
UPDATE
OK, no debugger still, but I found where it crashes, now is the question why the oem-ffu behaves differently from the side-deployed code (our code is identical) Since iot-core/UWP provices no way to get the board-UUID, I use the MAC of the primary network interface. To get this, I use this http://embedded101.com/BruceEitman/entryid/676/Windows-10-IoT-Core-Getting-the-MAC-Address-from-Raspberry-Pi which requires that a webserver be running, which it normally is, otherwise the console webapp would not work. However, on the OEM-Custom-Build-Version I get a crash in this routine. I don't know where since I can't debug, but it crashes, and I get a null back, which causes my azure storage connect to crash. I do not block processing since I have a retry loop... Anyway, what is the difference or what must we do to enable this code to also work in the OEM build?
The grass roots issue is: all I really need is a unique ID for the RPi board from somewhere... which does not seem possible via C#!? See How to get the processor serial number of Raspberry PI 2 with Windows IOT
So it looks like my MAC-Address solution above was the best we can expect at the moment, but doesn't work on the oem build. Why?
If your purpose is to avoid problem with auto update, you can use powershell script or putty to disable auto-update. Will that work for you?
Below is the command line you can use to disable auto-update,
Use powershell or putty to connect to pi using administrator
sc.exe config wuauserv start=disabled
sc.exe query wuauserv
sc.exe stop wuauserv
sc.exe query wuauserv
REG.exe QUERY HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\wuauserv /v Start