| title | description | services | keywords | author | manager | ms.author | ms.date | ms.topic | ms.service |
|---|---|---|---|---|---|---|---|---|---|
Develop and deploy an Azure IoT Edge module | Microsoft Docs |
Create an IoT Edge module and deploy it to an edge device |
iot-edge |
JimacoMS2 |
timlt |
v-jamebr |
11/08/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 Install Azure IoT Edge tutorial. In this tutorial, you learn how to:
[!div class="checklist"]
- Use Visual Studio Code to create an IoT Edge module
- Use VS 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 Azure Install IoT Edge tutorial.
- The IoT Hub connection string for the IoT hub that your IoT Edge device connects to.
- Visual Studio Code.
- The following Visual Studio Code extensions:
-
C# for Visual Studio Code (powered by OmniSharp) extension. (You can install the extension from the extensions panel in Visual Studio Code.)
-
Azure IoT Edge extension
[!IMPORTANT] The IoT Edge extension is not yet available in the Marketplace. Perform the following steps to install it and its dependencies:
- Install the Azure IoT Toolkit extension from the extensions panel in VS Code.
- Download the Azure IoT Edge extension VSIX here: https://aka.ms/edge-extension. Note: If you use Microsoft Edge or Internet Explorer, the browser downloads the file with a ".zip" file extension. After the file downloads, you need to change the file extension back to ".vsix".
- Install the extension VSIX by using the View | Command Palette... | Extensions: Install from VSIX... menu command, navigating to the downloaded VSIX on your computer and clicking Open. (You can also install the extension by clicking ... in the upper-right corner of the extension panel and selecting Install from VSIX....)
-
- 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.
The steps in this section are only required until Azure IoT Edge goes public. They walk you through setting up VS Code with dependencies that will not be public until we release Azure IoT Edge.
-
Install version 3 or later of the NuGet CLI. The module code depends on a couple of NuGet packages that won't be made public until we release Azure IoT Edge. For the time being, we have placed them on
myget. You need the NuGet CLI to reference these packages. -
Open Visual Studio Code.
-
Use the View | Integrated Terminal menu command to open the VS Code integrated terminal.
-
In integrated terminal, add a NuGet source for the AzureIotEdgeModule template NuGet package.
nuget sources add -name AzureIoTEdgeModule -source https://www.myget.org/F/dotnet-template-azure-iot-edge-module/api/v3/index.json -
The preview version of the Microsoft.Azure.Devices.Client package used in this tutorial is not yet available in the public gallery. To ensure that your IoT Edge module will build correctly, add a NuGet source that contains the correct package version.
nuget sources Add -Name "Edge Private Preview" -source https://www.myget.org/F/aziot-device-sdk/api/v3/index.json
In this tutorial, you use the IoT Edge extension to build a Docker image from your module code. Then you push this Docker image to a Docker repository hosted by 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 using Visual Studio Code and the IoT Edge extension.
-
Use the View | Integrated Terminal menu command to open the VS Code integrated terminal.
-
In the integrated terminal, enter the following command to install 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 InitEdgeModule method, replace the code in the try block with the following code. This code creates and configures a DeviceClient object, which allows the module to connect to the local Azure IoT Edge runtime to send and receive messages. This is similar to the way code in a device uses a DeviceClient to connect to a remote IoT Hub, except that the endpoint and credential information used in the connection string are specific to the Edge hub. The connection string parameter used in the InitEdgeModule method is supplied to the module by Azure IoT Edge in an environment variable - EdgeHubConnectionString. After creating the DeviceClient, the code registers a callback for desired properties updates on the module twin and registers the FilterHandler method as the handler for messages from the Edge Hub via the "input1" endpoint.
// Open a connection to the Edge runtime using MQTT transport and // the connection string provided as an environment variable DeviceClient ioTHubModuleClient = DeviceClient.CreateFromConnectionString(Environment.GetEnvironmentVariable("EdgeHubConnectionString"), TransportType.Mqtt_Tcp_Only); await ioTHubModuleClient.OpenAsync(); Console.WriteLine("IoT Hub module client initialized."); // 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, just like a device twin lets a back-end service configure code running on a device.
static Task onDesiredPropertiesUpdate(TwinCollection desiredProperties, object userContext) { try { Console.WriteLine("Desired property change:"); Console.WriteLine(JsonConvert.SerializeObject(desiredProperties)); if (desiredProperties["TemperatureThreshold"].exists()) 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); } // We need to indicate that we have completed the message treatment return MessageResponse.Completed; } catch (AggregateException ex) { foreach (Exception exception in ex.InnerExceptions) { Console.WriteLine(); Console.WriteLine("Error in sample: {0}", exception); } // We need to indicate that we have not completed the message treatment DeviceClient deviceClient = (DeviceClient)userContext; return MessageResponse.Abandoned; } catch (Exception ex) { Console.WriteLine(); Console.WriteLine("Error in sample: {0}", ex.Message); // We need to indicate that we have not completed the message treatment 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.
-
Build the Docker image.
- In VS Code explorer, click the Docker folder to open it. Then click the linux-x64 folder, right-click the Dockerfile 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 URL. 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 URL in the pop-up text box at the top of the VS Code window. Use the same image URL you used in step 1.c.
Add the credentials for your registry to the IoT Edge runtime on the machine where you are running your IoT Edge device. This gives the runtime access to pull the container from your repository. Run the following command on the machine where you are running your Edge device:
iotedgectl login --address <docker-repository> --username <docker-username> --password <docker-password>
Note
The preceding command gives the Python 2.7 command for Windows. If you're running your Edge device on Linux, add sudo in front of the command.
-
In the Azure portal, https://df.onecloud.azure-test.net/, navigate to your IoT hub.
-
Go to IoT Edge Explorer and select your IoT Edge device.
-
Select Set Modules.
-
Select Add IoT Edge Module.
-
In the Name field, enter
tempSensor. -
In the Image field, enter
edgepreview.azurecr.io/azureiotedge/simulated-temperature-sensor:1.0-preview. -
Leave the other settings unchanged and select Save.
-
Select Add IoT Edge Module again.
-
In the Name field, enter
filtermodule. -
In the Image field, enter your image address; for example
{your registry}/filtermodule:latest. -
Check the Edit module twin box.
-
Replace the JSON in the text box 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,
upstreamis 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 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