title | description | services | keywords | author | manager | ms.author | ms.date | ms.topic | ms.service |
---|---|---|---|---|---|---|---|---|---|
Azure IoT Edge C# module | Microsoft Docs |
Create an IoT Edge module with C# code and deploy it to an edge device |
iot-edge |
JimacoMS2 |
timlt |
v-jamebr |
11/15/2017 |
article |
iot-edge |
You can use IoT Edge modules to deploy code that implements your business logic directly to your IoT Edge devices. This tutorial walks you through creating and deploying an IoT Edge module that filters sensor data on the simulated IoT Edge device that you created in the Deploy Azure IoT Edge on a simulated device on Windows or Linux tutorials. In this tutorial, you learn how to:
[!div class="checklist"]
- Use Visual Studio Code to create an IoT Edge module based on .NET core 2.0
- Use Visual Studio Code and Docker to create a docker image and publish it to your registry
- Deploy the module to your IoT Edge device
- View generated data
The IoT Edge module that you create in this tutorial filters the temperature data generated by your device and only sends messages upstream when the temperature is above a specified threshold.
- The Azure IoT Edge device that you created in the quickstart or previous tutorial.
- The IoT Hub connection string for the IoT hub that your IoT Edge device connects to.
- Visual Studio Code.
- Azure IoT Edge extension for Visual Studio Code. (You can install the extension from the extensions panel in Visual Studio Code.)
- C# for Visual Studio Code (powered by OmniSharp) extension. (You can install the extension from the extensions panel in Visual Studio Code.)
- Docker. The Community Edition (CE) for your platform is sufficient for this tutorial. Make sure you install it on the computer that you run VS Code on.
- .NET Core 2.0 SDK.
In this tutorial, you use the Azure IoT Edge extension for VS Code to build a module and create a Docker image. Then you push this Docker image to a Docker repository hosted on a Docker registry. Finally, you deploy your Docker image packaged as a Docker container from your registry to your IoT Edge device.
You can use any Docker-compatible registry for this tutorial. Two popular Docker registry services available in the cloud are Azure Container Registry and Docker Hub:
-
Azure Container Registry is available with a paid subscription. For this tutorial, the Basic subscription is sufficient.
-
Docker Hub offers one free private repository if you sign up for a (free) Docker ID.
-
To sign up for a Docker ID, follow the instructions in Register for a Docker ID on the Docker site.
-
To create a private Docker repository, follow the instructions in Creating a new repository on Docker Hub on the Docker site.
-
Throughout this tutorial, where appropriate, commands will be provided for both Azure Container Registry and Docker Hub.
The following steps show you how to create an IoT Edge module based on .NET core 2.0 using Visual Studio Code and the Azure IoT Edge extension.
-
Open VS Code.
-
Use the View | Integrated Terminal menu command to open the VS Code integrated terminal.
-
In the integrated terminal, enter the following command to install (or update) the AzureIoTEdgeModule template in dotnet:
dotnet new -i Microsoft.Azure.IoT.Edge.Module
-
In the integrated terminal, enter the following command to create a project for the new module:
dotnet new aziotedgemodule -n FilterModule
[!NOTE] This command creates the project folder, FilterModule, in the current working folder. If you want to create it in another location, change directories before running the command.
-
Use the File | Open Folder menu command, browse to the FilterModule folder, and click Select Folder to open the project in VS Code.
-
In VS Code explorer, click Program.cs to open it.
-
Add the following field to the Program class.
static int temperatureThreshold { get; set; } = 25;
-
Add the following classes to the Program class. These classes define the expected schema for the body of incoming messages.
class MessageBody { public Machine machine {get;set;} public Ambient ambient {get; set;} public string timeCreated {get; set;} } class Machine { public double temperature {get; set;} public double pressure {get; set;} } class Ambient { public double temperature {get; set;} public int humidity {get; set;} }
-
In the Init method, the code creates and configures a DeviceClient object. This object allows the module to connect to the local Azure IoT Edge runtime to send and receive messages. The connection string parameter used in the Init method is supplied to the module by IoT Edge runtime in the environment variable EdgeHubConnectionString. After creating the DeviceClient, the code registers a callback for receiving messages from the IoT Edge hub via the input1 endpoint. Replace the method used as callback for handling messages with a new one, and attach a callback for desired properties updates on the module twin. To make this change, replace the last line of the Init method with the following code:
// Register callback to be called when a message is received by the module // await ioTHubModuleClient.SetImputMessageHandlerAsync("input1", PipeMessage, iotHubModuleClient); // Attach callback for Twin desired properties updates await ioTHubModuleClient.SetDesiredPropertyUpdateCallbackAsync(onDesiredPropertiesUpdate, null); // Register callback to be called when a message is received by the module await ioTHubModuleClient.SetInputMessageHandlerAsync("input1", FilterMessages, ioTHubModuleClient);
-
Add the following method to the Program class to update the temperatureThreshold field based on the desired properties sent by the back-end service via the module twin. All modules have their own module twin. A module twin lets a back-end service configure the code running inside a module.
static Task onDesiredPropertiesUpdate(TwinCollection desiredProperties, object userContext) { try { Console.WriteLine("Desired property change:"); Console.WriteLine(JsonConvert.SerializeObject(desiredProperties)); if (desiredProperties["TemperatureThreshold"]!=null) temperatureThreshold = desiredProperties["TemperatureThreshold"]; } catch (AggregateException ex) { foreach (Exception exception in ex.InnerExceptions) { Console.WriteLine(); Console.WriteLine("Error when receiving desired property: {0}", exception); } } catch (Exception ex) { Console.WriteLine(); Console.WriteLine("Error when receiving desired property: {0}", ex.Message); } return Task.CompletedTask; }
-
Replace the PipeMessage method with the following method. This method is called whenever the module is sent a message from the Edge Hub. It filters messages based on the temperature value in the body of the message, and the temperature threshold set via the module twin.
static async Task<MessageResponse> FilterMessages(Message message, object userContext) { int counterValue = Interlocked.Increment(ref counter); try { DeviceClient deviceClient = (DeviceClient)userContext; byte[] messageBytes = message.GetBytes(); string messageString = Encoding.UTF8.GetString(messageBytes); Console.WriteLine($"Received message {counterValue}: [{messageString}]"); // Get message body var messageBody = JsonConvert.DeserializeObject<MessageBody>(messageString); if (messageBody != null && messageBody.machine.temperature > temperatureThreshold) { Console.WriteLine($"Machine temperature {messageBody.machine.temperature} " + $"exceeds threshold {temperatureThreshold}"); var filteredMessage = new Message(messageBytes); foreach (KeyValuePair<string, string> prop in message.Properties) { filteredMessage.Properties.Add(prop.Key, prop.Value); } filteredMessage.Properties.Add("MessageType", "Alert"); await deviceClient.SendEventAsync("output1", filteredMessage); } // Indicate that the message treatment is completed return MessageResponse.Completed; } catch (AggregateException ex) { foreach (Exception exception in ex.InnerExceptions) { Console.WriteLine(); Console.WriteLine("Error in sample: {0}", exception); } // Indicate that the message treatment is not completed DeviceClient deviceClient = (DeviceClient)userContext; return MessageResponse.Abandoned; } catch (Exception ex) { Console.WriteLine(); Console.WriteLine("Error in sample: {0}", ex.Message); // Indicate that the message treatment is not completed DeviceClient deviceClient = (DeviceClient)userContext; return MessageResponse.Abandoned; } }
-
Build the project. Use the View | Explorer menu command to open the VS Code explorer. In the explorer, right-click the FilterModule.csproj file and click Build IoT Edge module to compile the module and export the binary and its dependencies into a folder that the Docker image is created from in the next step.
-
Build the Docker image.
- In VS Code explorer, click the Docker folder to open it. Then select the folder for your container platform, either linux-x64 or windows-nano.
- Right-click the Dockerfile file and click Build IoT Edge module Docker image.
- In the Select Folder box, either browse to or enter
./bin/Debug/netcoreapp2.0/publish
. Click Select Folder as EXE_DIR. - In the pop-up text box at the top of the VS Code window, enter the image name. For example:
<docker registry address>/filtermodule:latest
; where docker registry address is your Docker ID if you are using Docker Hub or similar to<your registry name>.azurecr.io
, if you are using Azure Container Registry.
-
Sign in to Docker. In integrated terminal, enter the following command:
-
Docker Hub (enter your credentials when prompted):
docker login
-
For Azure Container Registry:
docker login -u <username> -p <password> <Login server>
To find the user name, password and login server to use in this command, go to the [Azure portal] (https://portal.azure.com). From All resources, click the tile for your Azure container registry to open its properties, then click Access keys. Copy the values in the Username, password, and Login server fields. The login server sould be of the form:
<your registry name>.azurecr.io
.
-
-
Push the image to your Docker repository. Use the View | Command Palette ... | Edge: Push IoT Edge module Docker image menu command and enter the image name in the pop-up text box at the top of the VS Code window. Use the same image name you used in step 1.d.
Add the credentials for your registry to the Edge runtime on the computer where you are running your Edge device. This gives the runtime access to pull the container.
-
For Windows, run the following command:
iotedgectl login --address <docker-registry-address> --username <docker-username> --password <docker-password>
-
For Linux, run the following command:
sudo iotedgectl login --address <docker-registry-address> --username <docker-username> --password <docker-password>
-
In the Azure portal, navigate to your IoT hub.
-
Go to IoT Edge (preview) and select your IoT Edge device.
-
Select Set Modules.
-
Add the tempSensor module. This step is only required if you have not previously deployed the tempSensor module to your IoT Edge device.
- Select Add IoT Edge Module.
- In the Name field, enter
tempSensor
. - In the Image URI field, enter
microsoft/azureiotedge-simulated-temperature-sensor:1.0-preview
. - Leave the other settings unchanged and click Save.
-
Add the filtermodule
-
Select Add IoT Edge Module again.
-
In the Name field, enter
filtermodule
. -
In the Image field, enter your image address; for example
<docker registry address>/filtermodule:latest
. -
Check the Edit module twin box.
-
Replace the JSON in the text box for the module twin with the following JSON:
{ "properties.desired":{ "TemperatureThreshold":25 } }
-
Click Save.
-
-
Click Next.
-
In the Specify Routes step, copy the JSON below into the text box. Modules publish all messages to the Edge runtime. Declarative rules in the runtime define where those messages flow. In this tutorial you need two routes. The first route transports messages from the temperature sensor to the filter module via the "input1" endpoint, which is the endpoint that you configured with the FilterMessages handler. The second route transports messages from the filter module to IoT Hub. In this route,
upstream
is a special destination that tells Edge Hub to send messages to IoT Hub.{ "routes":{ "sensorToFilter":"FROM /messages/modules/tempSensor/outputs/temperatureOutput INTO BrokeredEndpoint(\"/modules/filtermodule/inputs/input1\")", "filterToIoTHub":"FROM /messages/modules/filtermodule/outputs/output1 INTO $upstream" } }
-
Click Next.
-
In the Review Template step, click Submit.
-
Return to the IoT Edge device details page and click Refresh. You should see the new filtermodule running along with the tempSensor module and the IoT Edge runtime.
To monitor device to cloud messages sent from your IoT Edge device to your IoT hub:
-
Configure the Azure IoT Toolkit extension with connection string for your IoT hub:
-
Use the View | Explorer menu command to open the VS Code explorer.
-
In the explorer, click IOT HUB DEVICES and then click .... Click Set IoT Hub Connection String and enter the connection string for the IoT hub that your IoT Edge device connects to in the pop-up window.
To find the connection string, click the tile for your IoT hub in the Azure portal and then click Shared access policies. In Shared access policies, click the iothubowner policy and copy the IoT Hub connection string in the iothubowner window.
-
-
To monitor data arriving at the IoT hub, use the View | Command Palette... | IoT: Start monitoring D2C message menu command.
-
To stop monitoring data, use the View | Command Palette... | IoT: Stop monitoring D2C message menu command.
In this tutorial, you created an IoT Edge module that contains code to filter raw data generated by your IoT Edge device. You can continue on to either of the following tutorials to learn about other ways that Azure IoT Edge can help you turn data into business insights at the edge.
[!div class="nextstepaction"] Deploy Azure Function as a module Deploy Azure Stream Analytics as a module