Download as pdf or txt
Download as pdf or txt
You are on page 1of 432

Contents

Azure IoT Edge Documentation


Overview
About Azure IoT Edge
Quickstarts
Deploy code to a Linux device
Deploy code to a Windows device
Tutorials
1. Set up development environment
Develop for Linux devices
Develop for Windows devices
2. Develop custom code modules
C
C modules for Linux devices
C modules for Windows devices
C#
C# modules for Linux devices
C# modules for Windows devices
Java
Node.js
Python
3. Deploy Azure services as modules
Filter data with Azure Functions
Find averages with Azure Stream Analytics
Score data with Azure Machine Learning
Classify images with Custom Vision
Store data locally with SQL
4. End-to-end example of machine learning at the edge
Introduction
Set up development machine and Azure services
Generate simulated device data
Train and deploy an Azure Machine Learning model
Configure a transparent gateway
Create and deploy IoT Edge modules
Send data to IoT Hub via transparent gateway
Concepts
IoT Edge runtime
IoT Edge modules
Understand Azure IoT Edge modules
IoT Edge agent and hub properties
Development
Develop modules
Development environment
Deployment
Deployment manifest
Automatic deployments
Offline capabilities
IoT Edge device as a gateway
Security
Securing Azure IoT Edge
IoT Edge security manager
IoT Edge certificates
Platform support
Production deployment checklist
IoT Edge glossary
How-to guides
Register an IoT Edge device
Install and manage IoT Edge
Linux
Windows
Linux containers on Windows
Windows Server VM
Ubuntu VM
Kubernetes
Update the runtime version
Auto-provision with DPS
TPM attestation
Linux
Windows
Symmetric key attestation
Develop and debug custom modules
Visual Studio 2019
Visual Studio Code
Deploy modules
Azure portal
Azure CLI
Visual Studio Code
Deploy and monitor at scale
Azure portal
Azure CLI
Use IoT Edge devices as gateways
Configure a transparent gateway
Authenticate a downstream device
Connect a downstream device
Modbus protocol gateway
Configure proxy support
Store data at the edge
Give modules access to a device's local storage
Azure Blob Storage on IoT Edge
Deploy blob storage modules
Manage with DevOps tools
Azure DevOps Projects
Azure DevOps
IoT Edge plugin for Jenkins
Troubleshoot
Related
Solutions
IoT Central
IoT solution accelerators
Platform Services
IoT Hub
IoT Plug and Play
IoT Hub Device Provisioning Service
IoT Service SDKs
Maps
Time Series Insights
IoT Edge
Azure IoT Edge
IoT Device SDKs
Resources
Azure IoT Samples for C# (.NET)
Azure IoT Samples for Node.js
Azure IoT Samples for Java
Azure IoT Samples for Python
Azure IoT Samples for iOS Platform
Azure Certified for IoT device catalog
Azure IoT Developer Center
Azure Roadmap
Azure IoT Edge for VS Code
Azure IoT Hub Toolkit for VS Code
DeviceExplorer tool
iothub-diagnostics tool
MSDN forum
Pricing
Pricing calculator
Service updates
Stack Overflow
Technical case studies
Videos
What is Azure IoT Edge
10/28/2019 • 3 minutes to read • Edit Online

Azure IoT Edge moves cloud analytics and custom business logic to devices so that your organization can focus on
business insights instead of data management. Scale out your IoT solution by packaging your business logic into
standard containers, then you can deploy those containers to any of your devices and monitor it all from the cloud.
Analytics drives business value in IoT solutions, but not all analytics needs to be in the cloud. If you want to
respond to emergencies as quickly as possible, you can run anomaly detection workloads at the edge. If you want
to reduce bandwidth costs and avoid transferring terabytes of raw data, you can clean and aggregate the data
locally then only send the insights to the cloud for analysis.
Azure IoT Edge is made up of three components:
IoT Edge modules are containers that run Azure services, third-party services, or your own code. Modules are
deployed to IoT Edge devices and execute locally on those devices.
The IoT Edge runtime runs on each IoT Edge device and manages the modules deployed to each device.
A cloud-based interface enables you to remotely monitor and manage IoT Edge devices.

NOTE
Azure IoT Edge is available in the free and standard tier of IoT Hub. The free tier is for testing and evaluation only. For more
information about the basic and standard tiers, see How to choose the right IoT Hub tier.

IoT Edge modules


IoT Edge modules are units of execution, implemented as Docker compatible containers, that run your business
logic at the edge. Multiple modules can be configured to communicate with each other, creating a pipeline of data
processing. You can develop custom modules or package certain Azure services into modules that provide insights
offline and at the edge.
Artificial intelligence at the edge
Azure IoT Edge allows you to deploy complex event processing, machine learning, image recognition, and other
high value AI without writing it in-house. Azure services like Azure Functions, Azure Stream Analytics, and Azure
Machine Learning can all be run on-premises via Azure IoT Edge. You’re not limited to Azure services, though.
Anyone is able to create AI modules and make them available to the community for use through the Azure
Marketplace.
Bring your own code
When you want to deploy your own code to your devices, Azure IoT Edge supports that, too. Azure IoT Edge holds
to the same programming model as the other Azure IoT services. You can run the same code on a device or in the
cloud. Azure IoT Edge supports both Linux and Windows so you can code to the platform of your choice. It
supports Java, .NET Core 2.0, Node.js, C, and Python so your developers can code in a language they already know
and use existing business logic.

IoT Edge runtime


The Azure IoT Edge runtime enables custom and cloud logic on IoT Edge devices. The runtime sits on the IoT Edge
device, and performs management and communication operations. The runtime performs several functions:
Installs and update workloads on the device.
Maintains Azure IoT Edge security standards on the device.
Ensures that IoT Edge modules are always running.
Reports module health to the cloud for remote monitoring.
Manages communication between downstream leaf devices and an IoT Edge device, between modules on an
IoT Edge device, and between an IoT Edge device and the cloud.

How you use an Azure IoT Edge device is up to you. The runtime is often used to deploy AI to gateway devices
which aggregate and process data from other on-premises devices, but this deployment model is just one option.
The Azure IoT Edge runtime runs on a large set of IoT devices that enables using it in a wide variety of ways. It
supports both Linux and Windows operating systems and abstracts hardware details. Use a device smaller than a
Raspberry Pi 3 if you’re not processing much data, or use an industrial server to run resource-intensive workloads.

IoT Edge cloud interface


It's difficult to manage the software life cycle for millions of IoT devices that are often different makes and models
or geographically scattered. Workloads are created and configured for a particular type of device, deployed to all of
your devices, and monitored to catch any misbehaving devices. These activities can’t be done on a per device basis
and must be done at scale.
Azure IoT Edge integrates seamlessly with Azure IoT solution accelerators to provide one control plane for your
solution’s needs. Cloud services allow you to:
Create and configure a workload to be run on a specific type of device.
Send a workload to a set of devices.
Monitor workloads running on devices in the field.
Next steps
Try out these concepts by deploying IoT Edge on a simulated device.
Quickstart: Deploy your first IoT Edge module to a
virtual Linux device
11/24/2019 • 12 minutes to read • Edit Online

Test out Azure IoT Edge in this quickstart by deploying containerized code to a virtual IoT Edge device. IoT Edge
allows you to remotely manage code on your devices so that you can send more of your workloads to the edge.
For this quickstart, we recommend using an Azure virtual machine for your IoT Edge device, which allows you to
quickly create a test machine with all prerequisites installed and then delete it when you're finished.
In this quickstart you learn how to:
1. Create an IoT Hub.
2. Register an IoT Edge device to your IoT hub.
3. Install and start the IoT Edge runtime on your virtual device.
4. Remotely deploy a module to an IoT Edge device.

This quickstart walks you through creating a Linux virtual machine that's configured to be IoT Edge device. Then
you can deploy a module from the Azure portal to your device. The module that you deploy in this quickstart is a
simulated sensor that generates temperature, humidity, and pressure data. The other Azure IoT Edge tutorials
build upon the work you do here by deploying modules that analyze the simulated data for business insights.
If you don't have an active Azure subscription, create a free account before you begin.

Use Azure Cloud Shell


Azure hosts Azure Cloud Shell, an interactive shell environment that you can use through your browser. You can
use either Bash or PowerShell with Cloud Shell to work with Azure services. You can use the Cloud Shell
preinstalled commands to run the code in this article without having to install anything on your local
environment.
To start Azure Cloud Shell:

OPTION EXAMPLE/LINK

Select Try It in the upper-right corner of a code block.


Selecting Try It doesn't automatically copy the code to Cloud
Shell.

Go to https://shell.azure.com, or select the Launch Cloud


Shell button to open Cloud Shell in your browser.

Select the Cloud Shell button on the top-right menu bar in


the Azure portal.

To run the code in this article in Azure Cloud Shell:


1. Start Cloud Shell.
2. Select the Copy button on a code block to copy the code.
3. Paste the code into the Cloud Shell session by selecting Ctrl+Shift+V on Windows and Linux or by
selecting Cmd+Shift+V on macOS.
4. Select Enter to run the code.
You use the Azure CLI to complete many of the steps in this quickstart, and Azure IoT has an extension to enable
additional functionality.
Add the Azure IoT extension to the cloud shell instance.

az extension add --name azure-cli-iot-ext

Prerequisites
Cloud resources:
A resource group to manage all the resources you use in this quickstart.

az group create --name IoTEdgeResources --location westus2

IoT Edge device:


A Linux device or virtual machine to act as your IoT Edge device. You should use the Microsoft-provided
Azure IoT Edge on Ubuntu virtual machine, which preinstalls everything you need to run IoT Edge on a
device. Accept the terms of use and create this virtual machine using the following commands:

az vm image accept-terms --urn


microsoft_iot_edge:iot_edge_vm_ubuntu:ubuntu_1604_edgeruntimeonly:latest
az vm create --resource-group IoTEdgeResources --name EdgeVM --image
microsoft_iot_edge:iot_edge_vm_ubuntu:ubuntu_1604_edgeruntimeonly:latest --admin-username azureuser --
generate-ssh-keys

It may take a few minutes to create and start the new virtual machine.
When you create a new virtual machine, make a note of the publicIpAddress, which is provided as part
of the create command output. You will use this public IP address to connect to the virtual machine later
in the quickstart.
If you prefer to run the Azure IoT Edge runtime on your own device, follow instructions at Install the
Azure IoT Edge runtime on Linux.

Create an IoT hub


Start the quickstart by creating an IoT hub with Azure CLI.

The free level of IoT Hub works for this quickstart. If you've used IoT Hub in the past and already have a free hub
created, you can use that IoT hub. Each subscription can only have one free IoT hub.
The following code creates a free F1 hub in the resource group IoTEdgeResources. Replace {hub_name} with a
unique name for your IoT hub.

az iot hub create --resource-group IoTEdgeResources --name {hub_name} --sku F1

If you get an error because there's already one free hub in your subscription, change the SKU to S1. If you get an
error that the IoT Hub name isn't available, it means that someone else already has a hub with that name. Try a
new name.

Register an IoT Edge device


Register an IoT Edge device with your newly created IoT hub.
Create a device identity for your IoT Edge device so that it can communicate with your IoT hub. The device
identity lives in the cloud, and you use a unique device connection string to associate a physical device to a
device identity.
Since IoT Edge devices behave and can be managed differently than typical IoT devices, declare this identity to
be for an IoT Edge device with the --edge-enabled flag.
1. In the Azure cloud shell, enter the following command to create a device named myEdgeDevice in your
hub.

az iot hub device-identity create --hub-name {hub_name} --device-id myEdgeDevice --edge-enabled

If you get an error about iothubowner policy keys, make sure that your cloud shell is running the latest
version of the azure-cli-iot-ext extension.
2. Retrieve the connection string for your device, which links your physical device with its identity in IoT
Hub.

az iot hub device-identity show-connection-string --device-id myEdgeDevice --hub-name {hub_name}

3. Copy the value of the connectionString key from the JSON output and save it. This value is the device
connection string. You'll use this connection string to configure the IoT Edge runtime in the next section.
Configure your IoT Edge device
Start the Azure IoT Edge runtime on your IoT Edge device.

The IoT Edge runtime is deployed on all IoT Edge devices. It has three components. The IoT Edge security
daemon starts each time an IoT Edge device boots and bootstraps the device by starting the IoT Edge agent.
The IoT Edge agent facilitates deployment and monitoring of modules on the IoT Edge device, including the
IoT Edge hub. The IoT Edge hub manages communications between modules on the IoT Edge device, and
between the device and IoT Hub.
During the runtime configuration, you provide a device connection string. Use the string that you retrieved from
the Azure CLI. This string associates your physical device with the IoT Edge device identity in Azure.
Set the connection string on the IoT Edge device
If you're using the Azure IoT Edge on Ubuntu virtual machine as described in the prerequisites, then your device
already has the IoT Edge runtime installed. You just need to configure your device with the device connection
string that you retrieved in the previous section. You can do this remotely without having to connect to the
virtual machine. Run the following command, replacing {device_connection_string} with your own string.

az vm run-command invoke -g IoTEdgeResources -n EdgeVM --command-id RunShellScript --script


"/etc/iotedge/configedge.sh '{device_connection_string}'"
If you're running IoT Edge on your local machine or an ARM32 or ARM64 device, you need to install the IoT
Edge runtime and its prerequisites on your device. Follow the instructions in Install the Azure IoT Edge runtime
on Linux, then return to this quickstart.
View the IoT Edge runtime status
The rest of the commands in this quickstart take place on your IoT Edge device itself, so that you can see what's
happening on the device. If you're using a virtual machine, connect to that machine now using the public IP
address that was output by the creation command. You can also find the public IP address on your virtual
machine's overview page in the Azure portal. Use the following command to connect to your virtual machine.
Replace {azureuser} if you used a different username than the one suggested in the prerequisites. Replace
{publicIpAddress} with your machine's address.

ssh azureuser@{publicIpAddress}

Verify that the runtime was successfully installed and configured on your IoT Edge device.

TIP
You need elevated privileges to run iotedge commands. Once you sign out of your machine and sign back in the first
time after installing the IoT Edge runtime, your permissions are automatically updated. Until then, use sudo in front of the
commands.

1. Check to see that the IoT Edge security daemon is running as a system service.

sudo systemctl status iotedge

2. If you need to troubleshoot the service, retrieve the service logs.

journalctl -u iotedge

3. View the modules running on your device.

sudo iotedge list


Your IoT Edge device is now configured. It's ready to run cloud-deployed modules.

Deploy a module
Manage your Azure IoT Edge device from the cloud to deploy a module that will send telemetry data to IoT Hub.

One of the key capabilities of Azure IoT Edge is being able to deploy code to your IoT Edge devices from the
cloud. IoT Edge modules are executable packages implemented as containers. In this section, you deploy a pre-
built module from the IoT Edge Modules section of the Azure Marketplace.
The module that you deploy in this section simulates a sensor and sends generated data. This module is a useful
piece of code when you're getting started with IoT Edge because you can use the simulated data for
development and testing. If you want to see exactly what this module does, you can view the simulated
temperature sensor source code.
To deploy your first module from the Azure Marketplace, use the following steps:
1. In the Azure portal, enter Simulated Temperature Sensor into the search and open the Marketplace
result.

2. Choose an IoT Edge device to receive this module. On the Target Devices for IoT Edge Module page,
provide the following information:
a. Subscription: select the subscription that contains the IoT hub you're using.
b. IoT Hub: select the name of the IoT hub you're using.
c. IoT Edge Device Name: if you used the suggested device name earlier in this quickstart, enter
myEdgeDevice. Or, select Find Device to choose from a list of IoT Edge devices in your IoT hub.
d. Select Create.
3. Now that you've chosen an IoT Edge module from the Azure Marketplace, and chosen an IoT Edge device
to receive the module, you're taken to a three-step wizard that helps you define exactly how to deploy the
module. In the Add Modules step of the wizard, notice that the SimulatedTemperatureSensor module
is autopopulated. In the tutorials, you use this page to add additional modules to your deployment. For
this quickstart, only deploy this one module. Select Next to continue to the next step of the wizard.
4. In the Specify Routes step of the wizard, you define how messages are passed between modules and to
IoT Hub. For the quickstart, you want all messages from all modules to go to IoT Hub ( $upstream ). If it's
not autopopulated, add the following code:

{
"routes": {
"route": "FROM /messages/* INTO $upstream"
}
}

Then select Next.


5. In the Review Deployment step of the wizard, you can preview the JSON file that defines all the
modules that get deployed to your IoT Edge device. Notice that the SimulatedTemperatureSensor
module is included, and two additional system modules called edgeAgent and edgeHub. Select Submit
when you're done reviewing.
When you submit a new deployment to an IoT Edge device, nothing is pushed to your device. Instead, the
device queries IoT Hub regularly for any new instructions. If the device finds an updated deployment
manifest, it uses the information about the new deployment to pull the module images from the cloud
then starts running the modules locally. This process may take a few minutes.
6. After you submit the module deployment details, the wizard returns you to the IoT Edge page of your
IoT hub. Select your device from the list of IoT Edge devices to see its details.
7. On the device details page, scroll down to the Modules section. Three modules should be listed:
$edgeAgent, $edgeHub, and SimulatedTemperatureSensor. If one or more of the modules are listed as
specified in deployment but not reported by device, your IoT Edge device is still starting them. Wait a few
moments and select Refresh at the top of the page.
View generated data
In this quickstart, you created a new IoT Edge device and installed the IoT Edge runtime on it. Then, you used the
Azure portal to deploy an IoT Edge module to run on the device without having to make changes to the device
itself.
In this case, the module that you pushed creates sample data that you can use for testing. The simulated
temperature sensor module generates environment data that you can use for testing later. The simulated sensor
is monitoring both a machine and the environment around the machine. For example, this sensor might be in a
server room, on a factory floor, or on a wind turbine. The message includes ambient temperature and humidity,
machine temperature and pressure, and a timestamp. The IoT Edge tutorials use the data created by this module
as test data for analytics.
Open the command prompt on your IoT Edge device again, or use the SSH connection from Azure CLI. Confirm
that the module deployed from the cloud is running on your IoT Edge device:

sudo iotedge list

View the messages being sent from the temperature sensor module:

sudo iotedge logs SimulatedTemperatureSensor -f

TIP
IoT Edge commands are case-sensitive when referring to module names.

You can also watch the messages arrive at your IoT hub by using the Azure IoT Hub Toolkit extension for Visual
Studio Code (formerly Azure IoT Toolkit extension).

Clean up resources
If you want to continue on to the IoT Edge tutorials, you can use the device that you registered and set up in this
quickstart. Otherwise, you can delete the Azure resources that you created to avoid charges.
If you created your virtual machine and IoT hub in a new resource group, you can delete that group and all the
associated resources. Double check the contents of the resource group to make sure that there's nothing you
want to keep. If you don't want to delete the whole group, you can delete individual resources instead.
Remove the IoTEdgeResources group.

az group delete --name IoTEdgeResources

Next steps
In this quickstart, you created an IoT Edge device and used the Azure IoT Edge cloud interface to deploy code
onto the device. Now, you have a test device generating raw data about its environment.
The next step is to set up your local development environment so that you can start creating IoT Edge modules
that run your business logic.
Start developing IoT Edge modules for Linux devices
Quickstart: Deploy your first IoT Edge module to a
virtual Windows device
11/24/2019 • 12 minutes to read • Edit Online

Test out Azure IoT Edge in this quickstart by deploying containerized code to a virtual IoT Edge device. IoT Edge
allows you to remotely manage code on your devices so that you can send more of your workloads to the edge.
For this quickstart, we recommend using an Azure virtual machine for your IoT Edge device, which allows you to
quickly create a test machine, install the prerequisites, and then delete it when you're finished.
In this quickstart you learn how to:
1. Create an IoT hub.
2. Register an IoT Edge device to your IoT hub.
3. Install and start the IoT Edge runtime on your virtual device.
4. Remotely deploy a module to an IoT Edge device and send telemetry to IoT Hub.

This quickstart walks you through creating a Windows virtual machine and configuring it to be IoT Edge device.
Then you can deploy a module from the Azure portal to your device. The module that you deploy in this
quickstart is a simulated sensor that generates temperature, humidity, and pressure data. The other Azure IoT
Edge tutorials build upon the work you do here by deploying modules that analyze the simulated data for
business insights.
If you don't have an active Azure subscription, create a free account before you begin.

Use Azure Cloud Shell


Azure hosts Azure Cloud Shell, an interactive shell environment that you can use through your browser. You can
use either Bash or PowerShell with Cloud Shell to work with Azure services. You can use the Cloud Shell
preinstalled commands to run the code in this article without having to install anything on your local
environment.
To start Azure Cloud Shell:

OPTION EXAMPLE/LINK

Select Try It in the upper-right corner of a code block.


Selecting Try It doesn't automatically copy the code to Cloud
Shell.

Go to https://shell.azure.com, or select the Launch Cloud


Shell button to open Cloud Shell in your browser.

Select the Cloud Shell button on the top-right menu bar in


the Azure portal.

To run the code in this article in Azure Cloud Shell:


1. Start Cloud Shell.
2. Select the Copy button on a code block to copy the code.
3. Paste the code into the Cloud Shell session by selecting Ctrl+Shift+V on Windows and Linux or by
selecting Cmd+Shift+V on macOS.
4. Select Enter to run the code.
You use the Azure CLI to complete many of the steps in this quickstart, and Azure IoT has an extension to enable
additional functionality.
Add the Azure IoT extension to the cloud shell instance.

az extension add --name azure-cli-iot-ext

Prerequisites
Cloud resources:
A resource group to manage all the resources you use in this quickstart.

az group create --name IoTEdgeResources --location westus2

IoT Edge device:


A Windows virtual machine to act as your IoT Edge device. You can create this virtual machine using the
following command, replacing {password } with a secure password:

az vm create --resource-group IoTEdgeResources --name EdgeVM --image MicrosoftWindowsDesktop:Windows-


10:rs5-pro:latest --admin-username azureuser --admin-password {password} --size Standard_DS1_v2

It may take a few minutes to create and start the new virtual machine. You can then download an RDP file
for use when connecting to your virtual machine:
1. Navigate to your new Windows virtual machine in the Azure portal.
2. Select Connect.
3. On the RDP tab, select Download RDP File.
Open this file with Remote Desktop Connection to connect to your Windows virtual machine using the
administrator name and password you specified with the az vm create command.

NOTE
This quickstart uses a Windows desktop virtual machine for simplicity. For information about which Windows operating
systems are generally available for production scenarios, see Azure IoT Edge supported systems.
If you're ready to configure your own Windows device for IoT Edge, including devices running IoT Core, follow the steps in
Install the Azure IoT Edge runtime on Windows.

Create an IoT hub


Start the quickstart by creating an IoT hub with Azure CLI.

The free level of IoT Hub works for this quickstart. If you've used IoT Hub in the past and already have a free hub
created, you can use that IoT hub. Each subscription can only have one free IoT hub.
The following code creates a free F1 hub in the resource group IoTEdgeResources. Replace {hub_name} with a
unique name for your IoT hub.

az iot hub create --resource-group IoTEdgeResources --name {hub_name} --sku F1

If you get an error because there's already one free hub in your subscription, change the SKU to S1. If you get an
error that the IoT Hub name isn't available, it means that someone else already has a hub with that name. Try a
new name.

Register an IoT Edge device


Register an IoT Edge device with your newly created IoT hub.
Create a device identity for your simulated device so that it can communicate with your IoT hub. The device
identity lives in the cloud, and you use a unique device connection string to associate a physical device to a device
identity.
Since IoT Edge devices behave and can be managed differently than typical IoT devices, declare this identity to be
for an IoT Edge device with the --edge-enabled flag.
1. In the Azure cloud shell, enter the following command to create a device named myEdgeDevice in your
hub.

az iot hub device-identity create --device-id myEdgeDevice --hub-name {hub_name} --edge-enabled

If you get an error about iothubowner policy keys, make sure that your cloud shell is running the latest
version of the azure-cli-iot-ext extension.
2. Retrieve the connection string for your device, which links your physical device with its identity in IoT Hub.

az iot hub device-identity show-connection-string --device-id myEdgeDevice --hub-name {hub_name}

3. Copy the value of the connectionString key from the JSON output and save it. This value is the device
connection string. You'll use this connection string to configure the IoT Edge runtime in the next section.
Install and start the IoT Edge runtime
Install the Azure IoT Edge runtime on your IoT Edge device and configure it with a device connection string.

The IoT Edge runtime is deployed on all IoT Edge devices. It has three components. The IoT Edge security
daemon starts each time an IoT Edge device boots and bootstraps the device by starting the IoT Edge agent. The
IoT Edge agent manages deployment and monitoring of modules on the IoT Edge device, including the IoT
Edge hub. The IoT Edge hub handles communications between modules on the IoT Edge device, and between
the device and IoT Hub.
The installation script also includes a container engine called Moby that manages the container images on your
IoT Edge device.
During the runtime installation, you're asked for a device connection string. Use the string that you retrieved from
the Azure CLI. This string associates your physical device with the IoT Edge device identity in Azure.
Connect to your IoT Edge device
The steps in this section all take place on your IoT Edge device, so you want to connect to that virtual machine
now via remote desktop.
Install and configure the IoT Edge service
Use PowerShell to download and install the IoT Edge runtime. Use the device connection string that you
retrieved from IoT Hub to configure your device.
1. If you haven't already, follow the steps in Register a new Azure IoT Edge device to register your device and
retrieve the device connection string.
2. In the virtual machine, run PowerShell as an administrator.
NOTE
Use an AMD64 session of PowerShell to install IoT Edge, not PowerShell (x86). If you're not sure which session type
you're using, run the following command:

(Get-Process -Id $PID).StartInfo.EnvironmentVariables["PROCESSOR_ARCHITECTURE"]

3. The Deploy-IoTEdge command checks that your Windows machine is on a supported version, turns on
the containers feature, downloads the Moby runtime, and then downloads the IoT Edge runtime.

. {Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; `


Deploy-IoTEdge -ContainerOs Windows

4. Your machine may restart automatically. If you are prompted by the Deploy-IoTEdge command to reboot,
do so now.
5. Run PowerShell as an administrator again.
6. The Initialize-IoTEdge command configures the IoT Edge runtime on your machine. The command
defaults to manual provisioning with Windows containers.

. {Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; `


Initialize-IoTEdge -ContainerOs Windows

7. When prompted for a DeviceConnectionString, provide the string that you copied in the previous
section. Don't include quotes around the connection string.
View the IoT Edge runtime status
Verify that the runtime was successfully installed and configured.
1. Check the status of the IoT Edge service.

Get-Service iotedge

2. If you need to troubleshoot the service, retrieve the service logs.

. {Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; Get-IoTEdgeLog

3. View all the modules running on your IoT Edge device. Since the service just started for the first time, you
should only see the edgeAgent module running. The edgeAgent module runs by default, and helps to
install and start any additional modules that you deploy to your device.

iotedge list
It may take a few minutes for the installation to complete and the IoT Edge agent module to start.
Your IoT Edge device is now configured. It's ready to run cloud-deployed modules.

Deploy a module
Manage your Azure IoT Edge device from the cloud to deploy a module that sends telemetry data to IoT Hub.

One of the key capabilities of Azure IoT Edge is being able to deploy code to your IoT Edge devices from the
cloud. IoT Edge modules are executable packages implemented as containers. In this section, you deploy a pre-
built module from the IoT Edge Modules section of the Azure Marketplace.
The module that you deploy in this section simulates a sensor and sends generated data. This module is a useful
piece of code when you're getting started with IoT Edge because you can use the simulated data for development
and testing. If you want to see exactly what this module does, you can view the simulated temperature sensor
source code.
To deploy your first module from the Azure Marketplace, use the following steps:
1. In the Azure portal, enter Simulated Temperature Sensor into the search and open the Marketplace
result.
2. Choose an IoT Edge device to receive this module. On the Target Devices for IoT Edge Module page,
provide the following information:
a. Subscription: select the subscription that contains the IoT hub you're using.
b. IoT Hub: select the name of the IoT hub you're using.
c. IoT Edge Device Name: if you used the suggested device name earlier in this quickstart, enter
myEdgeDevice. Or, select Find Device to choose from a list of IoT Edge devices in your IoT hub.
d. Select Create.
3. Now that you've chosen an IoT Edge module from the Azure Marketplace, and chosen an IoT Edge device
to receive the module, you're taken to a three-step wizard that helps you define exactly how to deploy the
module. In the Add Modules step of the wizard, notice that the SimulatedTemperatureSensor module
is autopopulated. In the tutorials, you use this page to add additional modules to your deployment. For this
quickstart, only deploy this one module. Select Next to continue to the next step of the wizard.
4. In the Specify Routes step of the wizard, you define how messages are passed between modules and to
IoT Hub. For the quickstart, you want all messages from all modules to go to IoT Hub ( $upstream ). If it's
not autopopulated, add the following code:

{
"routes": {
"route": "FROM /messages/* INTO $upstream"
}
}

Then select Next.


5. In the Review Deployment step of the wizard, you can preview the JSON file that defines all the
modules that get deployed to your IoT Edge device. Notice that the SimulatedTemperatureSensor
module is included, and two additional system modules called edgeAgent and edgeHub. Select Submit
when you're done reviewing.
When you submit a new deployment to an IoT Edge device, nothing is pushed to your device. Instead, the
device queries IoT Hub regularly for any new instructions. If the device finds an updated deployment
manifest, it uses the information about the new deployment to pull the module images from the cloud
then starts running the modules locally. This process may take a few minutes.
6. After you submit the module deployment details, the wizard returns you to the IoT Edge page of your IoT
hub. Select your device from the list of IoT Edge devices to see its details.
7. On the device details page, scroll down to the Modules section. Three modules should be listed:
$edgeAgent, $edgeHub, and SimulatedTemperatureSensor. If one or more of the modules are listed as
specified in deployment but not reported by device, your IoT Edge device is still starting them. Wait a few
moments and select Refresh at the top of the page.

View generated data


In this quickstart, you registered an IoT Edge device and installed the IoT Edge runtime on it. Then, you used the
Azure portal to deploy an IoT Edge module to run on the device without having to make changes to the device
itself.
In this case, the module that you pushed creates sample data that you can use for testing. The simulated
temperature sensor module generates environment data that you can use for testing later. The simulated sensor
is monitoring both a machine and the environment around the machine. For example, this sensor might be in a
server room, on a factory floor, or on a wind turbine. The message includes ambient temperature and humidity,
machine temperature and pressure, and a timestamp. The IoT Edge tutorials use the data created by this module
as test data for analytics.
Confirm that the module deployed from the cloud is running on your IoT Edge device.

iotedge list

View the messages being sent from the temperature sensor module to the cloud.

iotedge logs SimulatedTemperatureSensor -f

TIP
IoT Edge commands are case-sensitive when referring to module names.
You can also watch the messages arrive at your IoT hub by using the Azure IoT Hub Toolkit extension for Visual
Studio Code (formerly Azure IoT Toolkit extension).

Clean up resources
If you want to continue on to the IoT Edge tutorials, you can use the device that you registered and set up in this
quickstart. Otherwise, you can delete the Azure resources that you created to avoid charges.
If you created your virtual machine and IoT hub in a new resource group, you can delete that group and all the
associated resources. Double check the contents of the resource group to make sure that there's nothing you
want to keep. If you don't want to delete the whole group, you can delete individual resources instead.
Remove the IoTEdgeResources group.

az group delete --name IoTEdgeResources

Next steps
In this quickstart, you created an IoT Edge device and used the Azure IoT Edge cloud interface to deploy code
onto the device. Now, you have a test device generating raw data about its environment.
The next step is to set up your local development environment so that you can start creating IoT Edge modules
that run your business logic.
Start developing IoT Edge modules for Windows devices
Tutorial: Develop IoT Edge modules for Linux devices
12/2/2019 • 19 minutes to read • Edit Online

Use Visual Studio Code to develop and deploy code to Linux devices running IoT Edge.
In the quickstart articles, you created an IoT Edge device using a Linux virtual machine and deployed a pre-built
module from the Azure Marketplace. This tutorial walks through what it takes to develop and deploy your own
code to an IoT Edge device. This tutorial is a useful prerequisite for all the other tutorials, which will go into more
detail about specific programming languages or Azure services.
This tutorial uses the example of deploying a C# module to a Linux device. This example was chosen because it
is the most common developer scenario for IoT Edge solutions. Even if you plan on using a different language or
deploying an Azure service, this tutorial is still useful to learn about the development tools and concepts. After
completing this introduction to the development process, then you can choose your preferred language or Azure
service to dive into the details.
In this tutorial, you learn how to:
Set up your development machine.
Use the IoT Edge tools for Visual Studio Code to create a new project.
Build your project as a container and store it in an Azure container registry.
Deploy your code to an IoT Edge device.
If you don't have an Azure subscription, create a free account before you begin.

Key concepts
This tutorial walks through the development of an IoT Edge module. An IoT Edge module, or sometimes just
module for short, is a container that contains executable code. You can deploy one or more modules to an IoT
Edge device. Modules perform specific tasks like ingesting data from sensors, performing data analytics or data
cleaning operations, or sending messages to an IoT hub. For more information, see Understand Azure IoT Edge
modules.
When developing IoT Edge modules, it's important to understand the difference between the development
machine and the target IoT Edge device where the module will eventually be deployed. The container that you
build to hold your module code must match the operating system (OS ) of the target device. For example, the
most common scenario is someone developing a module on a Windows computer intending to target a Linux
device running IoT Edge. In that case, the container operating system would be Linux. As you go through this
tutorial, keep in mind the difference between the development machine OS and the container OS.
This tutorial targets Linux devices running IoT Edge. You can use your preferred operating system, as long as your
development machine can run Linux containers. We recommend using Visual Studio Code to develop for Linux
devices, so that's what this tutorial will use. You can use Visual Studio as well, although there are differences in
support between the two tools.
The following table lists the supported development scenarios for Linux containers in Visual Studio Code and
Visual Studio.

VISUAL STUDIO CODE VISUAL STUDIO 2017/2019

Linux device architecture Linux AMD64 Linux AMD64


Linux ARM32 Linux ARM32
VISUAL STUDIO CODE VISUAL STUDIO 2017/2019

Azure services Azure Functions


Azure Stream Analytics
Azure Machine Learning

Languages C C
C# C#
Java
Node.js
Python

More information Azure IoT Edge for Visual Studio Code Azure IoT Edge Tools for Visual Studio
2017
Azure IoT Edge Tools for Visual Studio
2019

NOTE
Support for Linux ARM64 devices is available in public preview. For more information, see Develop and debug ARM64 IoT
Edge modules in Visual Studio Code (preview).

This tutorial teaches the development steps for Visual Studio Code. If you would rather use Visual Studio, refer to
the instructions in Use Visual Studio 2019 to develop and debug modules for Azure IoT Edge.

Prerequisites
A development machine:
You can use your own computer or a virtual machine, depending on your development preferences.
Make sure that your development machine supports nested virtualization. This capability is necessary
for running a container engine, which you install in the next section.
Most operating systems that can run a container engine can be used to develop IoT Edge modules for Linux
devices. This tutorial uses a Windows computer, but points out known differences on MacOS or Linux.
Install Git, to pull module template packages later in this tutorial.
C# for Visual Studio Code (powered by OmniSharp) extension.
.NET Core 2.1 SDK.
An Azure IoT Edge device on Linux:
We recommend that you don't run IoT Edge on your development machine, but instead use a separate device.
This distinction between development machine and IoT Edge device more accurately mirrors a true
deployment scenario, and helps to keep the different concepts straight.
If you don't have a second device available, use the quickstart article to create an IoT Edge device in Azure with
a Linux virtual machine.
Cloud resources:
A free or standard-tier IoT hub in Azure.

Install container engine


IoT Edge modules are packaged as containers, so you need a container engine on your development machine to
build and manage the containers. We recommend using Docker Desktop for development because of its many
features and popularity as a container engine. With Docker Desktop on a Windows device, you can switch
between Linux containers and Windows containers so that you can easily develop modules for different types of
IoT Edge devices.
Use the Docker documentation to install on your development machine:
Install Docker Desktop for Windows
When you install Docker Desktop for Windows, you're asked whether you want to use Linux or
Windows containers. This decision can be changed at any time using an easy switch. For this tutorial, we
use Linux containers because our modules are targeting Linux devices. For more information, see
Switch between Windows and Linux containers.
Install Docker Desktop for Mac
Read About Docker CE for installation information on several Linux platforms.

Set up VS Code and tools


Use the IoT extensions for Visual Studio Code to develop IoT Edge modules. These extensions provide project
templates, automate the creation of the deployment manifest, and allow you to monitor and manage IoT Edge
devices. In this section, you install Visual Studio Code and the IoT extension, then set up your Azure account to
manage IoT Hub resources from within Visual Studio Code.
1. Install Visual Studio Code on your development machine.
2. Once the installation is finished, select View > Extensions.
3. Search for Azure IoT Tools, which is actually a collection of extensions that help you interact with IoT Hub
and IoT devices, as well as developing IoT Edge modules.
4. Select Install. Each included extension installs individually.
5. When the extensions are done installing, open the command palette by selecting View > Command
Palette.
6. In the command palette, search for and select Azure: Sign in. Follow the prompts to sign in to your Azure
account.
7. In the command palette again, search for and select Azure IoT Hub: Select IoT Hub. Follow the prompts
to select your Azure subscription and IoT hub.
8. Open the explorer section of Visual Studio Code by either selecting the icon in the activity bar on the left,
or by selecting View > Explorer.
9. At the bottom of the explorer section, expand the collapsed Azure IoT Hub Devices menu. You should
see the devices and IoT Edge devices associated with the IoT hub that you selected through the command
palette.
Create a container registry
In this tutorial, you use the Azure IoT Tools extension to build a module and create a container image from the
files. Then you push this image to a registry that stores and manages your images. Finally, you deploy your
image from your registry to run on your IoT Edge device.
You can use any Docker-compatible registry to hold your container images. Two popular Docker registry services
are Azure Container Registry and Docker Hub. This tutorial uses Azure Container Registry.
If you don't already have a container registry, follow these steps to create a new one in Azure:
1. In the Azure portal, select Create a resource > Containers > Container Registry.
2. Provide the following values to create your container registry:

FIELD VALUE

Registry name Provide a unique name.

Subscription Select a subscription from the drop-down list.

Resource group We recommend that you use the same resource group
for all of the test resources that you create during the IoT
Edge quickstarts and tutorials. For example,
IoTEdgeResources.

Location Choose a location close to you.

Admin user Set to Enable.

SKU Select Basic.

3. Select Create.
4. After your container registry is created, browse to it, and then select Access keys.
5. Copy the values for Login server, Username, and Password and save them somewhere convenient. You
use these values throughout this tutorial to provide access to the container registry.

Create a new module project


The Azure IoT Tools extension provides project templates for all supported IoT Edge module languages in Visual
Studio Code. These templates have all the files and code that you need to deploy a working module to test IoT
Edge, or give you a starting point to customize the template with your own business logic.
For this tutorial, we use the C# module template because it is the most commonly used template.
Create a project template
In the Visual Studio Code command palette, search for and select Azure IoT Edge: New IoT Edge Solution.
Follow the prompts and use the following values to create your solution:

FIELD VALUE

Select folder Choose the location on your development machine for VS


Code to create the solution files.

Provide a solution name Enter a descriptive name for your solution or accept the
default EdgeSolution.

Select module template Choose C# Module.

Provide a module name Accept the default SampleModule.


FIELD VALUE

Provide Docker image repository for the module An image repository includes the name of your container
registry and the name of your container image. Your
container image is prepopulated from the name you provided
in the last step. Replace localhost:5000 with the login server
value from your Azure container registry. You can retrieve the
login server from the Overview page of your container
registry in the Azure portal.

The final image repository looks like <registry


name>.azurecr.io/samplemodule.

Once your new solution loads in the Visual Studio Code window, take a moment to familiarize yourself with the
files that it created:
The .vscode folder contains a file called launch.json, which is used for debugging modules.
The modules folder contains a folder for each module in your solution. Right now, that should only be
SampleModule, or whatever name you gave to the module. The SampleModule folder contains the main
program code, the module metadata, and several Docker files.
The .env file holds the credentials to your container registry. These credentials are shared with your IoT
Edge device so that it has access to pull the container images.
The deployment.debug.template.json file and deployment.template.json file are templates that help
you create a deployment manifest. A deployment manifest is a file that defines exactly which modules you
want deployed on a device, how they should be configured, and how they can communicate with each
other and the cloud. The template files use pointers for some values. When you transform the template
into a true deployment manifest, the pointers are replaced with values taken from other solution files.
Locate the two common placeholders in your deployment template:
In the registry credentials section, the address is autofilled from the information you provided when you
created the solution. However, the username and password reference the variables stored in the .env
file. This is for security, as the .env file is git ignored, but the deployment template is not.
In the SampleModule section, the container image isn't filled in even though you provided the image
repository when you created the solution. This placeholder points to the module.json file inside the
SampleModule folder. If you go to that file, you'll see that the image field does contain the repository,
but also a tag value that is made up of the version and the platform of the container. You can iterate the
version manually as part of your development cycle, and you select the container platform using a
switcher that we introduce later in this section.
Provide your registry credentials to the IoT Edge agent
The environment file stores the credentials for your container registry and shares them with the IoT Edge
runtime. The runtime needs these credentials to pull your container images onto the IoT Edge device.
The IoT Edge extension tries to pull your container registry credentials from Azure and populate them in the
environment file. Check to see if your credentials are already included. If not, add them now:
1. Open the .env file in your module solution.
2. Add the username and password values that you copied from your Azure container registry.
3. Save your changes to the .env file.
Select your target architecture
Currently, Visual Studio Code can develop C# modules for Linux AMD64 and ARM32v7 devices. You need to
select which architecture you're targeting with each solution, because that affects how the container is built and
runs. The default is Linux AMD64.
1. Open the command palette and search for Azure IoT Edge: Set Default Target Platform for Edge
Solution, or select the shortcut icon in the side bar at the bottom of the window.

2. In the command palette, select the target architecture from the list of options. For this tutorial, we're using
an Ubuntu virtual machine as the IoT Edge device, so will keep the default amd64.
Review the sample code
The solution template that you created includes sample code for an IoT Edge module. This sample module simply
receives messages and then passes them on. The pipeline functionality demonstrates an important concept in IoT
Edge, which is how modules communicate with each other.
Each module can have multiple input and output queues declared in their code. The IoT Edge hub running on the
device routes messages from the output of one module into the input of one or more modules. The specific
language for declaring inputs and outputs varies between languages, but the concept is the same across all
modules. For more information about routing between modules, see Declare routes.
The sample C# code that comes with the project template uses the ModuleClient Class from the IoT Hub SDK for
.NET.
1. Open the Program.cs file, which is inside the modules/SampleModule/ folder.
2. In program.cs, find the SetInputMessageHandlerAsync method.
3. The SetInputMessageHandlerAsync method sets up an input queue to receive incoming messages. Review
this method and see how it initializes an input queue called input1.
4. Next, find the SendEventAsync method.
5. The SendEventAsync method processes received messages and sets up an output queue to pass them
along. Review this method and see that it initializes an output queue called output1.

6. Open the deployment.template.json file.


7. Find the modules property of the $edgeAgent desired properties.
There should be two modules listed here. The first is SimulatedTemperatureSensor, which is included in
all the templates by default to provide simulated temperature data that you can use to test your modules.
The second is the SampleModule module that you created as part of this solution.
8. At the bottom of the file, find the desired properties for the $edgeHub module.
One of the functions of the IoT Edge hub module is to route messages between all the modules in a
deployment. Review the values in the routes property. The first route, SampleModuleToIoTHub, uses a
wildcard character (*) to indicate any messages coming from any output queues in the SampleModule
module. These messages go into $upstream, which is a reserved name that indicates IoT Hub. The second
route, sensorToSampleModule, takes messages coming from the SimulatedTemperatureSensor module
and routes them to the input1 input queue that you saw initialized in the SampleModule code.

Build and push your solution


You've reviewed the module code and the deployment template to understand some key deployment concepts.
Now, you're ready to build the SampleModule container image and push it to your container registry. With the
IoT tools extension for Visual Studio Code, this step also generates the deployment manifest based on the
information in the template file and the module information from the solution files.
Sign in to Docker
Provide your container registry credentials to Docker so that it can push your container image to be stored in the
registry.
1. Open the Visual Studio Code integrated terminal by selecting View > Terminal.
2. Sign in to Docker with the Azure container registry credentials that you saved after creating the registry.

docker login -u <ACR username> -p <ACR password> <ACR login server>

You may receive a security warning recommending the use of --password-stdin . While that best practice is
recommended for production scenarios, it's outside the scope of this tutorial. For more information, see the
docker login reference.
Build and push
Visual Studio Code now has access to your container registry, so it's time to turn the solution code into a
container image.
1. In the Visual Studio Code explorer, right-click the deployment.template.json file and select Build and
Push IoT Edge Solution.

The build and push command starts three operations. First, it creates a new folder in the solution called
config that holds the full deployment manifest, built out of information in the deployment template and
other solution files. Second, it runs docker build to build the container image based on the appropriate
dockerfile for your target architecture. Then, it runs docker push to push the image repository to your
container registry.
This process may take several minutes the first time, but is faster the next time that you run the commands.
2. Open the deployment.amd64.json file in newly created config folder. The filename reflects the target
architecture, so it will be different if you chose a different architecture.
3. Notice that the two parameters that had placeholders now are filled in with their proper values. The
registryCredentials section has your registry username and password pulled from the .env file. The
SampleModule has the full image repository with the name, version, and architecture tag from the
module.json file.
4. Open the module.json file in the SampleModule folder.
5. Change the version number for the module image. (The version, not the $schema-version.) For example,
increment the patch version number to 0.0.2 as though we had made a small fix in the module code.

TIP
Module versions enable version control, and allow you to test changes on a small set of devices before deploying
updates to production. If you don't increment the module version before building and pushing, then you overwrite
the repository in your container registry.

6. Save your changes to the module.json file.


7. Right-click the deployment.template.json file again, and again select Build and Push IoT Edge
Solution.
8. Open the deployment.amd64.json file again. Notice that a new file wasn't created when you ran the
build and push command again. Rather, the same file was updated to reflect the changes. The
SampleModule image now points to the 0.0.2 version of the container.
9. To further verify what the build and push command did, go to the Azure portal and navigate to your
container registry.
10. In your container registry, select Repositories then samplemodule. Verify that both versions of the image
were pushed to the registry.

Troubleshoot
If you encounter errors when building and pushing your module image, it often has to do with Docker
configuration on your development machine. Use the following checks to review your configuration:
Did you run the docker login command using the credentials that you copied from your container registry?
These credentials are different than the ones that you use to sign in to Azure.
Is your container repository correct? Does it have your correct container registry name and your correct
module name? Open the module.json file in the SampleModule folder to check. The repository value should
look like <registry name>.azurecr.io/samplemodule.
If you used a different name than SampleModule for your module, is that name consistent throughout the
solution?
Is your machine running the same type of containers that you're building? This tutorial is for Linux IoT Edge
devices, so Visual Studio Code should say amd64 or arm32v7 in the side bar, and Docker Desktop should be
running Linux containers.

Deploy modules to device


You verified that the built container images are stored in your container registry, so it's time to deploy them to a
device. Make sure that your IoT Edge device is up and running.
1. In the Visual Studio Code explorer, expand the Azure IoT Hub Devices section.
2. Right-click the IoT Edge device that you want to deploy to, then select Create Deployment for Single
Device.

3. In the file explorer, navigate into the config folder then select the deployment.amd64.json file.
Do not use the deployment.template.json file, which doesn't have the container registry credentials or
module image values in it. If you're targeting a Linux ARM32 device, the deployment manifest will be
named deployment.arm32v7.json.
4. Expand the details for your IoT Edge device, then expand the Modules list for your device.
5. Use the refresh button to update the device view until you see the SimulatedTemperatureSensor and
SampleModule modules running on your device.
It may take a few minutes for both modules to start. The IoT Edge runtime needs to receive its new
deployment manifest, pull down the module images from the container runtime, then start each new
module.

View messages from device


The SampleModule code receives messages through its input queue and passes them along through its output
queue. The deployment manifest declared routes that passed messages to SampleModule from
SimulatedTemperatureSensor, and then forwarded messages from SampleModule to IoT Hub. The Azure IoT
tools for Visual Studio Code allow you to see messages as they arrive at IoT Hub from your individual devices.
1. In the Visual Studio Code explorer, right-click the IoT Edge device that you want to monitor, then select
Start Monitoring Built-in Event Endpoint.
2. Watch the output window in Visual Studio Code to see messages arriving at your IoT hub.
View changes on device
If you want to see what's happening on your device itself, use the commands in this section to inspect the IoT
Edge runtime and modules running on your device.
The commands in this section are for your IoT Edge device, not your development machine. If you're using a
virtual machine for your IoT Edge device, connect to it now. In Azure, go to the virtual machine's overview page
and select Connect to access the secure shell connection.
View all modules deployed to your device, and check their status:

iotedge list

You should see four modules: the two IoT Edge runtime modules, SimulatedTemperatureSensor, and
SampleModule. All four should be listed as running.
Inspect the logs for a specific module:

iotedge logs <module name>

IoT Edge modules are case-sensitive.


The SimulatedTemperatureSensor and SampleModule logs should show the messages they're processing.
The edgeAgent module is responsible for starting the other modules, so its logs will have information
about implementing the deployment manifest. If any module isn't listed or isn't running, the edgeAgent
logs will probably have the errors. The edgeHub module is responsible for communications between the
modules and IoT Hub. If the modules are up and running, but the messages aren't arriving at your IoT hub,
the edgeHub logs will probably have the errors.

Next steps
In this tutorial, you set up Visual Studio Code on your development machine and deployed your first IoT Edge
module from it. Now that you know the basic concepts, try adding functionality to a module so that it can analyze
the data passing through it. Choose your preferred language:
C C# Java Node.js Python
Tutorial: Develop IoT Edge modules for Windows
devices
12/2/2019 • 17 minutes to read • Edit Online

Use Visual Studio to develop and deploy code to Windows devices running IoT Edge.
In the quickstart, you created an IoT Edge device using a Windows virtual machine and deployed a pre-built
module from the Azure Marketplace. This tutorial walks through what it takes to develop and deploy your own
code to an IoT Edge device. This tutorial is a useful prerequisite for the other tutorials, which go into more detail
about specific programming languages or Azure services.
This tutorial uses the example of deploying a C# module to a Windows device. This example was chosen
because it's the most common development scenario. If you're interested in developing in a different language, or
plan on deploying Azure services as modules, this tutorial will still be helpful to learn about the development tools.
Once you understand the development concepts, then you can choose your preferred language or Azure service to
dive into the details.
In this tutorial, you learn how to:
Set up your development machine.
Use the IoT Edge tools for Visual Studio to create a new project.
Build your project as a container and store it in an Azure container registry.
Deploy your code to an IoT Edge device.
If you don't have an Azure subscription, create a free account before you begin.

Key concepts
This tutorial walks through the development of an IoT Edge module. An IoT Edge module, or sometimes just
module for short, is a container that contains executable code. You can deploy one or more modules to an IoT
Edge device. Modules perform specific tasks like ingesting data from sensors, performing data analytics or data
cleaning operations, or sending messages to an IoT hub. For more information, see Understand Azure IoT Edge
modules.
When developing IoT Edge modules, it's important to understand the difference between the development
machine and the target IoT Edge device where the module will eventually be deployed. The container that you
build to hold your module code must match the operating system (OS ) of the target device. For Windows
container development, this concept is simpler because Windows containers only run on Windows operating
systems. But you could, for example, use your Windows development machine to build modules for Linux IoT
Edge devices. In that scenario, you'd have to make sure that your development machine was running Linux
containers. As you go through this tutorial, keep in mind the difference between development machine OS and the
container OS.
This tutorial targets Windows devices running IoT Edge. Windows IoT Edge devices use Windows containers. We
recommend using Visual Studio to develop for Windows devices, so that's what this tutorial will use. You can use
Visual Studio Code as well, although there are differences in support between the two tools.
The following table lists the supported development scenarios for Windows containers in Visual Studio Code
and Visual Studio.
VISUAL STUDIO CODE VISUAL STUDIO 2017/2019

Azure services Azure Functions


Azure Stream Analytics

Languages C# (debugging not supported) C


C#

More information Azure IoT Edge for Visual Studio Code Azure IoT Edge Tools for Visual Studio
2017
Azure IoT Edge Tools for Visual Studio
2019

Prerequisites
A development machine:
Windows 10 with 1809 update or newer.
You can use your own computer or a virtual machine, depending on your development preferences.
Make sure that your development machine supports nested virtualization. This capability is necessary
for running a container engine, which you install in the next section.
Install Git.
An Azure IoT Edge device on Windows:
We recommend that you don't run IoT Edge on your development machine, but instead use a separate device.
This distinction between development machine and IoT Edge device more accurately mirrors a true
deployment scenario, and helps to keep the different concepts straight.
If you don't have a second device available, use the quickstart article to create an IoT Edge device in Azure with
a Windows virtual machine.
Cloud resources:
A free or standard-tier IoT hub in Azure.

Install container engine


IoT Edge modules are packaged as containers, so you need a container engine on your development machine to
build and manage the containers. We recommend using Docker Desktop for development because of its many
features and popularity as a container engine. With Docker Desktop on a Windows computer, you can switch
between Linux containers and Windows containers so that you can easily develop modules for different types of
IoT Edge devices.
Use the Docker documentation to install on your development machine:
Install Docker Desktop for Windows
When you install Docker Desktop for Windows, you're asked whether you want to use Linux or
Windows containers. For this tutorial, use Windows containers. For more information, see Switch
between Windows and Linux containers.

Set up Visual Studio and tools


The IoT extensions for Visual Studio help you to develop IoT Edge modules. These extensions provide project
templates, automate the creation of the deployment manifest, and allow you to monitor and manage IoT Edge
devices. In this section, you install Visual Studio and the IoT Edge extension, then set up your Azure account to
manage IoT Hub resources from within Visual Studio.
This tutorial teaches the development steps for Visual Studio 2019. If you are using Visual Studio 2017 (version
15.7 or higher), the steps are very similar. If you would rather use Visual Studio Code, refer to the instructions in
Use Visual Studio Code to develop and debug modules for Azure IoT Edge.
1. Prepare Visual Studio 2019 on your development machine.
If you don't already have Visual Studio on your development machine, Install Visual Studio 2019
with the following workloads:
Azure development
Desktop development with C++
.NET Core cross-platform development
If you do already have Visual Studio 2019 on your development machine, follow the steps in Modify
Visual Studio to add the required workloads.
2. Download and install the Azure IoT Edge Tools extension for Visual Studio 2019.
If you are using Visual Studio 2017 (version 15.7 or higher), download and install the Azure IoT Edge Tools
for Visual Studio 2017.
3. When your installations are complete, open Visual Studio 2019 and select Continue without code.
4. Select View > Cloud Explorer.
5. Select the profile icon in the cloud explorer and sign in to your Azure account if you aren't signed in already.
6. Once you sign in, your Azure subscriptions are listed. Expand the subscription that has your IoT hub.
7. Under your subscription, expand IoT Hubs then your IoT hub. You should see a list of your IoT devices, and
can use this explorer to manage them.

Create a container registry


In this tutorial, you use the Azure IoT Tools extension to build a module and create a container image from the
files. Then you push this image to a registry that stores and manages your images. Finally, you deploy your image
from your registry to run on your IoT Edge device.
You can use any Docker-compatible registry to hold your container images. Two popular Docker registry services
are Azure Container Registry and Docker Hub. This tutorial uses Azure Container Registry.
If you don't already have a container registry, follow these steps to create a new one in Azure:
1. In the Azure portal, select Create a resource > Containers > Container Registry.
2. Provide the following values to create your container registry:

FIELD VALUE

Registry name Provide a unique name.

Subscription Select a subscription from the drop-down list.

Resource group We recommend that you use the same resource group for
all of the test resources that you create during the IoT
Edge quickstarts and tutorials. For example,
IoTEdgeResources.

Location Choose a location close to you.

Admin user Set to Enable.

SKU Select Basic.

3. Select Create.
4. After your container registry is created, browse to it, and then select Access keys.
5. Copy the values for Login server, Username, and Password and save them somewhere convenient. You
use these values throughout this tutorial to provide access to the container registry.

Create a new module project


The Azure IoT Edge Tools extension provides project templates for all supported IoT Edge module languages in
Visual Studio. These templates have all the files and code that you need to deploy a working module to test IoT
Edge, or give you a starting point to customize the template with your own business logic.
1. Select File > New > Project...
2. In the new project window, search for IoT Edge and choose the Azure IoT Edge (Windows amd64)
project. Click Next.

3. In the configure your new project window, rename the project and solution to something descriptive like
CSharpTutorialApp. Click Create to create the project.

4. In the Add Module window, configure your project with the following values:
FIELD VALUE

Visual Studio Template Select C# Module.

Module Name Accept the default IotEdgeModule1.

Repository Url An image repository includes the name of your container


registry and the name of your container image. Your
container image is prepopulated from the module project
name value. Replace localhost:5000 with the login server
value from your Azure container registry. You can retrieve
the Login server value from the Overview page of your
container registry in the Azure portal.

The final image repository looks like <registry


name>.azurecr.io/iotedgemodule1.

5. Select Add to create the module.


Once your new project loads in the Visual Studio window, take a moment to familiarize yourself with the files that
it created:
An IoT Edge project called CSharpTutorialApp.
The Modules folder contains pointers to the modules included in the project. In this case, it should be
just IotEdgeModule1.
The hidden .env file holds the credentials to your container registry. These credentials are shared with
your IoT Edge device so that it has access to pull the container images.
The deployment.template.json file is a template to help you create a deployment manifest. A
deployment manifest is a file that defines exactly which modules you want deployed on a device, how
they should be configured, and how they can communicate with each other and the cloud.
TIP
In the registry credentials section, the address is autofilled from the information you provided when you
created the solution. However, the username and password reference variables stored in the .env file. This is
for security, as the .env file is git ignored, but the deployment template is not.

An IoT Edge module project called IotEdgeModule1.


The program.cs file contains the default C# module code that comes with the project template. The
default module takes input from a source and passes it along to IoT Hub.
The module.json file hold details about the module, including the full image repository, image version,
and which Dockerfile to use for each supported platform.
Provide your registry credentials to the IoT Edge agent
The IoT Edge runtime needs your registry credentials to pull your container images onto the IoT Edge device. The
IoT Edge extension tries to pull your container registry information from Azure and populate it in the deployment
template.
1. Open the deployment.template.json file in your module solution.
2. Find the registryCredentials property in the $edgeAgent desired properties and ensure it contains the
correct information.

"registryCredentials": {
"<registry name>": {
"username": "$CONTAINER_REGISTRY_USERNAME_<registry name>",
"password": "$CONTAINER_REGISTRY_PASSWORD_<registry name>",
"address": "<registry name>.azurecr.io"
}
}

3. Open the .env file in your module solution. (It's hidden by default in the Solution Explorer, so you might
need to select the Show All Files button to display it.)
4. Add the Username and Password values that you copied from your Azure container registry.
5. Save your changes to the .env file.
Review the sample code
The solution template that you created includes sample code for an IoT Edge module. This sample module simply
receives messages and then passes them on. The pipeline functionality demonstrates an important concept in IoT
Edge, which is how modules communicate with each other.
Each module can have multiple input and output queues declared in their code. The IoT Edge hub running on the
device routes messages from the output of one module into the input of one or more modules. The specific
language for declaring inputs and outputs varies between languages, but the concept is the same across all
modules. For more information about routing between modules, see Declare routes.
The sample C# code that comes with the project template uses the ModuleClient Class from the IoT Hub SDK for
.NET.
1. In the program.cs file, find the SetInputMessageHandlerAsync method.
2. The SetInputMessageHandlerAsync method sets up an input queue to receive incoming messages. Review
this method and see how it initializes an input queue called input1.
3. Next, find the SendEventAsync method.
4. The SendEventAsync method processes received messages and sets up an output queue to pass them
along. Review this method and see that it initializes an output queue called output1.

5. Open the deployment.template.json file.


6. Find the modules property of the $edgeAgent desired properties.
There should be two modules listed here. The first is SimulatedTemperatureSensor, which is included in
all the templates by default to provide simulated temperature data that you can use to test your modules.
The second is the IotEdgeModule1 module that you created as part of this project.
This modules property declares which modules should be included in the deployment to your device or
devices.
7. Find the routes property of the $edgeHub desired properties.
One of the functions of the IoT Edge hub module is to route messages between all the modules in a
deployment. Review the values in the routes property. The first route, IotEdgeModule1ToIoTHub, uses a
wildcard character (*) to include any message coming from any output queue in the IotEdgeModule1
module. These messages go into $upstream, which is a reserved name that indicates IoT Hub. The second
route, sensorToIotEdgeModule1, takes messages coming from the SimulatedTemperatureSensor module
and routes them to the input1 input queue of the IotEdgeModule1 module.

Build and push your solution


You've reviewed the module code and the deployment template to understand some key deployment concepts.
Now, you're ready to build the IotEdgeModule1 container image and push it to your container registry. With the
IoT tools extension for Visual Studio, this step also generates the deployment manifest based on the information in
the template file and the module information from the solution files.
Sign in to Docker
Provide your container registry credentials to Docker on your development machine so that it can push your
container image to be stored in the registry.
1. Open PowerShell or a command prompt.
2. Sign in to Docker with the Azure container registry credentials that you saved after creating the registry.

docker login -u <ACR username> -p <ACR password> <ACR login server>

You may receive a security warning recommending the use of --password-stdin . While that best practice is
recommended for production scenarios, it's outside the scope of this tutorial. For more information, see the
docker login reference.
Build and push
Your development machine now has access to your container registry, and your IoT Edge devices will too. It's time
to turn the project code into a container image.
1. Right-click the CSharpTutorialApp project folder and select Build and Push IoT Edge Modules.

The build and push command starts three operations. First, it creates a new folder in the solution called
config that holds the full deployment manifest, built out of information in the deployment template and
other solution files. Second, it runs docker build to build the container image based on the appropriate
dockerfile for your target architecture. Then, it runs docker push to push the image repository to your
container registry.
This process may take several minutes the first time, but is faster the next time that you run the commands.
2. Open the deployment.windows-amd64.json file in the newly created config folder. (The config folder
may not appear in the Solution Explorer in Visual Studio. If that's the case, select the Show all files icon in
the Solution Explorer taskbar.)
3. Find the image parameter of the IotEdgeModule1 section. Notice that the image contains the full image
repository with the name, version, and architecture tag from the module.json file.
4. Open the module.json file in the IotEdgeModule1 folder.
5. Change the version number for the module image. (The version, not the $schema-version.) For example,
increment the patch version number to 0.0.2 as though we had made a small fix in the module code.
TIP
Module versions enable version control, and allow you to test changes on a small set of devices before deploying
updates to production. If you don't increment the module version before building and pushing, then you overwrite
the repository in your container registry.

6. Save your changes to the module.json file.


7. Right-click the CSharpTutorialApp project folder again, and select Build and Push IoT Edge modules
again.
8. Open the deployment.windows-amd64.json file again. Notice that a new file wasn't created when you
ran the build and push command again. Rather, the same file was updated to reflect the changes. The
IotEdgeModule1 image now points to the 0.0.2 version of the container. This change in the deployment
manifest is how you tell the IoT Edge device that there's a new version of a module to pull.
9. To further verify what the build and push command did, go to the Azure portal and navigate to your
container registry.
10. In your container registry, select Repositories then iotedgemodule1. Verify that both versions of the
image were pushed to the registry.

Troubleshoot
If you encounter errors when building and pushing your module image, it often has to do with Docker
configuration on your development machine. Use the following checks to review your configuration:
Did you run the docker login command using the credentials that you copied from your container registry?
These credentials are different than the ones that you use to sign in to Azure.
Is your container repository correct? Does it have your correct container registry name and your correct
module name? Open the module.json file in the IotEdgeModule1 folder to check. The repository value should
look like <registry name>.azurecr.io/iotedgemodule1.
If you used a different name than IotEdgeModule1 for your module, is that name consistent throughout the
solution?
Is your machine running the same type of containers that you're building? This tutorial is for Windows IoT
Edge devices, so your Visual Studio files should have the windows-amd64 extension, and Docker Desktop
should be running Windows containers.

Deploy modules to device


You verified that the built container images are stored in your container registry, so it's time to deploy them to a
device. Make sure that your IoT Edge device is up and running.
1. Open the Cloud Explorer in Visual Studio and expand the details for your IoT hub.
2. Select the name of the device that you want to deploy to. In the Actions list, select Create Deployment.

3. In the file explorer, navigate to the config folder of your project and select the deployment.windows-
amd64.json file. This file is often located at
C:\Users\<username>\source\repos\CSharpTutorialApp\CSharpTutorialApp\config\deployment.windows-
amd64.json

Do not use the deployment.template.json file, which doesn't have the full module image values in it.
4. Expand the details for your IoT Edge device in the Cloud Explorer to see the modules on your device.
5. Use the Refresh button to update the device status to see that the SimulatedTemperatureSensor and
IotEdgeModule1 modules are deployed your device.
View messages from device
The IotEdgeModule1 code receives messages through its input queue and passes them along through its output
queue. The deployment manifest declared routes that passed messages from SimulatedTemperatureSensor to
IotEdgeModule1, and then forwarded messages from IotEdgeModule1 to IoT Hub. The Azure IoT Edge tools for
Visual Studio allow you to see messages as they arrive at IoT Hub from your individual devices.
1. In the Visual Studio cloud explorer, select the name of the IoT Edge device that you deployed to.
2. In the Actions menu, select Start Monitoring Built-in Event Endpoint.
3. Watch the Output section in Visual Studio to see messages arriving at your IoT hub.
It may take a few minutes for both modules to start. The IoT Edge runtime needs to receive its new
deployment manifest, pull down the module images from the container runtime, then start each new
module.
View changes on device
If you want to see what's happening on your device itself, use the commands in this section to inspect the IoT Edge
runtime and modules running on your device.
The commands in this section are for your IoT Edge device, not your development machine. If you're using a
virtual machine for your IoT Edge device, connect to it now. In Azure, go to the virtual machine's overview page
and select Connect to access the remote desktop connection. On the device, open a command or PowerShell
window to run the iotedge commands.
View all modules deployed to your device, and check their status:

iotedge list

You should see four modules: the two IoT Edge runtime modules, SimulatedTemperatureSensor, and
IotEdgeModule1. All four should be listed as running.
Inspect the logs for a specific module:

iotedge logs <module name>

IoT Edge modules are case-sensitive.


The SimulatedTemperatureSensor and IotEdgeModule1 logs should show the messages they're processing.
The edgeAgent module is responsible for starting the other modules, so its logs will have information about
implementing the deployment manifest. If any module isn't listed or isn't running, the edgeAgent logs will
probably have the errors. The edgeHub module is responsible for communications between the modules
and IoT Hub. If the modules are up and running, but the messages aren't arriving at your IoT hub, the
edgeHub logs will probably have the errors.

Next steps
In this tutorial, you set up Visual Studio 2019 on your development machine and deployed your first IoT Edge
module from it. Now that you know the basic concepts, try adding functionality to a module so that it can analyze
the data passing through it. Choose your preferred language:
C C#
Tutorial: Develop a C IoT Edge module for Linux
devices
11/27/2019 • 12 minutes to read • Edit Online

Use Visual Studio Code to develop C code and deploy it to a Linux device running Azure 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. In this
tutorial, you learn how to:
Use Visual Studio Code to create an IoT Edge module in C
Use Visual Studio Code and Docker to create a docker image and publish it to a container 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. It only
sends messages upstream if the temperature is above a specified threshold. This type of analysis at the edge is
useful for reducing the amount of data communicated to and stored in the cloud.
If you don't have an Azure subscription, create a free account before you begin.

Solution scope
This tutorial demonstrates how to develop a module in C using Visual Studio Code, and how to deploy it to a
Linux device. If you're developing modules for Windows devices, go to Develop a C IoT Edge module for
Windows devices instead.
Use the following table to understand your options for developing and deploying C modules to Linux:

C VISUAL STUDIO CODE VISUAL STUDIO

Linux AMD64

Linux ARM32

Prerequisites
Before beginning this tutorial, you should have gone through the previous tutorial to set up your development
environment for Linux container development: Develop IoT Edge modules for Linux devices. By completing that
tutorial, you should have the following prerequisites in place:
A free or standard-tier IoT Hub in Azure.
A Linux device running Azure IoT Edge
A container registry, like Azure Container Registry.
Visual Studio Code configured with the Azure IoT Tools.
Docker CE configured to run Linux containers.
To develop an IoT Edge module in C, install the following additional prerequisites on your development machine:
C/C++ extension for Visual Studio Code.
Create a module project
The following steps create an IoT Edge module project for C by using Visual Studio Code and the Azure IoT Tools
extension. Once you have a project template created, add new code so that the module filters out messages based
on their reported properties.
Create a new project
Create a C solution template that you can customize with your own code.
1. Select View > Command Palette to open the VS Code command palette.
2. In the command palette, type and run the command Azure: Sign in and follow the instructions to sign in
your Azure account. If you've already signed in, you can skip this step.
3. In the command palette, type and run the command Azure IoT Edge: New IoT Edge solution. Follow the
prompts in the command palette to create your solution.

FIELD VALUE

Select folder Choose the location on your development machine for VS


Code to create the solution files.

Provide a solution name Enter a descriptive name for your solution or accept the
default EdgeSolution.

Select module template Choose C Module.

Provide a module name Name your module CModule.

Provide Docker image repository for the module An image repository includes the name of your container
registry and the name of your container image. Your
container image is prepopulated from the name you
provided in the last step. Replace localhost:5000 with the
login server value from your Azure container registry. You
can retrieve the login server from the Overview page of
your container registry in the Azure portal.

The final image repository looks like <registry


name>.azurecr.io/cmodule.

Add your registry credentials


The environment file stores the credentials for your container registry and shares them with the IoT Edge runtime.
The runtime needs these credentials to pull your private images onto the IoT Edge device.
1. In the VS Code explorer, open the .env file.
2. Update the fields with the username and password values that you copied from your Azure container registry.
3. Save this file.
Select your target architecture
Currently, Visual Studio Code can develop C modules for Linux AMD64 and Linux ARM32v7 devices. You need to
select which architecture you're targeting with each solution, because the container is built and run differently for
each architecture type. The default is Linux AMD64.
1. Open the command palette and search for Azure IoT Edge: Set Default Target Platform for Edge
Solution, or select the shortcut icon in the side bar at the bottom of the window.
2. In the command palette, select the target architecture from the list of options. For this tutorial, we're using
an Ubuntu virtual machine as the IoT Edge device, so will keep the default amd64.
Update the module with custom code
The default module code receives messages on an input queue and passes them along through an output queue.
Let's add some additional code so that the module processes the messages at the edge before forwarding them to
IoT Hub. Update the module so that it analyzes the temperature data in each message, and only sends the
message to IoT Hub if the temperature exceeds a certain threshold.
1. The data from the sensor in this scenario comes in JSON format. To filter messages in JSON format,
import a JSON library for C. This tutorial uses Parson.
a. Download the Parson GitHub repository. Copy the parson.c and parson.h files into the CModule
folder.
b. Open modules > CModule > CMakeLists.txt. At the top of the file, import the Parson files as a
library called my_parson.

add_library(my_parson
parson.c
parson.h
)

c. Add my_parson to the list of libraries in the target_link_libraries function of CMakeLists.txt.


d. Save the CMakeLists.txt file.
e. Open modules > CModule > main.c. At the bottom of the list of include statements, add a new
one to include parson.h for JSON support:

#include "parson.h"

2. In the main.c file, add a global variable called temperatureThreshold after the include section. This variable
sets the value that the measured temperature must exceed in order for the data to be sent to IoT Hub.

static double temperatureThreshold = 25;

3. Find the CreateMessageInstance function in main.c. Replace the inner if-else statement with the following
code that adds a few lines of functionality:
if ((messageInstance->messageHandle = IoTHubMessage_Clone(message)) == NULL)
{
free(messageInstance);
messageInstance = NULL;
}
else
{
messageInstance->messageTrackingId = messagesReceivedByInput1Queue;
MAP_HANDLE propMap = IoTHubMessage_Properties(messageInstance->messageHandle);
if (Map_AddOrUpdate(propMap, "MessageType", "Alert") != MAP_OK)
{
printf("ERROR: Map_AddOrUpdate Failed!\r\n");
}
}

The new lines of code in the else statement add a new property to the message, which labels the message
as an alert. This code labels all messages as alerts, because we'll add functionality that only sends messages
to IoT Hub if they report high temperatures.
4. Replace the entire InputQueue1Callback function with the following code. This function implements the
actual messaging filter. When a message is received, it checks whether the reported temperature exceeds
the threshold. If yes, then it forwards the message through its output queue. If not, then it ignores the
message.

static unsigned char *bytearray_to_str(const unsigned char *buffer, size_t len)


{
unsigned char *ret = (unsigned char *)malloc(len + 1);
memcpy(ret, buffer, len);
ret[len] = '\0';
return ret;
}

static IOTHUBMESSAGE_DISPOSITION_RESULT InputQueue1Callback(IOTHUB_MESSAGE_HANDLE message, void*


userContextCallback)
{
IOTHUBMESSAGE_DISPOSITION_RESULT result;
IOTHUB_CLIENT_RESULT clientResult;
IOTHUB_MODULE_CLIENT_LL_HANDLE iotHubModuleClientHandle =
(IOTHUB_MODULE_CLIENT_LL_HANDLE)userContextCallback;

unsigned const char* messageBody;


size_t contentSize;

if (IoTHubMessage_GetByteArray(message, &messageBody, &contentSize) == IOTHUB_MESSAGE_OK)


{
messageBody = bytearray_to_str(messageBody, contentSize);
} else
{
messageBody = "<null>";
}

printf("Received Message [%zu]\r\n Data: [%s]\r\n",


messagesReceivedByInput1Queue, messageBody);

// Check if the message reports temperatures higher than the threshold


JSON_Value *root_value = json_parse_string(messageBody);
JSON_Object *root_object = json_value_get_object(root_value);
double temperature;
if (json_object_dotget_value(root_object, "machine.temperature") != NULL && (temperature =
json_object_dotget_number(root_object, "machine.temperature")) > temperatureThreshold)
{
printf("Machine temperature %f exceeds threshold %f\r\n", temperature, temperatureThreshold);
// This message should be sent to next stop in the pipeline, namely "output1". What happens at
"outpu1" is determined
// by the configuration of the Edge routing table setup.
// by the configuration of the Edge routing table setup.
MESSAGE_INSTANCE *messageInstance = CreateMessageInstance(message);
if (NULL == messageInstance)
{
result = IOTHUBMESSAGE_ABANDONED;
}
else
{
printf("Sending message (%zu) to the next stage in pipeline\n",
messagesReceivedByInput1Queue);

clientResult = IoTHubModuleClient_LL_SendEventToOutputAsync(iotHubModuleClientHandle,
messageInstance->messageHandle, "output1", SendConfirmationCallback, (void *)messageInstance);
if (clientResult != IOTHUB_CLIENT_OK)
{
IoTHubMessage_Destroy(messageInstance->messageHandle);
free(messageInstance);
printf("IoTHubModuleClient_LL_SendEventToOutputAsync failed on sending msg#=%zu,
err=%d\n", messagesReceivedByInput1Queue, clientResult);
result = IOTHUBMESSAGE_ABANDONED;
}
else
{
result = IOTHUBMESSAGE_ACCEPTED;
}
}
}
else
{
printf("Not sending message (%zu) to the next stage in pipeline.\r\n",
messagesReceivedByInput1Queue);
result = IOTHUBMESSAGE_ACCEPTED;
}

messagesReceivedByInput1Queue++;
return result;
}

5. Add a moduleTwinCallback function. This method receives updates on the desired properties from the
module twin, and updates the temperatureThreshold variable to match. All modules have their own
module twin, which lets you configure the code running inside a module directly from the cloud.

static void moduleTwinCallback(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad,


size_t size, void* userContextCallback)
{
printf("\r\nTwin callback called with (state=%s, size=%zu):\r\n%s\r\n",
MU_ENUM_TO_STRING(DEVICE_TWIN_UPDATE_STATE, update_state), size, payLoad);
JSON_Value *root_value = json_parse_string(payLoad);
JSON_Object *root_object = json_value_get_object(root_value);
if (json_object_dotget_value(root_object, "desired.TemperatureThreshold") != NULL) {
temperatureThreshold = json_object_dotget_number(root_object, "desired.TemperatureThreshold");
}
if (json_object_get_value(root_object, "TemperatureThreshold") != NULL) {
temperatureThreshold = json_object_get_number(root_object, "TemperatureThreshold");
}
}

6. Find the SetupCallbacksForModule function. Replace the function with the following code that adds an else
if statement to check if the module twin has been updated.
static int SetupCallbacksForModule(IOTHUB_MODULE_CLIENT_LL_HANDLE iotHubModuleClientHandle)
{
int ret;

if (IoTHubModuleClient_LL_SetInputMessageCallback(iotHubModuleClientHandle, "input1",
InputQueue1Callback, (void*)iotHubModuleClientHandle) != IOTHUB_CLIENT_OK)
{
printf("ERROR:
IoTHubModuleClient_LL_SetInputMessageCallback(\"input1\")..........FAILED!\r\n");
ret = MU_FAILURE;
}
else if (IoTHubModuleClient_LL_SetModuleTwinCallback(iotHubModuleClientHandle, moduleTwinCallback,
(void*)iotHubModuleClientHandle) != IOTHUB_CLIENT_OK)
{
printf("ERROR: IoTHubModuleClient_LL_SetModuleTwinCallback(default)..........FAILED!\r\n");
ret = MU_FAILURE;
}
else
{
ret = 0;
}

return ret;
}

7. Save the main.c file.


8. In the VS Code explorer, open the deployment.template.json file in your IoT Edge solution workspace.
9. Add the CModule module twin to the deployment manifest. Insert the following JSON content at the
bottom of the moduleContent section, after the $edgeHub module twin:

"CModule": {
"properties.desired":{
"TemperatureThreshold":25
}
}
10. Save the deployment.template.json file.

Build and push your module


In the previous section, you created an IoT Edge solution and added code to the CModule that will filter out
messages where the reported machine temperature is within the acceptable limits. Now you need to build the
solution as a container image and push it to your container registry.
1. Open the VS Code terminal by selecting View > Terminal.
2. Sign in to Docker by entering the following command in the terminal. Sign in with the username, password,
and login server from your Azure container registry. You can retrieve these values from the Access keys
section of your registry in the Azure portal.

docker login -u <ACR username> -p <ACR password> <ACR login server>

You may receive a security warning recommending the use of --password-stdin . While that best practice is
recommended for production scenarios, it's outside the scope of this tutorial. For more information, see the
docker login reference.
3. In the VS Code explorer, right-click the deployment.template.json file and select Build and Push IoT
Edge solution.
The build and push command starts three operations. First, it creates a new folder in the solution called
config that holds the full deployment manifest, built out of information in the deployment template and
other solution files. Second, it runs docker build to build the container image based on the appropriate
dockerfile for your target architecture. Then, it runs docker push to push the image repository to your
container registry.

Deploy modules to device


Use the Visual Studio Code explorer and the Azure IoT Tools extension to deploy the module project to your IoT
Edge device. You already have a deployment manifest prepared for your scenario, the deployment.json file in the
config folder. All you need to do now is select a device to receive the deployment.
Make sure that your IoT Edge device is up and running.
1. In the Visual Studio Code explorer, expand the Azure IoT Hub Devices section to see your list of IoT
devices.
2. Right-click the name of your IoT Edge device, then select Create Deployment for Single Device.
3. Select the deployment.json file in the config folder and then click Select Edge Deployment Manifest.
Do not use the deployment.template.json file.
4. Click the refresh button. You should see the new CModule running along with the
SimulatedTemperatureSensor module and the $edgeAgent and $edgeHub.

View generated data


Once you apply the deployment manifest to your IoT Edge device, the IoT Edge runtime on the device collects the
new deployment information and starts executing on it. Any modules running on the device that aren't included in
the deployment manifest are stopped. Any modules missing from the device are started.
You can view the status of your IoT Edge device using the Azure IoT Hub Devices section of the Visual Studio
Code explorer. Expand the details of your device to see a list of deployed and running modules.
1. In the Visual Studio Code explorer, right-click the name of your IoT Edge device and select Start
Monitoring Built-in Event Endpoint.
2. View the messages arriving at your IoT Hub. It may take a while for the messages to arrive, because the IoT
Edge device has to receive its new deployment and start all the modules. Then, the changes we made to the
CModule code wait until the machine temperature reaches 25 degrees before sending messages. It also
adds the message type Alert to any messages that reach that temperature threshold.

Edit the module twin


We used the CModule module twin in the deployment manifest to set the temperature threshold at 25 degrees.
You can use the module twin to change the functionality without having to update the module code.
1. In Visual Studio Code, expand the details under your IoT Edge device to see the running modules.
2. Right-click CModule and select Edit module twin.
3. Find TemperatureThreshold in the desired properties. Change its value to a new temperature 5 degrees
to 10 degrees higher than the latest reported temperature.
4. Save the module twin file.
5. Right-click anywhere in the module twin editing pane and select Update module twin.
6. Monitor the incoming device-to-cloud messages. You should see the messages stop until the new
temperature threshold is reached.

Clean up resources
If you plan to continue to the next recommended article, you can keep the resources and configurations that you
created and reuse them. You can also keep using the same IoT Edge device as a test device.
Otherwise, you can delete the local configurations and the Azure resources that you used in this article to avoid
charges.
Delete Azure resources
Deleting Azure resources and resource groups is irreversible. Make sure that you don't accidentally delete the
wrong resource group or resources. If you created the IoT hub inside an existing resource group that has
resources that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.
To delete the resources:
1. Sign in to the Azure portal and select Resource groups.
2. Select the name of the resource group that contains your IoT Edge test resources.
3. Review the list of resources contained in your resource group. If you want to delete all of them, you can
select Delete resource group. If you want to delete only some of them, you can click into each resource to
delete them individually.

Next steps
In this tutorial, you created an IoT Edge module that contains code to filter raw data generated by your IoT Edge
device. When you're ready to build your own modules, you can learn more about developing your own IoT Edge
modules or how to develop modules with Visual Studio Code. For examples of IoT Edge modules, including the
simulated temperature module, see IoT Edge module samples and IoT C SDK samples.
You can continue on to the next tutorials to learn how Azure IoT Edge can help you deploy Azure cloud services to
process and analyze data at the edge.
Functions Stream Analytics Machine Learning Custom Vision Service
Tutorial: Develop a C IoT Edge module for Windows
devices
11/27/2019 • 12 minutes to read • Edit Online

Use Visual Studio to develop C code and deploy it to a Windows device running Azure IoT Edge.
You can use Azure 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. In this
tutorial, you learn how to:
Use Visual Studio to create an IoT Edge module that's based on the C SDK.
Use Visual Studio 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 that's generated by your device. It
only sends messages upstream if the temperature is above a specified threshold. This type of analysis at the edge
is useful for reducing the amount of data that's communicated to and stored in the cloud.
If you don't have an Azure subscription, create a free account before you begin.

Solution scope
This tutorial demonstrates how to develop a module in C using Visual Studio 2019, and how to deploy it to a
Windows device. If you're developing modules for Linux devices, go to Develop a C IoT Edge module for Linux
devices instead.
Use the following table to understand your options for developing and deploying C modules to Windows devices:

C VISUAL STUDIO CODE VISUAL STUDIO 2017/2019

Windows AMD64

Prerequisites
Before beginning this tutorial, you should have gone through the previous tutorial to set up your development
environment for Windows container development: Develop IoT Edge modules for Windows devices. After
completing that tutorial, you should have the following prerequisites in place:
A free or standard-tier IoT Hub in Azure.
A Windows device running Azure IoT Edge.
A container registry, like Azure Container Registry.
Visual Studio 2019 configured with the Azure IoT Edge Tools extension.
Docker Desktop configured to run Windows containers.
Install the Azure IoT C SDK for Windows x64 through vcpkg:
git clone https://github.com/Microsoft/vcpkg
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg install azure-iot-sdk-c:x64-windows
.\vcpkg --triplet x64-windows integrate install

TIP
If you are using Visual Studio 2017 (version 15.7 or higher), please download and install Azure IoT Edge Tools for VS 2017
from the Visual Studio marketplace

Create a module project


The following steps create an IoT Edge module project that's based on the C SDK by using Visual Studio and the
Azure IoT Edge Tools extension. Once you have a project template created, add new code so that the module filters
out messages based on their reported properties.
Create a new project
Create a C solution template that you can customize with your own code.
1. Launch Visual Studio 2019 and select Create New Project.
2. In the new project window, search IoT Edge project and choose the Azure IoT Edge (Windows amd64)
project. Click Next.

3. In the configure your new project window, rename the project and solution to something descriptive like
CTutorialApp. Click Create to create the project.
4. In the IoT Edge application and module window, configure your project with the following values:

FIELD VALUE

Select a template Select C Module.

Module project name Name your module CModule.

Docker image repository An image repository includes the name of your container
registry and the name of your container image. Your
container image is prepopulated from the module project
name value. Replace localhost:5000 with the login server
value from your Azure container registry. You can retrieve
the login server from the Overview page of your container
registry in the Azure portal.

The final image repository looks like <registry


name>.azurecr.io/cmodule.
5. Select Add to create the project.
Add your registry credentials
The deployment manifest shares the credentials for your container registry with the IoT Edge runtime. The
runtime needs these credentials to pull your private images onto the IoT Edge device. Use the credentials from the
Access keys section of your Azure container registry.
1. In the Visual Studio solution explorer, open the deployment.template.json file.
2. Find the registryCredentials property in the $edgeAgent desired properties.
3. Update the property with your credentials, following this format:

"registryCredentials": {
"<registry name>": {
"username": "<username>",
"password": "<password>",
"address": "<registry name>.azurecr.io"
}
}

4. Save the deployment.template.json file.


Update the module with custom code
The default module code receives messages on an input queue and passes them along through an output queue.
Let's add some additional code so that the module processes the messages at the edge before forwarding them to
IoT Hub. Update the module so that it analyzes the temperature data in each message, and only sends the
message to IoT Hub if the temperature exceeds a certain threshold.
1. The data from the sensor in this scenario comes in JSON format. To filter messages in JSON format,
import a JSON library for C. This tutorial uses Parson.
a. Download the Parson GitHub repository. Copy the parson.c and parson.h files into the CModule
project.
b. In Visual Studio, open the CMakeLists.txt file from the CModule project folder. At the top of the file,
import the Parson files as a library called my_parson.

add_library(my_parson
parson.c
parson.h
)

c. Add my_parson to the list of libraries in the target_link_libraries section of the CMakeLists.txt file.
d. Save the CMakeLists.txt file.
e. Open CModule > main.c. At the bottom of the list of include statements, add a new one to include
parson.h for JSON support:

#include "parson.h"

2. In the main.c file, add a global variable called temperatureThreshold next to the
messagesReceivedByInput1Queue variable. This variable sets the value that the measured temperature
must exceed in order for the data to be sent to IoT Hub.

static double temperatureThreshold = 25;

3. Find the CreateMessageInstance function in main.c. Replace the inner if-else statement with the following
code that adds a few lines of functionality:

if ((messageInstance->messageHandle = IoTHubMessage_Clone(message)) == NULL)


{
free(messageInstance);
messageInstance = NULL;
}
else
{
messageInstance->messageTrackingId = messagesReceivedByInput1Queue;
MAP_HANDLE propMap = IoTHubMessage_Properties(messageInstance->messageHandle);
if (Map_AddOrUpdate(propMap, "MessageType", "Alert") != MAP_OK)
{
printf("ERROR: Map_AddOrUpdate Failed!\r\n");
}
}

The new lines of code in the else statement add a new property to the message, which labels the message
as an alert. This code labels all messages as alerts, because we'll add functionality that only sends messages
to IoT Hub if they report high temperatures.
4. Find the InputQueue1Callback function, and replace the whole function with the following code. This
function implements the actual messaging filter. When a message is received, it checks whether the
reported temperature exceeds the threshold. If yes, then it forwards the message through its output queue.
If not, then it ignores the message.

static unsigned char *bytearray_to_str(const unsigned char *buffer, size_t len)


{
unsigned char *ret = (unsigned char *)malloc(len + 1);
memcpy(ret, buffer, len);
memcpy(ret, buffer, len);
ret[len] = '\0';
return ret;
}

static IOTHUBMESSAGE_DISPOSITION_RESULT InputQueue1Callback(IOTHUB_MESSAGE_HANDLE message, void*


userContextCallback)
{
IOTHUBMESSAGE_DISPOSITION_RESULT result;
IOTHUB_CLIENT_RESULT clientResult;
IOTHUB_MODULE_CLIENT_LL_HANDLE iotHubModuleClientHandle =
(IOTHUB_MODULE_CLIENT_LL_HANDLE)userContextCallback;

unsigned const char* messageBody;


size_t contentSize;

if (IoTHubMessage_GetByteArray(message, &messageBody, &contentSize) == IOTHUB_MESSAGE_OK)


{
messageBody = bytearray_to_str(messageBody, contentSize);
} else
{
messageBody = "<null>";
}

printf("Received Message [%zu]\r\n Data: [%s]\r\n",


messagesReceivedByInput1Queue, messageBody);

// Check if the message reports temperatures higher than the threshold


JSON_Value *root_value = json_parse_string(messageBody);
JSON_Object *root_object = json_value_get_object(root_value);
double temperature;

// If temperature exceeds threshold, send to output1


if (json_object_dotget_value(root_object, "machine.temperature") != NULL && (temperature =
json_object_dotget_number(root_object, "machine.temperature")) > temperatureThreshold)
{
printf("Machine temperature %f exceeds threshold %f\r\n", temperature, temperatureThreshold);
// This message should be sent to next stop in the pipeline, namely "output1". What happens at
"outpu1" is determined
// by the configuration of the Edge routing table setup.
MESSAGE_INSTANCE *messageInstance = CreateMessageInstance(message);
if (NULL == messageInstance)
{
result = IOTHUBMESSAGE_ABANDONED;
}
else
{
printf("Sending message (%zu) to the next stage in pipeline\n",
messagesReceivedByInput1Queue);

clientResult = IoTHubModuleClient_LL_SendEventToOutputAsync(iotHubModuleClientHandle,
messageInstance->messageHandle, "output1", SendConfirmationCallback, (void *)messageInstance);
if (clientResult != IOTHUB_CLIENT_OK)
{
IoTHubMessage_Destroy(messageInstance->messageHandle);
free(messageInstance);
printf("IoTHubModuleClient_LL_SendEventToOutputAsync failed on sending msg#=%zu,
err=%d\n", messagesReceivedByInput1Queue, clientResult);
result = IOTHUBMESSAGE_ABANDONED;
}
else
{
result = IOTHUBMESSAGE_ACCEPTED;
}
}
}
// If message does not exceed threshold, do not forward
else
{
printf("Not sending message (%zu) to the next stage in pipeline.\r\n",
printf("Not sending message (%zu) to the next stage in pipeline.\r\n",
messagesReceivedByInput1Queue);
result = IOTHUBMESSAGE_ACCEPTED;
}

messagesReceivedByInput1Queue++;
return result;
}

5. Add a moduleTwinCallback function. This method receives updates on the desired properties from the
module twin, and updates the temperatureThreshold variable to match. All modules have their own
module twin, which lets you configure the code running inside a module directly from the cloud.

static void moduleTwinCallback(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad,


size_t size, void* userContextCallback)
{
printf("\r\nTwin callback called with (state=%s, size=%zu):\r\n%s\r\n",
MU_ENUM_TO_STRING(DEVICE_TWIN_UPDATE_STATE, update_state), size, payLoad);
JSON_Value *root_value = json_parse_string(payLoad);
JSON_Object *root_object = json_value_get_object(root_value);
if (json_object_dotget_value(root_object, "desired.TemperatureThreshold") != NULL) {
temperatureThreshold = json_object_dotget_number(root_object, "desired.TemperatureThreshold");
}
if (json_object_get_value(root_object, "TemperatureThreshold") != NULL) {
temperatureThreshold = json_object_get_number(root_object, "TemperatureThreshold");
}
}

6. Find the SetupCallbacksForModule function. Replace the function with the following code that adds an else
if statement to check if the module twin has been updated.

static int SetupCallbacksForModule(IOTHUB_MODULE_CLIENT_LL_HANDLE iotHubModuleClientHandle)


{
int ret;

if (IoTHubModuleClient_LL_SetInputMessageCallback(iotHubModuleClientHandle, "input1",
InputQueue1Callback, (void*)iotHubModuleClientHandle) != IOTHUB_CLIENT_OK)
{
printf("ERROR:
IoTHubModuleClient_LL_SetInputMessageCallback(\"input1\")..........FAILED!\r\n");
ret = MU_FAILURE;
}
else if (IoTHubModuleClient_LL_SetModuleTwinCallback(iotHubModuleClientHandle, moduleTwinCallback,
(void*)iotHubModuleClientHandle) != IOTHUB_CLIENT_OK)
{
printf("ERROR: IoTHubModuleClient_LL_SetModuleTwinCallback(default)..........FAILED!\r\n");
ret = MU_FAILURE;
}
else
{
ret = 0;
}

return ret;
}

7. Save the main.c file.


8. Open the deployment.template.json file.
9. Add the CModule module twin to the deployment manifest. Insert the following JSON content at the
bottom of the moduleContent section, after the $edgeHub module twin:
"CModule": {
"properties.desired":{
"TemperatureThreshold":25
}
}

10. Save the deployment.template.json file.

Build and push your module


In the previous section, you created an IoT Edge solution and added code to the CModule to filter out messages
where the reported machine temperature is below the acceptable threshold. Now you need to build the solution as
a container image and push it to your container registry.
1. Use the following command to sign in to Docker on your development machine. Sign in with the username,
password, and login server from your Azure container registry. You can retrieve these values from the
Access keys section of your registry in the Azure portal.

docker login -u <ACR username> -p <ACR password> <ACR login server>

You may receive a security warning recommending the use of --password-stdin . While that best practice is
recommended for production scenarios, it's outside the scope of this tutorial. For more information, see the
docker login reference.
2. In the Visual Studio solution explorer, right-click the project name that you want to build. The default name
is AzureIotEdgeApp1 and since you're building a Windows module, the extension should be
Windows.Amd64.
3. Select Build and Push IoT Edge Modules.
The build and push command starts three operations. First, it creates a new folder in the solution called
config that holds the full deployment manifest, built out of information in the deployment template, and
other solution files. Second, it runs docker build to build the container image based on the appropriate
dockerfile for your target architecture. Then, it runs docker push to push the image repository to your
container registry.
Deploy modules to device
Use the Visual Studio cloud explorer and the Azure IoT Edge Tools extension to deploy the module project to your
IoT Edge device. You already have a deployment manifest prepared for your scenario, the deployment.json file in
the config folder. All you need to do now is select a device to receive the deployment.
Make sure that your IoT Edge device is up and running.
1. In the Visual Studio cloud explorer, expand the resources to see your list of IoT devices.
2. Right-click the name of the IoT Edge device that you want to receive the deployment.
3. Select Create Deployment.
4. In the file explorer, select the deployment.windows-amd64 file in the config folder of your solution.
5. Refresh the cloud explorer to see the deployed modules listed under your device.

View generated data


Once you apply the deployment manifest to your IoT Edge device, the IoT Edge runtime on the device collects the
new deployment information and starts executing on it. Any modules running on the device that aren't included in
the deployment manifest are stopped. Any modules missing from the device are started.
You can use the IoT Edge Tools extension to view messages as they arrive at your IoT Hub.
1. In the Visual Studio cloud explorer, select the name of your IoT Edge device.
2. In the Actions list, select Start Monitoring Built-in Event Endpoint.
3. View the messages arriving at your IoT Hub. It may take a while for the messages to arrive, because the IoT
Edge device has to receive its new deployment and start all the modules. Then, the changes we made to the
CModule code wait until the machine temperature reaches 25 degrees before sending messages. It also
adds the message type Alert to any messages that reach that temperature threshold.

Edit the module twin


We used the CModule module twin to set the temperature threshold at 25 degrees. You can use the module twin
to change the functionality without having to update the module code.
1. In Visual Studio, open the deployment.windows-amd64.json file. (Not the deployment.template file. If
you don't see the deployment manifest in the config file in the solution explorer, select the Show all files
icon in the explorer toolbar.)
2. Find the CModule twin and change the value of the temperatureThreshold parameter to a new
temperature 5 degrees to 10 degrees higher than the latest reported temperature.
3. Save the deployment.windows-amd64.json file.
4. Follow the deployment steps again to apply the updated deployment manifest to your device.
5. Monitor the incoming device-to-cloud messages. You should see the messages stop until the new
temperature threshold is reached.

Clean up resources
If you plan to continue to the next recommended article, you can keep the resources and configurations that you
created and reuse them. You can also keep using the same IoT Edge device as a test device.
Otherwise, you can delete the local configurations and the Azure resources that you used in this article to avoid
charges.
Delete Azure resources
Deleting Azure resources and resource groups is irreversible. Make sure that you don't accidentally delete the
wrong resource group or resources. If you created the IoT hub inside an existing resource group that has
resources that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.
To delete the resources:
1. Sign in to the Azure portal and select Resource groups.
2. Select the name of the resource group that contains your IoT Edge test resources.
3. Review the list of resources contained in your resource group. If you want to delete all of them, you can
select Delete resource group. If you want to delete only some of them, you can click into each resource to
delete them individually.

Next steps
In this tutorial, you created an IoT Edge module with code to filter raw data that's generated by your IoT Edge
device. When you're ready to build your own modules, you can learn more about developing your own IoT Edge
modules or how to develop modules with Visual Studio. For examples of IoT Edge modules, including the
simulated temperature module, see IoT Edge module samples and IoT C SDK samples.
You can continue on to the next tutorials to learn how Azure IoT Edge can help you deploy Azure cloud services to
process and analyze data at the edge.
Functions Stream Analytics Machine Learning Custom Vision Service
Tutorial: Develop a C# IoT Edge module for Linux
devices
12/2/2019 • 12 minutes to read • Edit Online

Use Visual Studio Code to develop C# code and deploy it to a Linux device running Azure IoT Edge.
You can use Azure 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. You'll
use the simulated IoT Edge device that you created in the Deploy Azure IoT Edge on a simulated device in
Windows or Linux quickstarts. In this tutorial, you learn how to:
Use Visual Studio Code to create an IoT Edge module that's based on the .NET Core 2.1 SDK.
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 that's generated by your device. It
only sends messages upstream if the temperature is above a specified threshold. This type of analysis at the edge
is useful for reducing the amount of data that's communicated to and stored in the cloud.
If you don't have an Azure subscription, create a free account before you begin.

Solution scope
This tutorial demonstrates how to develop a module in C# using Visual Studio Code, and how to deploy it to a
Linux device. If you're developing modules for Windows devices, go to Develop a C# IoT Edge module for
Windows devices instead.
Use the following table to understand your options for developing and deploying C# modules to Linux:

C# VISUAL STUDIO CODE VISUAL STUDIO

Linux AMD64

Linux ARM32

NOTE
Support for Linux ARM64 devices is available in public preview. For more information, see Develop and debug ARM64 IoT
Edge modules in Visual Studio Code (preview).

Prerequisites
Before beginning this tutorial, you should have gone through the previous tutorial to set up your development
environment, Develop an IoT Edge module for a Linux device. After completing that tutorial, you already should
have the following prerequisites:
A free or standard-tier IoT Hub in Azure.
A Linux device running Azure IoT Edge.
A container registry, like Azure Container Registry.
Visual Studio Code configured with the Azure IoT Tools.
Docker CE configured to run Linux containers.
To complete these tutorials, prepare the following additional prerequisites on your development machine:
C# for Visual Studio Code (powered by OmniSharp) extension.
.NET Core 2.1 SDK.

Create a module project


The following steps create an IoT Edge module project for C# by using Visual Studio Code and the Azure IoT Tools
extension. Once you have a project template created, add new code so that the module filters out messages based
on their reported properties.
Create a new project
Create a C# solution template that you can customize with your own code.
1. In Visual Studio Code, select View > Command Palette to open the VS Code command palette.
2. In the command palette, enter and run the command Azure: Sign in and follow the instructions to sign in
your Azure account. If you're already signed in, you can skip this step.
3. In the command palette, enter and run the command Azure IoT Edge: New IoT Edge solution. Follow
the prompts in the command palette to create your solution.

FIELD VALUE

Select folder Choose the location on your development machine for VS


Code to create the solution files.

Provide a solution name Enter a descriptive name for your solution or accept the
default EdgeSolution.

Select module template Choose C# Module.

Provide a module name Name your module CSharpModule.

Provide Docker image repository for the module An image repository includes the name of your container
registry and the name of your container image. Your
container image is prepopulated from the name you
provided in the last step. Replace localhost:5000 with the
login server value from your Azure container registry. You
can retrieve the login server from the Overview page of
your container registry in the Azure portal.

The final image repository looks like <registry


name>.azurecr.io/csharpmodule.
Add your registry credentials
The environment file stores the credentials for your container registry and shares them with the IoT Edge runtime.
The runtime needs these credentials to pull your private images onto the IoT Edge device. Use the credentials from
the Access keys section of your Azure container registry.
1. In the VS Code explorer, open the .env file.
2. Update the fields with the username and password values from your Azure container registry.
3. Save this file.
Select your target architecture
Currently, Visual Studio Code can develop C# modules for Linux AMD64 and Linux ARM32v7 devices. You need
to select which architecture you're targeting with each solution, because the container is built and run differently
for each architecture type. The default is Linux AMD64.
1. Open the command palette and search for Azure IoT Edge: Set Default Target Platform for Edge
Solution, or select the shortcut icon in the side bar at the bottom of the window.
2. In the command palette, select the target architecture from the list of options. For this tutorial, we're using
an Ubuntu virtual machine as the IoT Edge device, so will keep the default amd64.
Update the module with custom code
1. In the VS Code explorer, open modules > CSharpModule > Program.cs.
2. At the top of the CSharpModule namespace, add three using statements for types that are used later:

using System.Collections.Generic; // For KeyValuePair<>


using Microsoft.Azure.Devices.Shared; // For TwinCollection
using Newtonsoft.Json; // For JsonConvert

3. Add the temperatureThreshold variable to the Program class. This variable sets the value that the
measured temperature must exceed for the data to be sent to the IoT hub.

static int temperatureThreshold { get; set; } = 25;

4. Add the MessageBody, Machine, and Ambient 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;}
}

5. Find the Init function. This function creates and configures a ModuleClient object, which allows the
module to connect to the local Azure IoT Edge runtime to send and receive messages. After creating the
ModuleClient, the code reads the temperatureThreshold value from the module twin's desired
properties. The code registers a callback to receive messages from an IoT Edge hub via the input1
endpoint. Replace the SetInputMessageHandlerAsync method with a new one, and add a
SetDesiredPropertyUpdateCallbackAsync method for updates to the desired properties. To make this
change, replace the last line of the Init method with the following code:

// Register a callback for messages that are received by the module.


// await ioTHubModuleClient.SetInputMessageHandlerAsync("input1", PipeMessage, iotHubModuleClient);

// Read the TemperatureThreshold value from the module twin's desired properties
var moduleTwin = await ioTHubModuleClient.GetTwinAsync();
await OnDesiredPropertiesUpdate(moduleTwin.Properties.Desired, ioTHubModuleClient);

// Attach a callback for updates to the module twin's desired properties.


await ioTHubModuleClient.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertiesUpdate, null);

// Register a callback for messages that are received by the module.


await ioTHubModuleClient.SetInputMessageHandlerAsync("input1", FilterMessages, ioTHubModuleClient);

6. Add the onDesiredPropertiesUpdate method to the Program class. This method receives updates on the
desired properties from the module twin, and updates the temperatureThreshold variable to match. All
modules have their own module twin, which lets you configure the code that's running inside a module
directly from the cloud.

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;
}

7. Replace the PipeMessage method with the FilterMessages method. This method is called whenever the
module receives a message from the IoT Edge hub. It filters out messages that report temperatures below
the temperature threshold set via the module twin. It also adds the MessageType property to the message
with the value set to Alert.
static async Task<MessageResponse> FilterMessages(Message message, object userContext)
{
var counterValue = Interlocked.Increment(ref counter);
try
{
ModuleClient moduleClient = (ModuleClient)userContext;
var messageBytes = message.GetBytes();
var messageString = Encoding.UTF8.GetString(messageBytes);
Console.WriteLine($"Received message {counterValue}: [{messageString}]");

// Get the 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}");
using (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 moduleClient.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.
var moduleClient = (ModuleClient)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.
ModuleClient moduleClient = (ModuleClient)userContext;
return MessageResponse.Abandoned;
}
}

8. Save the Program.cs file.


9. In the VS Code explorer, open the deployment.template.json file in your IoT Edge solution workspace.
10. Add the CSharpModule module twin to the deployment manifest. Insert the following JSON content at
the bottom of the modulesContent section, after the $edgeHub module twin:
"CSharpModule": {
"properties.desired":{
"TemperatureThreshold":25
}
}

11. Save the deployment.template.json file.

Build and push your module


In the previous section, you created an IoT Edge solution and added code to the CSharpModule that will filter out
messages where the reported machine temperature is within the acceptable limits. Now you need to build the
solution as a container image and push it to your container registry.
1. Open the VS Code integrated terminal by selecting View > Terminal.
2. Sign in to Docker by entering the following command in the terminal. Sign in with the username, password,
and login server from your Azure container registry. You can retrieve these values from the Access keys
section of your registry in the Azure portal.

docker login -u <ACR username> -p <ACR password> <ACR login server>

You may receive a security warning recommending the use of --password-stdin . While that best practice is
recommended for production scenarios, it's outside the scope of this tutorial. For more information, see the
docker login reference.
3. In the VS Code explorer, right-click the deployment.template.json file and select Build and Push IoT
Edge solution.
The build and push command starts three operations. First, it creates a new folder in the solution called
config that holds the full deployment manifest, built out of information in the deployment template and
other solution files. Second, it runs docker build to build the container image based on the appropriate
dockerfile for your target architecture. Then, it runs docker push to push the image repository to your
container registry.
Deploy and run the solution
Use the Visual Studio Code explorer and the Azure IoT Tools extension to deploy the module project to your IoT
Edge device. You already have a deployment manifest prepared for your scenario, the deployment.json file in the
config folder. All you need to do now is select a device to receive the deployment.
Make sure that your IoT Edge device is up and running.
1. In the Visual Studio Code explorer, expand the Azure IoT Hub Devices section to see your list of IoT
devices.
2. Right-click the name of your IoT Edge device, then select Create Deployment for Single Device.
3. Select the deployment.json file in the config folder and then click Select Edge Deployment Manifest.
Do not use the deployment.template.json file.
4. Click the refresh button. You should see the new CSharpModule running along with the
SimulatedTemperatureSensor module and the $edgeAgent and $edgeHub.

View generated data


Once you apply the deployment manifest to your IoT Edge device, the IoT Edge runtime on the device collects the
new deployment information and starts executing on it. Any modules running on the device that aren't included in
the deployment manifest are stopped. Any modules missing from the device are started.
You can view the status of your IoT Edge device using the Azure IoT Hub Devices section of the Visual Studio
Code explorer. Expand the details of your device to see a list of deployed and running modules.
1. In the Visual Studio Code explorer, right-click the name of your IoT Edge device and select Start
Monitoring Built-in Event Endpoint.
2. View the messages arriving at your IoT Hub. It may take a while for the messages to arrive, because the IoT
Edge device has to receive its new deployment and start all the modules. Then, the changes we made to the
CModule code wait until the machine temperature reaches 25 degrees before sending messages. It also
adds the message type Alert to any messages that reach that temperature threshold.

Edit the module twin


We used the CSharpModule module twin in the deployment manifest to set the temperature threshold at 25
degrees. You can use the module twin to change the functionality without having to update the module code.
1. In Visual Studio Code, expand the details under your IoT Edge device to see the running modules.
2. Right-click CSharpModule and select Edit module twin.
3. Find TemperatureThreshold in the desired properties. Change its value to a new temperature 5 degrees
to 10 degrees higher than the latest reported temperature.
4. Save the module twin file.
5. Right-click anywhere in the module twin editing pane and select Update module twin.
6. Monitor the incoming device-to-cloud messages. You should see the messages stop until the new
temperature threshold is reached.

Clean up resources
If you plan to continue to the next recommended article, you can keep the resources and configurations that you
created and reuse them. You can also keep using the same IoT Edge device as a test device.
Otherwise, you can delete the local configurations and the Azure resources that you used in this article to avoid
charges.
Delete Azure resources
Deleting Azure resources and resource groups is irreversible. Make sure that you don't accidentally delete the
wrong resource group or resources. If you created the IoT hub inside an existing resource group that has
resources that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.
To delete the resources:
1. Sign in to the Azure portal and select Resource groups.
2. Select the name of the resource group that contains your IoT Edge test resources.
3. Review the list of resources contained in your resource group. If you want to delete all of them, you can
select Delete resource group. If you want to delete only some of them, you can click into each resource to
delete them individually.

Next steps
In this tutorial, you created an IoT Edge module that contains code to filter raw data generated by your IoT Edge
device. When you're ready to build your own modules, you can learn more about developing your own IoT Edge
modules or how to develop modules with Visual Studio Code. For examples of IoT Edge modules, including the
simulated temperature module, see IoT Edge module samples.
You can continue on to the next tutorials to learn how Azure IoT Edge can help you deploy Azure cloud services to
process and analyze data at the edge.
Functions Stream Analytics Machine Learning Custom Vision Service
Tutorial: Develop a C# IoT Edge module for
Windows devices
12/2/2019 • 12 minutes to read • Edit Online

Use Visual Studio to develop C# code and deploy it to a Windows device running Azure IoT Edge.
You can use Azure 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. In this
tutorial, you learn how to:
Use Visual Studio to create an IoT Edge module that's based on the C# SDK.
Use Visual Studio 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 that's generated by your device. It
only sends messages upstream if the temperature is above a specified threshold. This type of analysis at the edge
is useful for reducing the amount of data that's communicated to and stored in the cloud.
If you don't have an Azure subscription, create a free account before you begin.

Solution scope
This tutorial demonstrates how to develop a module in C# using Visual Studio 2019, and how to deploy it to a
Windows device. If you're developing modules for Linux devices, go to Develop a C# IoT Edge module for Linux
devices instead.
Use the following table to understand your options for developing and deploying C# modules to Windows
devices:

C# VISUAL STUDIO CODE VISUAL STUDIO 2017/2019

Windows AMD64 develop

Windows AMD64 debug

Prerequisites
Before beginning this tutorial, you should have gone through the previous tutorial to set up your development
environment, Develop an IoT Edge module for a Windows device. After completing that tutorial, you already
should have the following prerequisites:
A free or standard-tier IoT Hub in Azure.
A Windows device running Azure IoT Edge.
A container registry, like Azure Container Registry.
Visual Studio 2019 configured with the Azure IoT Edge Tools extension.
Docker Desktop configured to run Windows containers.
TIP
If you are using Visual Studio 2017 (version 15.7 or higher), plrease download and install Azure IoT Edge Tools for VS 2017
from the Visual Studio marketplace

Create a module project


The following steps create an IoT Edge module project by using Visual Studio and the Azure IoT Edge Tools
extension. Once you have a project template created, add new code so that the module filters out messages based
on their reported properties.
Create a new project
The Azure IoT Edge Tools provides project templates for all supported IoT Edge module languages in Visual
Studio. These templates have all the files and code that you need to deploy a working module to test IoT Edge, or
give you a starting point to customize the template with your own business logic.
1. Launch Visual Studio 2019 and select Create New Project.
2. In the new project window, search IoT Edge project and choose the Azure IoT Edge (Windows amd64)
project. Click Next.

3. In the configure your new project window, rename the project and solution to something descriptive like
CSharpTutorialApp. Click Create to create the project.
4. In the IoT Edge application and module window, configure your project with the following values:

FIELD VALUE

Select a template Select C# Module.

Module project name Name your module CSharpModule.

Docker image repository An image repository includes the name of your container
registry and the name of your container image. Your
container image is prepopulated from the module project
name value. Replace localhost:5000 with the login server
value from your Azure container registry. You can retrieve
the login server from the Overview page of your container
registry in the Azure portal.

The final image repository looks like <registry


name>.azurecr.io/csharpmodule.
5. Select Add to create the project.
Add your registry credentials
The deployment manifest shares the credentials for your container registry with the IoT Edge runtime. The
runtime needs these credentials to pull your private images onto the IoT Edge device. Use the credentials from the
Access keys section of your Azure container registry.
1. In the Visual Studio solution explorer, open the deployment.template.json file.
2. Find the registryCredentials property in the $edgeAgent desired properties.
3. Update the property with your credentials, following this format:

"registryCredentials": {
"<registry name>": {
"username": "<username>",
"password": "<password>",
"address": "<registry name>.azurecr.io"
}
}

4. Save the deployment.template.json file.


Update the module with custom code
The default module code receives messages on an input queue and passes them along through an output queue.
Let's add some additional code so that the module processes the messages at the edge before forwarding them to
IoT Hub. Update the module so that it analyzes the temperature data in each message, and only sends the
message to IoT Hub if the temperature exceeds a certain threshold.
1. In Visual Studio, open CSharpModule > Program.cs.
2. At the top of the CSharpModule namespace, add three using statements for types that are used later:
using System.Collections.Generic; // For KeyValuePair<>
using Microsoft.Azure.Devices.Shared; // For TwinCollection
using Newtonsoft.Json; // For JsonConvert

3. Add the temperatureThreshold variable to the Program class after the counter variable. The
temperatureThreshold variable sets the value that the measured temperature must exceed for the data to be
sent to the IoT hub.

static int temperatureThreshold { get; set; } = 25;

4. Add the MessageBody, Machine, and Ambient classes to the Program class after the variable
declarations. 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;}
}

5. Find the Init method. This method creates and configures a ModuleClient object, which allows the
module to connect to the local Azure IoT Edge runtime to send and receive messages. The code also
registers a callback to receive messages from an IoT Edge hub via the input1 endpoint.
Replace the entire Init method with the following code:

static async Task Init()


{
AmqpTransportSettings amqpSetting = new AmqpTransportSettings(TransportType.Amqp_Tcp_Only);
ITransportSettings[] settings = { amqpSetting };

// Open a connection to the Edge runtime


ModuleClient ioTHubModuleClient = await ModuleClient.CreateFromEnvironmentAsync(settings);
await ioTHubModuleClient.OpenAsync();
Console.WriteLine("IoT Hub module client initialized.");

// Read the TemperatureThreshold value from the module twin's desired properties
var moduleTwin = await ioTHubModuleClient.GetTwinAsync();
await OnDesiredPropertiesUpdate(moduleTwin.Properties.Desired, ioTHubModuleClient);

// Attach a callback for updates to the module twin's desired properties.


await ioTHubModuleClient.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertiesUpdate, null);

// Register a callback for messages that are received by the module.


await ioTHubModuleClient.SetInputMessageHandlerAsync("input1", FilterMessages, ioTHubModuleClient);
}

This updated Init method still sets up the connection to the IoT Edge runtime with the ModuleClient, but
also adds new functionality. It reads the module twin's desired properties to retrieve the
temperatureThreshold value. Then, it creates a callback that listens for any future updates to the module
twin's desired properties. With this callback, you can update the temperature threshold in the module twin
remotely, and the changes will be incorporated into the module.
The updated Init method also changes the existing SetInputMessageHandlerAsync method. In the
sample code, incoming messages on input1 are processed with the PipeMessage function, but we want to
change that to use the FilterMessages function that we'll create in the following steps.
6. Add a new onDesiredPropertiesUpdate method to the Program class. This method receives updates on
the desired properties from the module twin, and updates the temperatureThreshold variable to match.
All modules have their own module twin, which lets you configure the code that's running inside a module
directly from the cloud.

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;
}

7. Remove the sample PipeMessage method and replace it with a new FilterMessages method. This
method is called whenever the module receives a message from the IoT Edge hub. It filters out messages
that report temperatures below the temperature threshold set via the module twin. It also adds the
MessageType property to the message with the value set to Alert.
static async Task<MessageResponse> FilterMessages(Message message, object userContext)
{
var counterValue = Interlocked.Increment(ref counter);
try
{
ModuleClient moduleClient = (ModuleClient)userContext;
var messageBytes = message.GetBytes();
var messageString = Encoding.UTF8.GetString(messageBytes);
Console.WriteLine($"Received message {counterValue}: [{messageString}]");

// Get the 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}");
using(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 moduleClient.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.
var moduleClient = (ModuleClient)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.
ModuleClient moduleClient = (ModuleClient)userContext;
return MessageResponse.Abandoned;
}
}

8. Save the Program.cs file.


9. Open the deployment.template.json file in your IoT Edge solution. This file tells the IoT Edge agent
which modules to deploy, in this case SimulatedTemperatureSensor and CSharpModule, and tells the
IoT Edge hub how to route messages between them.
10. Add the CSharpModule module twin to the deployment manifest. Insert the following JSON content at
the bottom of the modulesContent section, after the $edgeHub module twin:
"CSharpModule": {
"properties.desired":{
"TemperatureThreshold":25
}
}

11. Save the deployment.template.json file.

Build and push your module


In the previous section, you created an IoT Edge solution and added code to the CSharpModule to filter out
messages where the reported machine temperature is below the acceptable threshold. Now you need to build the
solution as a container image and push it to your container registry.
1. Use the following command to sign in to Docker on your development machine. Use the username,
password, and login server from your Azure container registry. You can retrieve these values from the
Access keys section of your registry in the Azure portal.

docker login -u <ACR username> -p <ACR password> <ACR login server>

You may receive a security warning recommending the use of --password-stdin . While that best practice is
recommended for production scenarios, it's outside the scope of this tutorial. For more information, see the
docker login reference.
2. In the Visual Studio solution explorer, right-click the project name that you want to build. The default name
is AzureIotEdgeApp1 and since you're building a Windows module, the extension should be
Windows.Amd64.
3. Select Build and Push IoT Edge Modules.
The build and push command starts three operations. First, it creates a new folder in the solution called
config that holds the full deployment manifest, built out of information in the deployment template and
other solution files. Second, it runs docker build to build the container image based on the appropriate
dockerfile for your target architecture. Then, it runs docker push to push the image repository to your
container registry.

Deploy modules to device


Use the Visual Studio cloud explorer and the Azure IoT Edge Tools extension to deploy the module project to your
IoT Edge device. You already have a deployment manifest prepared for your scenario, the deployment.json file in
the config folder. All you need to do now is select a device to receive the deployment.
Make sure that your IoT Edge device is up and running.
1. In the Visual Studio cloud explorer, expand the resources to see your list of IoT devices.
2. Right-click the name of the IoT Edge device that you want to receive the deployment.
3. Select Create Deployment.
4. In the file explorer, select the deployment.windows-amd64 file in the config folder of your solution.
5. Refresh the cloud explorer to see the deployed modules listed under your device.

View generated data


Once you apply the deployment manifest to your IoT Edge device, the IoT Edge runtime on the device collects the
new deployment information and starts executing on it. Any modules running on the device that aren't included in
the deployment manifest are stopped. Any modules missing from the device are started.
You can use the IoT Edge Tools extension to view messages as they arrive at your IoT Hub.
1. In the Visual Studio cloud explorer, select the name of your IoT Edge device.
2. In the Actions list, select Start Monitoring Built-in Event Endpoint.
3. View the messages arriving at your IoT Hub. It may take a while for the messages to arrive, because the
changes we made to the CSharpModule code wait until the machine temperature reaches 25 degrees
before sending messages. It also adds the message type Alert to any messages that reach that temperature
threshold.

Edit the module twin


We used the CSharpModule module twin to set the temperature threshold at 25 degrees. You can use the module
twin to change the functionality without having to update the module code.
1. In Visual Studio, open the deployment.windows-amd64.json file. (Not the deployment.template file. If
you don't see the deployment manifest in the config file in the solution explorer, select the Show all files
icon in the explorer toolbar.)
2. Find the CSharpModule twin and change the value of the temperatureThreshold parameter to a new
temperature 5 degrees to 10 degrees higher than the latest reported temperature.
3. Save the deployment.windows-amd64.json file.
4. Follow the deployment steps again to apply the updated deployment manifest to your device.
5. Monitor the incoming device-to-cloud messages. You should see the messages stop until the new
temperature threshold is reached.

Clean up resources
If you plan to continue to the next recommended article, you can keep the resources and configurations that you
created and reuse them. You can also keep using the same IoT Edge device as a test device.
Otherwise, you can delete the local configurations and the Azure resources that you used in this article to avoid
charges.
Delete Azure resources
Deleting Azure resources and resource groups is irreversible. Make sure that you don't accidentally delete the
wrong resource group or resources. If you created the IoT hub inside an existing resource group that has
resources that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.
To delete the resources:
1. Sign in to the Azure portal and select Resource groups.
2. Select the name of the resource group that contains your IoT Edge test resources.
3. Review the list of resources contained in your resource group. If you want to delete all of them, you can
select Delete resource group. If you want to delete only some of them, you can click into each resource to
delete them individually.

Next steps
In this tutorial, you created an IoT Edge module with code to filter raw data that's generated by your IoT Edge
device. When you're ready to build your own modules, you can learn more about developing your own IoT Edge
modules or how to develop modules with Visual Studio. For examples of IoT Edge modules, including the
simulated temperature module, see IoT Edge module samples.
You can continue on to the next tutorials to learn how Azure IoT Edge can help you deploy Azure cloud services to
process and analyze data at the edge.
Functions Stream Analytics Machine Learning Custom Vision Service
Tutorial: Develop a Java IoT Edge module for Linux
devices
12/2/2019 • 11 minutes to read • Edit Online

You can use Azure 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. You'll
use the simulated IoT Edge device that you created in the Deploy Azure IoT Edge on a simulated device in Linux
quickstart. In this tutorial, you learn how to:
Use Visual Studio Code to create an IoT Edge Java module based on the Azure IoT Edge maven template
package and Azure IoT Java device SDK.
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 that's generated by your device. It
only sends messages upstream if the temperature is above a specified threshold. This type of analysis at the edge
is useful for reducing the amount of data that's communicated to and stored in the cloud.
If you don't have an Azure subscription, create a free account before you begin.

Solution scope
This tutorial demonstrates how to develop a module in Java using Visual Studio Code, and how to deploy it to a
Linux device. IoT Edge does not support Java modules for Windows devices.
Use the following table to understand your options for developing and deploying Java modules:

JAVA VISUAL STUDIO CODE VISUAL STUDIO 2017/2019

Linux AMD64

Linux ARM32

Prerequisites
Before beginning this tutorial, you should have gone through the previous tutorial to set up your development
environment for Linux container development: Develop IoT Edge modules for Linux devices. By completing either
of those tutorials, you should have the following prerequisites in place:
A free or standard-tier IoT Hub in Azure.
A Linux device running Azure IoT Edge
A container registry, like Azure Container Registry.
Visual Studio Code configured with the Azure IoT Tools.
Docker CE configured to run Linux containers.
To develop an IoT Edge module in Java, install the following additional prerequisites on your development
machine:
Java Extension Pack for Visual Studio Code.
Java SE Development Kit 10, and set the JAVA_HOME environment variable to point to your JDK installation.
Maven

Create a module project


The following steps create an IoT Edge module project that's based on the Azure IoT Edge maven template
package and Azure IoT Java device SDK. You create the project by using Visual Studio Code and the Azure IoT
Tools.
Create a new project
Create a Java solution template that you can customize with your own code.
1. In Visual Studio Code, select View > Command Palette to open the VS Code command palette.
2. In the command palette, enter and run the command Azure IoT Edge: New IoT Edge solution. Follow
the prompts in the command palette to create your solution.

FIELD VALUE

Select folder Choose the location on your development machine for VS


Code to create the solution files.

Provide a solution name Enter a descriptive name for your solution or accept the
default EdgeSolution.

Select module template Choose Java Module.

Provide value for groupId Enter a group ID value or accept the default
com.edgemodule.

Provide a module name Name your module JavaModule.

Provide Docker image repository for the module An image repository includes the name of your container
registry and the name of your container image. Your
container image is prepopulated from the name you
provided in the last step. Replace localhost:5000 with the
login server value from your Azure container registry. You
can retrieve the login server from the Overview page of
your container registry in the Azure portal.

The final image repository looks like <registry


name>.azurecr.io/javamodule.

If it's the first time to create Java module, it might take several minutes to download maven packages. Then the VS
Code window loads your IoT Edge solution workspace. The solution workspace contains five top-level
components. The modules folder contains the Java code for your module as well as Docker files for building your
module as a container image. The .env file stores your container registry credentials. The
deployment.template.json file contains the information that the IoT Edge runtime uses to deploy modules on a
device. And deployment.debug.template.json file containers the debug version of modules. You won't edit the
.vscode folder or .gitignore file in this tutorial.
If you didn't specify a container registry when creating your solution, but accepted the default localhost:5000 value,
you won't have a .env file.
Add your registry credentials
The environment file stores the credentials for your container registry and shares them with the IoT Edge runtime.
The runtime needs these credentials to pull your private images onto the IoT Edge device.
1. In the VS Code explorer, open the .env file.
2. Update the fields with the username and password values that you copied from your Azure container registry.
3. Save this file.
Select your target architecture
Currently, Visual Studio Code can develop Java modules for Linux AMD64 and Linux ARM32v7 devices. You need
to select which architecture you're targeting with each solution, because the container is built and run differently
for each architecture type. The default is Linux AMD64.
1. Open the command palette and search for Azure IoT Edge: Set Default Target Platform for Edge
Solution, or select the shortcut icon in the side bar at the bottom of the window.
2. In the command palette, select the target architecture from the list of options. For this tutorial, we're using
an Ubuntu virtual machine as the IoT Edge device, so will keep the default amd64.
Update the module with custom code
1. In the VS Code explorer, open modules > JavaModule > src > main > java > com > edgemodule >
App.java.
2. Add the following code at the top of the file to import new referenced classes.

import java.io.StringReader;
import java.util.concurrent.atomic.AtomicLong;
import java.util.HashMap;
import java.util.Map;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;

import com.microsoft.azure.sdk.iot.device.DeviceTwin.Pair;
import com.microsoft.azure.sdk.iot.device.DeviceTwin.Property;
import com.microsoft.azure.sdk.iot.device.DeviceTwin.TwinPropertyCallBack;

3. Add the following definition into class App. This variable sets a temperature threshold. The measured
machine temperature won't be reported to IoT Hub until it goes over this value.

private static final String TEMP_THRESHOLD = "TemperatureThreshold";


private static AtomicLong tempThreshold = new AtomicLong(25);

4. Replace the execute method of MessageCallbackMqtt with the following code. This method is called
whenever the module receives an MQTT message from the IoT Edge hub. It filters out messages that report
temperatures below the temperature threshold set via the module twin.
protected static class MessageCallbackMqtt implements MessageCallback {
private int counter = 0;
@Override
public IotHubMessageResult execute(Message msg, Object context) {
this.counter += 1;

String msgString = new String(msg.getBytes(), Message.DEFAULT_IOTHUB_MESSAGE_CHARSET);


System.out.println(
String.format("Received message %d: %s",
this.counter, msgString));
if (context instanceof ModuleClient) {
try (JsonReader jsonReader = Json.createReader(new StringReader(msgString))) {
final JsonObject msgObject = jsonReader.readObject();
double temperature =
msgObject.getJsonObject("machine").getJsonNumber("temperature").doubleValue();
long threshold = App.tempThreshold.get();
if (temperature >= threshold) {
ModuleClient client = (ModuleClient) context;
System.out.println(
String.format("Temperature above threshold %d. Sending message: %s",
threshold, msgString));
client.sendEventAsync(msg, eventCallback, msg, App.OUTPUT_NAME);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return IotHubMessageResult.COMPLETE;
}
}

5. Add the following two static inner classes into class App. These classes update the tempThreshold variable
when the module twin's desired property changes. All modules have their own module twin, which lets you
configure the code that's running inside a module directly from the cloud.

protected static class DeviceTwinStatusCallBack implements IotHubEventCallback {


@Override
public void execute(IotHubStatusCode status, Object context) {
System.out.println("IoT Hub responded to device twin operation with status " + status.name());
}
}

protected static class OnProperty implements TwinPropertyCallBack {


@Override
public void TwinPropertyCallBack(Property property, Object context) {
if (!property.getIsReported()) {
if (property.getKey().equals(App.TEMP_THRESHOLD)) {
try {
long threshold = Math.round((double) property.getValue());
App.tempThreshold.set(threshold);
} catch (Exception e) {
System.out.println("Faile to set TemperatureThread with exception");
e.printStackTrace();
}
}
}
}
}

6. Add the following lines in to main method after client.open() to subscribe the module twin updates.
client.startTwin(new DeviceTwinStatusCallBack(), null, new OnProperty(), null);
Map<Property, Pair<TwinPropertyCallBack, Object>> onDesiredPropertyChange = new HashMap<Property,
Pair<TwinPropertyCallBack, Object>>() {
{
put(new Property(App.TEMP_THRESHOLD, null), new Pair<TwinPropertyCallBack, Object>(new
OnProperty(), null));
}
};
client.subscribeToTwinDesiredProperties(onDesiredPropertyChange);
client.getTwin();

7. Save the App.java file.


8. In the VS Code explorer, open the deployment.template.json file in your IoT Edge solution workspace.
9. Add the JavaModule module twin to the deployment manifest. Insert the following JSON content at the
bottom of the moduleContent section, after the $edgeHub module twin:

"JavaModule": {
"properties.desired":{
"TemperatureThreshold":25
}
}

10. Save the deployment.template.json file.

Build and push your module


In the previous section, you created an IoT Edge solution and added code to the JavaModule to filter out
messages where the reported machine temperature is below the acceptable limit. Now, build the solution as a
container image and push it to your container registry.
1. Open the VS Code integrated terminal by selecting View > Terminal.
2. Sign in to Docker by entering the following command in the terminal. Sign in with the username, password,
and login server from your Azure container registry. You can retrieve these values from the Access keys
section of your registry in the Azure portal.
docker login -u <ACR username> -p <ACR password> <ACR login server>

You may receive a security warning recommending the use of --password-stdin . While that best practice is
recommended for production scenarios, it's outside the scope of this tutorial. For more information, see the
docker login reference.
3. In the VS Code explorer, right-click the deployment.template.json file and select Build and Push IoT
Edge solution.
The build and push command starts three operations. First, it creates a new folder in the solution called
config that holds the full deployment manifest, built out of information in the deployment template and
other solution files. Second, it runs docker build to build the container image based on the appropriate
dockerfile for your target architecture. Then, it runs docker push to push the image repository to your
container registry.

Deploy modules to device


Use the Visual Studio Code explorer and the Azure IoT Tools extension to deploy the module project to your IoT
Edge device. You already have a deployment manifest prepared for your scenario, the deployment.json file in the
config folder. All you need to do now is select a device to receive the deployment.
Make sure that your IoT Edge device is up and running.
1. In the Visual Studio Code explorer, expand the Azure IoT Hub Devices section to see your list of IoT
devices.
2. Right-click the name of your IoT Edge device, then select Create Deployment for Single Device.
3. Select the deployment.json file in the config folder and then click Select Edge Deployment Manifest.
Do not use the deployment.template.json file.
4. Click the refresh button. You should see the new JavaModule running along with the
SimulatedTemperatureSensor module and the $edgeAgent and $edgeHub.

View generated data


Once you apply the deployment manifest to your IoT Edge device, the IoT Edge runtime on the device collects the
new deployment information and starts executing on it. Any modules running on the device that aren't included in
the deployment manifest are stopped. Any modules missing from the device are started.
You can view the status of your IoT Edge device using the Azure IoT Hub Devices section of the Visual Studio
Code explorer. Expand the details of your device to see a list of deployed and running modules.
1. In the Visual Studio Code explorer, right-click the name of your IoT Edge device and select Start
Monitoring Built-in Event Endpoint.
2. View the messages arriving at your IoT Hub. It may take a while for the messages to arrive, because the IoT
Edge device has to receive its new deployment and start all the modules. Then, the changes we made to the
JavaModule code wait until the machine temperature reaches 25 degrees before sending messages. It also
adds the message type Alert to any messages that reach that temperature threshold.

Edit the module twin


We used the JavaModule module twin in the deployment manifest to set the temperature threshold at 25 degrees.
You can use the module twin to change the functionality without having to update the module code.
1. In Visual Studio Code, expand the details under your IoT Edge device to see the running modules.
2. Right-click JavaModule and select Edit module twin.
3. Find TemperatureThreshold in the desired properties. Change its value to a new temperature 5 degrees
to 10 degrees higher than the latest reported temperature.
4. Save the module twin file.
5. Right-click anywhere in the module twin editing pane and select Update module twin.
6. Monitor the incoming device-to-cloud messages. You should see the messages stop until the new
temperature threshold is reached.

Clean up resources
If you plan to continue to the next recommended article, you can keep the resources and configurations that you
created and reuse them. You can also keep using the same IoT Edge device as a test device.
Otherwise, you can delete the local configurations and the Azure resources that you created in this article to avoid
charges.
Delete Azure resources
Deleting Azure resources and resource groups is irreversible. Make sure that you don't accidentally delete the
wrong resource group or resources. If you created the IoT hub inside an existing resource group that has resources
that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.
To delete the resources:
1. Sign in to the Azure portal and select Resource groups.
2. Select the name of the resource group that contains your IoT Edge test resources.
3. Review the list of resources contained in your resource group. If you want to delete all of them, you can
select Delete resource group. If you want to delete only some of them, you can click into each resource to
delete them individually.

Next steps
In this tutorial, you created an IoT Edge module that contains code to filter raw data generated by your IoT Edge
device. When you're ready to build your own modules, you can learn more about developing your own IoT Edge
modules or how to develop modules with Visual Studio Code. For examples of IoT Edge modules, including the
simulated temperature module, see IoT Edge module samples.
You can continue on to the next tutorials to learn how Azure IoT Edge can help you deploy Azure cloud services to
process and analyze data at the edge.
Functions Stream Analytics Machine Learning Custom Vision Service
Tutorial: Develop and deploy a Node.js IoT Edge
module for Linux devices
11/27/2019 • 10 minutes to read • Edit Online

Use Visual Studio Code to develop Node.js code and deploy it to a Linux device running Azure 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. You'll
use the simulated IoT Edge device that you created in the quickstarts. In this tutorial, you learn how to:
Use Visual Studio Code to create an IoT Edge Node.js module
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. It only
sends messages upstream if the temperature is above a specified threshold. This type of analysis at the edge is
useful for reducing the amount of data communicated to and stored in the cloud.
If you don't have an Azure subscription, create a free account before you begin.

Solution scope
This tutorial demonstrates how to develop a module in Node.js using Visual Studio Code, and how to deploy it
to a Linux device. IoT Edge does not support Node.js modules for Windows devices.
Use the following table to understand your options for developing and deploying Node.js modules:

NODE.JS VISUAL STUDIO CODE VISUAL STUDIO 2017/2019

Linux AMD64

Linux ARM32

Prerequisites
Before beginning this tutorial, you should have gone through the previous tutorial to set up your development
environment for Linux container development: Develop IoT Edge modules for Linux devices. By completing either
of those tutorials, you should have the following prerequisites in place:
A free or standard-tier IoT Hub in Azure.
A Linux device running Azure IoT Edge
A container registry, like Azure Container Registry.
Visual Studio Code configured with the Azure IoT Tools.
Docker CE configured to run Linux containers.
To develop an IoT Edge module in Node.js, install the following additional prerequisites on your development
machine:
Node.js and npm. The npm package is distributed with Node.js, which means that when you download Node.js,
you automatically get npm installed on your computer.

Create a module project


The following steps show you how to create an IoT Edge Node.js module using Visual Studio Code and the Azure
IoT Tools.
Create a new project
Use npm to create a Node.js solution template that you can build on top of.
1. In Visual Studio Code, select View > Integrated Terminal to open the VS Code integrated terminal.
2. In the integrated terminal, enter the following command to install yeoman and the generator for Node.js
Azure IoT Edge module:

npm install -g yo generator-azure-iot-edge-module

3. Select View > Command Palette to open the VS Code command palette.
4. In the command palette, type and run the command Azure: Sign in and follow the instructions to sign in
your Azure account. If you've already signed in, you can skip this step.
5. In the command palette, type and run the command Azure IoT Edge: New IoT Edge solution. Follow the
prompts in the command palette to create your solution.

FIELD VALUE

Select folder Choose the location on your development machine for VS


Code to create the solution files.

Provide a solution name Enter a descriptive name for your solution or accept the
default EdgeSolution.

Select module template Choose Node.js Module.

Provide a module name Name your module NodeModule.

Provide Docker image repository for the module An image repository includes the name of your container
registry and the name of your container image. Your
container image is prepopulated from the name you
provided in the last step. Replace localhost:5000 with the
login server value from your Azure container registry. You
can retrieve the login server from the Overview page of
your container registry in the Azure portal.

The final image repository looks like <registry


name>.azurecr.io/nodemodule.
Add your registry credentials
The environment file stores the credentials for your container repository and shares those with the IoT Edge
runtime. The runtime needs these credentials to pull your private images onto the IoT Edge device.
1. In the VS Code explorer, open the .env file.
2. Update the fields with the username and password values that you copied from your Azure container registry.
3. Save this file.
Select your target architecture
Currently, Visual Studio Code can develop Node.js modules for Linux AMD64 and Linux ARM32v7 devices. You
need to select which architecture you're targeting with each solution, because the container is built and run
differently for each architecture type. The default is Linux AMD64.
1. Open the command palette and search for Azure IoT Edge: Set Default Target Platform for Edge
Solution, or select the shortcut icon in the side bar at the bottom of the window.
2. In the command palette, select the target architecture from the list of options. For this tutorial, we're using
an Ubuntu virtual machine as the IoT Edge device, so will keep the default amd64.
Update the module with custom code
Each template comes with sample code included, which takes simulated sensor data from the
SimulatedTemperatureSensor module and routes it to IoT Hub. In this section, add code to have NodeModule
analyze the messages before sending them.
1. In the VS Code explorer, open modules > NodeModule > app.js.
2. Add a temperature threshold variable below required node modules. The temperature threshold sets the
value that the measured temperature must exceed in order for the data to be sent to IoT Hub.

var temperatureThreshold = 25;

3. Replace the entire PipeMessage function with the FilterMessage function.

// This function filters out messages that report temperatures below the temperature threshold.
// It also adds the MessageType property to the message with the value set to Alert.
function filterMessage(client, inputName, msg) {
client.complete(msg, printResultFor('Receiving message'));
if (inputName === 'input1') {
var message = msg.getBytes().toString('utf8');
var messageBody = JSON.parse(message);
if (messageBody && messageBody.machine && messageBody.machine.temperature &&
messageBody.machine.temperature > temperatureThreshold) {
console.log(`Machine temperature ${messageBody.machine.temperature} exceeds threshold
${temperatureThreshold}`);
var outputMsg = new Message(message);
outputMsg.properties.add('MessageType', 'Alert');
client.sendOutputEvent('output1', outputMsg, printResultFor('Sending received message'));
}
}
}

4. Replace the function name pipeMessage with filterMessage in client.on() function.

client.on('inputMessage', function (inputName, msg) {


filterMessage(client, inputName, msg);
});
5. Copy the following code snippet into the client.open() function callback, after client.on() inside the
else statement. This function is invoked when the desired properties are updated.

client.getTwin(function (err, twin) {


if (err) {
console.error('Error getting twin: ' + err.message);
} else {
twin.on('properties.desired', function(delta) {
if (delta.TemperatureThreshold) {
temperatureThreshold = delta.TemperatureThreshold;
}
});
}
});

6. Save the app.js file.


7. In the VS Code explorer, open the deployment.template.json file in your IoT Edge solution workspace.
8. Add the NodeModule module twin to the deployment manifest. Insert the following JSON content at the
bottom of the moduleContent section, after the $edgeHub module twin:

"NodeModule": {
"properties.desired":{
"TemperatureThreshold":25
}
}

9. Save the deployment.template.json file.

Build and push your module


In the previous section, you created an IoT Edge solution and added code to the NodeModule that will filter out
messages where the reported machine temperature is within the acceptable limits. Now you need to build the
solution as a container image and push it to your container registry.
1. Open the VS Code integrated terminal by selecting View > Terminal.
2. Sign in to Docker by entering the following command in the terminal. Sign in with the username, password,
and login server from your Azure container registry. You can retrieve these values from the Access keys
section of your registry in the Azure portal.

docker login -u <ACR username> -p <ACR password> <ACR login server>

You may receive a security warning recommending the use of --password-stdin . While that best practice is
recommended for production scenarios, it's outside the scope of this tutorial. For more information, see the
docker login reference.
3. In the VS Code explorer, right-click the deployment.template.json file and select Build and Push IoT
Edge solution.
The build and push command starts three operations. First, it creates a new folder in the solution called
config that holds the full deployment manifest, built out of information in the deployment template and
other solution files. Second, it runs docker build to build the container image based on the appropriate
dockerfile for your target architecture. Then, it runs docker push to push the image repository to your
container registry.

Deploy modules to device


Use the Visual Studio Code explorer and the Azure IoT Tools extension to deploy the module project to your IoT
Edge device. You already have a deployment manifest prepared for your scenario, the deployment.json file in the
config folder. All you need to do now is select a device to receive the deployment.
Make sure that your IoT Edge device is up and running.
1. In the Visual Studio Code explorer, expand the Azure IoT Hub Devices section to see your list of IoT
devices.
2. Right-click the name of your IoT Edge device, then select Create Deployment for Single Device.
3. Select the deployment.json file in the config folder and then click Select Edge Deployment Manifest.
Do not use the deployment.template.json file.
4. Click the refresh button. You should see the new NodeModule running along with the
SimulatedTemperatureSensor module and the $edgeAgent and $edgeHub.

View generated data


Once you apply the deployment manifest to your IoT Edge device, the IoT Edge runtime on the device collects the
new deployment information and starts executing on it. Any modules running on the device that aren't included in
the deployment manifest are stopped. Any modules missing from the device are started.
You can view the status of your IoT Edge device using the Azure IoT Hub Devices section of the Visual Studio
Code explorer. Expand the details of your device to see a list of deployed and running modules.
1. In the Visual Studio Code explorer, right-click the name of your IoT Edge device and select Start
Monitoring Built-in Event Endpoint.
2. View the messages arriving at your IoT Hub. It may take a while for the messages to arrive, because the IoT
Edge device has to receive its new deployment and start all the modules. Then, the changes we made to the
NodeModule code wait until the machine temperature reaches 25 degrees before sending messages. It also
adds the message type Alert to any messages that reach that temperature threshold.

Edit the module twin


We used the NodeModule module twin in the deployment manifest to set the temperature threshold at 25
degrees. You can use the module twin to change the functionality without having to update the module code.
1. In Visual Studio Code, expand the details under your IoT Edge device to see the running modules.
2. Right-click NodeModule and select Edit module twin.
3. Find TemperatureThreshold in the desired properties. Change its value to a new temperature 5 degrees
to 10 degrees higher than the latest reported temperature.
4. Save the module twin file.
5. Right-click anywhere in the module twin editing pane and select Update module twin.
6. Monitor the incoming device-to-cloud messages. You should see the messages stop until the new
temperature threshold is reached.

Clean up resources
If you plan to continue to the next recommended article, you can keep the resources and configurations that you
created and reuse them. You can also keep using the same IoT Edge device as a test device.
Otherwise, you can delete the local configurations and the Azure resources that you created in this article to avoid
charges.
Delete Azure resources
Deleting Azure resources and resource groups is irreversible. Make sure that you don't accidentally delete the
wrong resource group or resources. If you created the IoT hub inside an existing resource group that has resources
that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.
To delete the resources:
1. Sign in to the Azure portal and select Resource groups.
2. Select the name of the resource group that contains your IoT Edge test resources.
3. Review the list of resources contained in your resource group. If you want to delete all of them, you can
select Delete resource group. If you want to delete only some of them, you can click into each resource to
delete them individually.

Next steps
In this tutorial, you created an IoT Edge module that contains code to filter raw data generated by your IoT Edge
device. When you're ready to build your own modules, you can learn more about developing your own IoT Edge
modules or how to develop modules with Visual Studio Code. For examples of IoT Edge modules, including the
simulated temperature module, see IoT Edge module samples.
You can continue on to the next tutorials to learn how Azure IoT Edge can help you deploy Azure cloud services to
process and analyze data at the edge.
Functions Stream Analytics Machine Learning Custom Vision Service
Tutorial: Develop and deploy a Python IoT Edge
module for Linux devices
11/27/2019 • 11 minutes to read • Edit Online

Use Visual Studio Code to develop C code and deploy it to a Linux device running Azure IoT Edge.
You can use Azure 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
IoT Edge device that you set up in the quickstart. In this tutorial, you learn how to:
Use Visual Studio Code to create an IoT Edge Python module.
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 that's generated by your device. It
only sends messages upstream if the temperature is above a specified threshold. This type of analysis at the edge
is useful for reducing the amount of data that's communicated to and stored in the cloud.
If you don't have an Azure subscription, create a free account before you begin.

NOTE
The following guide is for the V1 Python SDK, which has since been deprecated. We are currently working to make this guide
V2 compatible. Please watch this space for updates.

Solution scope
This tutorial demonstrates how to develop a module in Python using Visual Studio Code, and how to deploy it
to a Linux device. IoT Edge does not support Python modules for Windows devices.
Use the following table to understand your options for developing and deploying Python modules to Linux:

PYTHON VISUAL STUDIO CODE VISUAL STUDIO 2017/2019

Linux AMD64

Linux ARM32

Prerequisites
Before beginning this tutorial, you should have gone through the previous tutorial to set up your development
environment for Linux container development: Develop IoT Edge modules for Linux devices. By completing either
of those tutorials, you should have the following prerequisites in place:
A free or standard-tier IoT Hub in Azure.
A Linux device running Azure IoT Edge
A container registry, like Azure Container Registry.
Visual Studio Code configured with the Azure IoT Tools.
Docker CE configured to run Linux containers.
To develop an IoT Edge module in Python, install the following additional prerequisites on your development
machine:
Python extension for Visual Studio Code.
Python.
Pip for installing Python packages (typically included with your Python installation).

NOTE
Ensure that your bin folder is on your path for your platform. Typically ~/.local/ for UNIX and macOS, or
%APPDATA%\Python on Windows.

Create a module project


The following steps create an IoT Edge Python module by using Visual Studio Code and the Azure IoT Tools.
Create a new project
Use the VS Code to create a Python solution template that you can build on top of.
1. In Visual Studio Code, select View > Terminal to open the VS Code integrated terminal.
2. Select View > Command Palette to open the VS Code command palette.
3. In the command palette, enter and run the command Azure: Sign in and follow the instructions to sign in
your Azure account. If you're already signed in, you can skip this step.
4. In the command palette, enter and run the command Azure IoT Edge: New IoT Edge solution. Follow
the prompts and provide the following information to create your solution:

FIELD VALUE

Select folder Choose the location on your development machine for VS


Code to create the solution files.

Provide a solution name Enter a descriptive name for your solution or accept the
default EdgeSolution.

Select module template Choose Python Module.

Provide a module name Name your module PythonModule.

Provide Docker image repository for the module An image repository includes the name of your container
registry and the name of your container image. Your
container image is prepopulated from the name you
provided in the last step. Replace localhost:5000 with the
login server value from your Azure container registry. You
can retrieve the login server from the Overview page of
your container registry in the Azure portal.

The final image repository looks like <registry


name>.azurecr.io/pythonmodule.
Add your registry credentials
The environment file stores the credentials for your container repository and shares them with the IoT Edge
runtime. The runtime needs these credentials to pull your private images onto the IoT Edge device.
1. In the VS Code explorer, open the .env file.
2. Update the fields with the username and password values that you copied from your Azure container registry.
3. Save the .env file.
Select your target architecture
Currently, Visual Studio Code can develop C modules for Linux AMD64 and Linux ARM32v7 devices. You need to
select which architecture you're targeting with each solution, because the container is built and run differently for
each architecture type. The default is Linux AMD64.
1. Open the command palette and search for Azure IoT Edge: Set Default Target Platform for Edge
Solution, or select the shortcut icon in the side bar at the bottom of the window.
2. In the command palette, select the target architecture from the list of options. For this tutorial, we're using
an Ubuntu virtual machine as the IoT Edge device, so will keep the default amd64.
Update the module with custom code
Each template includes sample code, which takes simulated sensor data from the SimulatedTemperatureSensor
module and routes it to the IoT hub. In this section, add the code that expands the PythonModule to analyze the
messages before sending them.
1. In the VS Code explorer, open modules > PythonModule > main.py.
2. At the top of the main.py file, import the json library:

import json

3. Add the TEMPERATURE_THRESHOLD and TWIN_CALLBACKS variables under the global counters.
The temperature threshold sets the value that the measured machine temperature must exceed for the data
to be sent to the IoT hub.

# global counters
TEMPERATURE_THRESHOLD = 25
TWIN_CALLBACKS = 0
RECEIVED_MESSAGES = 0

4. Replace the input1_listener function with the following code:


# Define behavior for receiving an input message on input1
# Because this is a filter module, we forward this message to the "output1" queue.
async def input1_listener(module_client):
global RECEIVED_MESSAGES
global TEMPERATURE_THRESHOLD
while True:
try:
input_message = await module_client.receive_message_on_input("input1") # blocking call
message = input_message.data
size = len(message)
message_text = message.decode('utf-8')
print ( " Data: <<<%s>>> & Size=%d" % (message_text, size) )
custom_properties = input_message.custom_properties
print ( " Properties: %s" % custom_properties )
RECEIVED_MESSAGES += 1
print ( " Total messages received: %d" % RECEIVED_MESSAGES )
data = json.loads(message_text)
if "machine" in data and "temperature" in data["machine"] and data["machine"]
["temperature"] > TEMPERATURE_THRESHOLD:
custom_properties["MessageType"] = "Alert"
print ( "Machine temperature %s exceeds threshold %s" % (data["machine"]
["temperature"], TEMPERATURE_THRESHOLD))
await module_client.send_message_to_output(input_message, "output1")
except Exception as ex:
print ( "Unexpected error in input1_listener: %s" % ex )

# twin_patch_listener is invoked when the module twin's desired properties are updated.
async def twin_patch_listener(module_client):
global TWIN_CALLBACKS
global TEMPERATURE_THRESHOLD
while True:
try:
data = await module_client.receive_twin_desired_properties_patch() # blocking call
print( "The data in the desired properties patch was: %s" % data)
if "TemperatureThreshold" in data:
TEMPERATURE_THRESHOLD = data["TemperatureThreshold"]
TWIN_CALLBACKS += 1
print ( "Total calls confirmed: %d\n" % TWIN_CALLBACKS )
except Exception as ex:
print ( "Unexpected error in twin_patch_listener: %s" % ex )

5. Update the listeners to also listen twin updates.

# Schedule task for C2D Listener


listeners = asyncio.gather(input1_listener(module_client), twin_patch_listener(module_client))

print ( "The sample is now waiting for messages. ")

6. Save the main.py file.


7. In the VS Code explorer, open the deployment.template.json file in your IoT Edge solution workspace.
8. Add the PythonModule module twin to the deployment manifest. Insert the following JSON content at
the bottom of the moduleContent section, after the $edgeHub module twin:

"PythonModule": {
"properties.desired":{
"TemperatureThreshold":25
}
}
9. Save the deployment.template.json file.

Build and push your module


In the previous section, you created an IoT Edge solution and added code to the PythonModule that will filter out
messages where the reported machine temperature is within the acceptable limits. Now you need to build the
solution as a container image and push it to your container registry.
1. Open the VS Code integrated terminal by selecting View > Terminal.
2. Sign in to Docker by entering the following command in the terminal. Sign in with the username, password,
and login server from your Azure container registry. You can retrieve these values from the Access keys
section of your registry in the Azure portal.

docker login -u <ACR username> -p <ACR password> <ACR login server>

You may receive a security warning recommending the use of --password-stdin . While that best practice is
recommended for production scenarios, it's outside the scope of this tutorial. For more information, see the
docker login reference.
3. In the VS Code explorer, right-click the deployment.template.json file and select Build and Push IoT
Edge solution.
The build and push command starts three operations. First, it creates a new folder in the solution called
config that holds the full deployment manifest, built out of information in the deployment template and
other solution files. Second, it runs docker build to build the container image based on the appropriate
dockerfile for your target architecture. Then, it runs docker push to push the image repository to your
container registry.

Deploy modules to device


Use the Visual Studio Code explorer and the Azure IoT Tools extension to deploy the module project to your IoT
Edge device. You already have a deployment manifest prepared for your scenario, the deployment.json file in the
config folder. All you need to do now is select a device to receive the deployment.
Make sure that your IoT Edge device is up and running.
1. In the Visual Studio Code explorer, expand the Azure IoT Hub Devices section to see your list of IoT
devices.
2. Right-click the name of your IoT Edge device, then select Create Deployment for Single Device.
3. Select the deployment.json file in the config folder and then click Select Edge Deployment Manifest.
Do not use the deployment.template.json file.
4. Click the refresh button. You should see the new PythonModule running along with the
SimulatedTemperatureSensor module and the $edgeAgent and $edgeHub.

View generated data


Once you apply the deployment manifest to your IoT Edge device, the IoT Edge runtime on the device collects the
new deployment information and starts executing on it. Any modules running on the device that aren't included in
the deployment manifest are stopped. Any modules missing from the device are started.
You can view the status of your IoT Edge device using the Azure IoT Hub Devices section of the Visual Studio
Code explorer. Expand the details of your device to see a list of deployed and running modules.
1. In the Visual Studio Code explorer, right-click the name of your IoT Edge device and select Start
Monitoring Built-in Event Endpoint.
2. View the messages arriving at your IoT Hub. It may take a while for the messages to arrive, because the IoT
Edge device has to receive its new deployment and start all the modules. Then, the changes we made to the
PythonModule code wait until the machine temperature reaches 25 degrees before sending messages. It
also adds the message type Alert to any messages that reach that temperature threshold.

Edit the module twin


We used the PythonModule module twin in the deployment manifest to set the temperature threshold at 25
degrees. You can use the module twin to change the functionality without having to update the module code.
1. In Visual Studio Code, expand the details under your IoT Edge device to see the running modules.
2. Right-click PythonModule and select Edit module twin.
3. Find TemperatureThreshold in the desired properties. Change its value to a new temperature 5 degrees
to 10 degrees higher than the latest reported temperature.
4. Save the module twin file.
5. Right-click anywhere in the module twin editing pane and select Update module twin.
6. Monitor the incoming device-to-cloud messages. You should see the messages stop until the new
temperature threshold is reached.

Clean up resources
If you plan to continue to the next recommended article, you can keep the resources and configurations that you
created and reuse them. You can also keep using the same IoT Edge device as a test device.
Otherwise, you can delete the local configurations and the Azure resources that you used in this article to avoid
charges.
Delete Azure resources
Deleting Azure resources and resource groups is irreversible. Make sure that you don't accidentally delete the
wrong resource group or resources. If you created the IoT hub inside an existing resource group that has resources
that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.
To delete the resources:
1. Sign in to the Azure portal and select Resource groups.
2. Select the name of the resource group that contains your IoT Edge test resources.
3. Review the list of resources contained in your resource group. If you want to delete all of them, you can
select Delete resource group. If you want to delete only some of them, you can click into each resource to
delete them individually.

Next steps
In this tutorial, you created an IoT Edge module that contains code to filter raw data generated by your IoT Edge
device. When you're ready to build your own modules, you can learn more about developing your own IoT Edge
modules or how to develop modules with Visual Studio Code. For examples of IoT Edge modules, including the
simulated temperature module, see IoT Edge module samples and IoT Python SDK samples.
You can continue on to the next tutorials to learn how Azure IoT Edge can help you deploy Azure cloud services to
process and analyze data at the edge.
Functions Stream Analytics Machine Learning Custom Vision Service
Tutorial: Deploy Azure functions as IoT Edge
modules
12/1/2019 • 9 minutes to read • Edit Online

You can use Azure Functions to deploy code that implements your business logic directly to your Azure IoT Edge
devices. This tutorial walks you through creating and deploying an Azure function that filters sensor data on the
simulated IoT Edge device. You use the simulated IoT Edge device that you created in the Deploy Azure IoT Edge
on a simulated device on Windows or Linux quickstarts. In this tutorial, you learn how to:
Use Visual Studio Code to create an Azure function.
Use VS Code and Docker to create a Docker image and publish it to a container registry.
Deploy the module from the container registry to your IoT Edge device.
View filtered data.

NOTE
Azure Function modules on Azure IoT Edge are in public preview.

The Azure function that you create in this tutorial filters the temperature data that's generated by your device.
The function only sends messages upstream to Azure IoT Hub when the temperature is above a specified
threshold.
If you don't have an Azure subscription, create a free account before you begin.

Prerequisites
Before beginning this tutorial, you should have gone through the previous tutorial to set up your development
environment for Linux container development: Develop IoT Edge modules for Linux devices. By completing that
tutorial, you should have the following prerequisites in place:
A free or standard-tier IoT Hub in Azure.
A Linux device running Azure IoT Edge
A container registry, like Azure Container Registry.
Visual Studio Code configured with the Azure IoT Tools.
Docker CE configured to run Linux containers.
To develop an IoT Edge module in with Azure Functions, install the following additional prerequisites on your
development machine:
C# for Visual Studio Code (powered by OmniSharp) extension.
The .NET Core 2.1 SDK.

Create a function project


The Azure IoT Tools for Visual Studio Code that you installed in the prerequisites provides management
capabilities as well as some code templates. In this section, you use Visual Studio Code to create an IoT Edge
solution that contains an Azure function.
Create a new project
Create a C# Function solution template that you can customize with your own code.
1. Open Visual Studio Code on your development machine.
2. Open the VS Code command palette by selecting View > Command Palette.
3. In the command palette, enter and run the command Azure IoT Edge: New IoT Edge solution. Follow
the prompts in the command palette to create your solution.

FIELD VALUE

Select folder Choose the location on your development machine for


VS Code to create the solution files.

Provide a solution name Enter a descriptive name for your solution, like
FunctionSolution, or accept the default.

Select module template Choose Azure Functions - C#.

Provide a module name Name your module CSharpFunction.

Provide Docker image repository for the module An image repository includes the name of your container
registry and the name of your container image. Your
container image is prepopulated from the last step.
Replace localhost:5000 with the login server value from
your Azure container registry. You can retrieve the login
server from the Overview page of your container registry
in the Azure portal. The final string looks like <registry
name>.azurecr.io/CSharpFunction.

Add your registry credentials


The environment file stores the credentials for your container registry and shares them with the IoT Edge
runtime. The runtime needs these credentials to pull your private images onto the IoT Edge device.
1. In the VS Code explorer, open the .env file.
2. Update the fields with the username and password values that you copied from your Azure container
registry.
3. Save this file.
Select your target architecture
Currently, Visual Studio Code can develop C modules for Linux AMD64 and Linux ARM32v7 devices. You need
to select which architecture you're targeting with each solution, because the container is built and run differently
for each architecture type. The default is Linux AMD64.
1. Open the command palette and search for Azure IoT Edge: Set Default Target Platform for Edge
Solution, or select the shortcut icon in the side bar at the bottom of the window.
2. In the command palette, select the target architecture from the list of options. For this tutorial, we're using
an Ubuntu virtual machine as the IoT Edge device, so will keep the default amd64.
Update the module with custom code
Let's add some additional code so that the module processes the messages at the edge before forwarding them
to IoT Hub.
1. In Visual Studio Code, open modules > CSharpFunction > CSharpFunction.cs.
2. Replace the contents of the CSharpFunction.cs file with the following code. This code receives telemetry
about ambient and machine temperature, and only forwards the message on to IoT Hub if the machine
temperature is above a defined threshold.

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Client;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.EdgeHub;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace Functions.Samples
{
public static class CSharpFunction
{
[FunctionName("CSharpFunction")]
public static async Task FilterMessageAndSendMessage(
[EdgeHubTrigger("input1")] Message messageReceived,
[EdgeHub(OutputName = "output1")] IAsyncCollector<Message> output,
ILogger logger)
{
const int temperatureThreshold = 20;
byte[] messageBytes = messageReceived.GetBytes();
var messageString = System.Text.Encoding.UTF8.GetString(messageBytes);

if (!string.IsNullOrEmpty(messageString))
{
logger.LogInformation("Info: Received one non-empty message");
// Get the body of the message and deserialize it.
var messageBody = JsonConvert.DeserializeObject<MessageBody>(messageString);

if (messageBody != null && messageBody.machine.temperature > temperatureThreshold)


{
// Send the message to the output as the temperature value is greater than the
// Send the message to the output as the temperature value is greater than the
threshold.
using (var filteredMessage = new Message(messageBytes))
{
// Copy the properties of the original message into the new Message object.
foreach (KeyValuePair<string, string> prop in messageReceived.Properties)
{filteredMessage.Properties.Add(prop.Key, prop.Value);}
// Add a new property to the message to indicate it is an alert.
filteredMessage.Properties.Add("MessageType", "Alert");
// Send the message.
await output.AddAsync(filteredMessage);
logger.LogInformation("Info: Received and transferred a message with
temperature above the threshold");
}
}
}
}
}
//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;}
}
}

3. Save the file.

Build your IoT Edge solution


In the previous section, you created an IoT Edge solution and added code to the CSharpFunction to filter out
messages where the reported machine temperature is less than the acceptable threshold. Now you need to build
the solution as a container image and push it to your container registry.
In this section, you provide the credentials for your container registry for the second time (the first was in the
.env file of your IoT Edge solution) by signing in locally from your development machine so that Visual Studio
Code can push images to your registry.
1. Open the VS Code integrated terminal by selecting View > Terminal.
2. Sign in to your container registry by entering the following command in the integrated terminal. Use the
username and login server that you copied from your Azure container registry earlier.

docker login -u <ACR username> <ACR login server>

When you're prompted for the password, paste the password (it won't be visible in the terminal window )
for your container registry and press Enter.

Password: <paste in the ACR password and press enter>


Login Succeeded
3. In the VS Code explorer, right-click the deployment.template.json file and select Build and Push IoT
Edge solution.
When you tell Visual Studio Code to build your solution, it first takes the information in the deployment template
and generates a deployment.json file in a new folder named config. Then it runs two commands in the
integrated terminal: docker build and docker push . These two commands build your code, containerize the
functions, and then push the code to the container registry that you specified when you initialized the solution.

View your container image


Visual Studio Code outputs a success message when your container image is pushed to your container registry.
If you want to confirm the successful operation for yourself, you can view the image in the registry.
1. In the Azure portal, browse to your Azure container registry.
2. Select Repositories.
3. You should see the csharpfunction repository in the list. Select this repository to see more details.
4. In the Tags section, you should see the 0.0.1-amd64 tag. This tag indicates the version and platform of the
image that you built. These values are set in the module.json file in the CSharpFunction folder.

Deploy and run the solution


You can use the Azure portal to deploy your function module to an IoT Edge device like you did in the
quickstarts. You can also deploy and monitor modules from within Visual Studio Code. The following sections
use the Azure IoT Tools for VS Code that was listed in the prerequisites. Install the extension now, if you didn't
already.
1. In the VS Code explorer, expand the Azure IoT Hub Devices section.
2. Right-click the name of your IoT Edge device, and then select Create Deployment for single device.
3. Browse to the solution folder that contains the CSharpFunction. Open the config folder, select the
deployment.json file, and then choose Select Edge Deployment Manifest.
4. Refresh the Azure IoT Hub Devices section. You should see the new CSharpFunction running along
with the SimulatedTemperatureSensor module and the $edgeAgent and $edgeHub. It may take a
few moments for the new modules to show up. Your IoT Edge device has to retrieve its new deployment
information from IoT Hub, start the new containers, and then report the status back to IoT Hub.
View generated data
You can see all of the messages that arrive at your IoT hub by running Azure IoT Hub: Start Monitoring Built-
in Event Endpoint in the command palette.
You can also filter the view to see all of the messages that arrive at your IoT hub from a specific device. Right-
click the device in the Azure IoT Hub Devices section and select Start Monitoring Built-in Event Endpoint.
To stop monitoring messages, run the command Azure IoT Hub: Stop Monitoring Built-in Event Endpoint
in the command palette.

Clean up resources
If you plan to continue to the next recommended article, you can keep the resources and configurations that you
created and reuse them. You can also keep using the same IoT Edge device as a test device.
Otherwise, you can delete the local configurations and the Azure resources that you created in this article to
avoid charges.
Delete Azure resources
Deleting Azure resources and resource groups is irreversible. Make sure that you don't accidentally delete the
wrong resource group or resources. If you created the IoT hub inside an existing resource group that has
resources that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.
To delete the resources:
1. Sign in to the Azure portal and select Resource groups.
2. Select the name of the resource group that contains your IoT Edge test resources.
3. Review the list of resources contained in your resource group. If you want to delete all of them, you can
select Delete resource group. If you want to delete only some of them, you can click into each resource
to delete them individually.

Next steps
In this tutorial, you created an Azure function module with code to filter raw data that's generated by your IoT
Edge device. When you're ready to build your own modules, you can learn more about how to Develop with
Azure IoT Edge for Visual Studio Code.
Continue on to the next tutorials to learn other ways that Azure IoT Edge can help you turn data into business
insights at the edge.
Find averages by using a floating window in Azure Stream Analytics
Tutorial: Deploy Azure Stream Analytics as an IoT
Edge module
12/2/2019 • 9 minutes to read • Edit Online

Many IoT solutions use analytics services to gain insight about data as it arrives in the cloud from IoT devices.
With Azure IoT Edge, you can take Azure Stream Analytics logic and move it onto the device itself. By processing
telemetry streams at the edge, you can reduce the amount of uploaded data and reduce the time it takes to react
to actionable insights.
Azure IoT Edge and Azure Stream Analytics are integrated so that you can create an Azure Stream Analytics job
in the Azure portal and then deploy it as an IoT Edge module with no additional code.
Azure Stream Analytics provides a richly structured query syntax for data analysis, both in the cloud and on IoT
Edge devices. For more information, see Azure Stream Analytics documentation.
The Stream Analytics module in this tutorial calculates the average temperature over a rolling 30-second
window. When that average reaches 70, the module sends an alert for the device to take action. In this case, that
action is to reset the simulated temperature sensor. In a production environment, you might use this functionality
to shut off a machine or take preventative measures when the temperature reaches dangerous levels.
In this tutorial, you learn how to:
Create an Azure Stream Analytics job to process data on the edge.
Connect the new Azure Stream Analytics job with other IoT Edge modules.
Deploy the Azure Stream Analytics job to an IoT Edge device from the Azure portal.

If you don't have an Azure subscription, create a free account before you begin.

Prerequisites
An Azure IoT Edge device:
You can use an Azure virtual machine as an IoT Edge device by following the steps in the quickstart for Linux
or Windows devices.
Cloud resources:
A free or standard-tier IoT Hub in Azure.
Create an Azure Stream Analytics job
In this section, you create an Azure Stream Analytics job that will do the following steps:
Receive data from your IoT Edge device.
Query the telemetry data for values outside a set range.
Take action on the IoT Edge device based on the query results.
Create a storage account
When you create an Azure Stream Analytics job to run on an IoT Edge device, it needs to be stored in a way that
can be called from the device. You can use an existing Azure storage account, or create a new one now.
1. In the Azure portal, go to Create a resource > Storage > Storage account.
2. Provide the following values to create your storage account:

FIELD VALUE

Subscription Choose the same subscription as your IoT hub.

Resource group We recommend that you use the same resource group
for all of the test resources that you create during the IoT
Edge quickstarts and tutorials. For example,
IoTEdgeResources.

Name Provide a unique name for your storage account.

Location Choose a location close to you.

3. Keep the default values for the other fields and select Review + Create.
4. Review your settings then select Create.
Create a new job
1. In the Azure portal, go to Create a resource > Internet of Things > Stream Analytics job.
2. Provide the following values to create your job:

FIELD VALUE

Job name Provide a name for your job. For example, IoTEdgeJob

Subscription Choose the same subscription as your IoT hub.

Resource group We recommend that you use the same resource group
for all of the test resources that you create during the IoT
Edge quickstarts and tutorials. For example,
IoTEdgeResources.

Location Choose a location close to you.

Hosting environment Select Edge.

3. Select Create.
Configure your job
Once your Stream Analytics job is created in the Azure portal, you can configure it with an input, an output, and a
query to run on the data that passes through.
Using the three elements of input, output, and query, this section creates a job that receives temperature data
from the IoT Edge device. It analyzes that data in a rolling 30-second window. If the average temperature in that
window goes over 70 degrees, then an alert is sent to the IoT Edge device. You'll specify exactly where the data
comes from and goes in the next section when you deploy the job.
1. Navigate to your Stream Analytics job in the Azure portal.
2. Under Job Topology, select Inputs then Add stream input.

3. Choose Edge Hub from the drop-down list.


4. In the New input pane, enter temperature as the input alias.
5. Keep the default values for the other fields, and select Save.
6. Under Job Topology, open Outputs then select Add.
7. Choose Edge Hub from the drop-down list.
8. In the New output pane, enter alert as the output alias.
9. Keep the default values for the other fields, and select Save.
10. Under Job Topology, select Query.
11. Replace the default text with the following query. The SQL code sends a reset command to the alert
output if the average machine temperature in a 30-second window reaches 70 degrees. The reset
command has been pre-programmed into the sensor as an action that can be taken.

SELECT
'reset' AS command
INTO
alert
FROM
temperature TIMESTAMP BY timeCreated
GROUP BY TumblingWindow(second,30)
HAVING Avg(machine.temperature) > 70

12. Select Save.


Configure IoT Edge settings
To prepare your Stream Analytics job to be deployed on an IoT Edge device, you need to associate the job with a
container in a storage account. When you go to deploy your job, the job definition is exported to the storage
container.
1. Under Configure, select Storage account settings then select Add storage account.
2. Select the Storage account that you created at the beginning of this tutorial from the drop-down menu.
3. For the Container field, select Create new and provide a name for the storage container.
4. Select Save.

Deploy the job


You are now ready to deploy the Azure Stream Analytics job on your IoT Edge device.
In this section, you use the Set Modules wizard in the Azure portal to create a deployment manifest. A
deployment manifest is a JSON file that describes all the modules that will be deployed to a device, the container
registries that store the module images, how the modules should be managed, and how the modules can
communicate with each other. Your IoT Edge device retrieves its deployment manifest from IoT Hub, then uses
the information in it to deploy and configure all of its assigned modules.
For this tutorial, you deploy two modules. The first is SimulatedTemperatureSensor, which is a module that
simulates a temperature and humidity sensor. The second is your Stream Analytics job. The sensor module
provides the stream of data that your job query will analyze.
1. In the Azure portal, navigate to your IoT hub.
2. Go to IoT Edge, and then open the details page for your IoT Edge device.
3. Select Set modules.
4. If you previously deployed the SimulatedTemperatureSensor module on this device, it might
autopopulate. If it does not, add the module with the following steps:
a. Click Add and select IoT Edge Module.
b. For the name, type SimulatedTemperatureSensor.
c. For the image URI, enter mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0.
d. Leave the other settings unchanged and select Save.
5. Add your Azure Stream Analytics Edge job with the following steps:
a. Click Add and select Azure Stream Analytics Module.
b. Select your subscription and the Azure Stream Analytics Edge job that you created.
c. Select Save.
Once you save your changes, the details of your Stream Analytics job are published to the storage
container that you created.
6. When the Stream Analytics module is added to the list of modules, select Configure to see how it's
structured.
The image URI points to a standard Azure Stream Analytics image. This one image is used for every
Stream Analytics module that gets deployed to an IoT Edge device.
The module twin is configured with a desired property called ASAJobInfo. The value of that property
points to the job definition in your storage container. This property is how the Stream Analytics image is
configured with your specific job details.
By default, the Stream Analytics module takes the same name as the job it's based on. You can change the
module name on this page if you like, but it's not necessary.
7. Close the module configuration page.
8. Make a note of the name of your Stream Analytics module because you'll need it in the next step, then
select Next to continue.
9. Replace the default value in Routes with the following code. Update all three instances of {moduleName}
with the name of your Azure Stream Analytics module.

{
"routes": {
"telemetryToCloud": "FROM /messages/modules/SimulatedTemperatureSensor/* INTO $upstream",
"alertsToCloud": "FROM /messages/modules/{moduleName}/* INTO $upstream",
"alertsToReset": "FROM /messages/modules/{moduleName}/* INTO
BrokeredEndpoint(\"/modules/SimulatedTemperatureSensor/inputs/control\")",
"telemetryToAsa": "FROM /messages/modules/SimulatedTemperatureSensor/* INTO
BrokeredEndpoint(\"/modules/{moduleName}/inputs/temperature\")"
}
}

The routes that you declare here define the flow of data through the IoT Edge device. The telemetry data
from SimulatedTemperatureSensor are sent to IoT Hub and to the temperature input that was
configured in the Stream Analytics job. The alert output messages are sent to IoT Hub and to the
SimulatedTemperatureSensor module to trigger the reset command.
10. Select Next.
11. In the Review Deployment step, you can see how the information you provided in the wizard is
converted into a JSON deployment manifest. When you're done reviewing the manifest, select Submit.
12. Return to the device details page, and then select Refresh.
You should see the new Stream Analytics module running, along with the IoT Edge agent and IoT Edge
hub modules. It may take a few minutes for the information to reach your IoT Edge device, and then for
the new modules to start. If you don't see the modules running right away, continue refreshing the page.
View data
Now you can go to your IoT Edge device to check out the interaction between the Azure Stream Analytics
module and the SimulatedTemperatureSensor module.
1. Check that all the modules are running in Docker:

iotedge list

2. View all system logs and metrics data. Use the Stream Analytics module name:

iotedge logs -f {moduleName}

3. View the reset command affect the SimulatedTemperatureSensor by viewing the sensor logs:

iotedge logs SimulatedTemperatureSensor

You can watch the machine's temperature gradually rise until it reaches 70 degrees for 30 seconds. Then
the Stream Analytics module triggers a reset, and the machine temperature drops back to 21.

Clean up resources
If you plan to continue to the next recommended article, you can keep the resources and configurations that you
created and reuse them. You can also keep using the same IoT Edge device as a test device.
Otherwise, you can delete the local configurations and the Azure resources that you used in this article to avoid
charges.
Delete Azure resources
Deleting Azure resources and resource groups is irreversible. Make sure that you don't accidentally delete the
wrong resource group or resources. If you created the IoT hub inside an existing resource group that has
resources that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.
To delete the resources:
1. Sign in to the Azure portal and select Resource groups.
2. Select the name of the resource group that contains your IoT Edge test resources.
3. Review the list of resources contained in your resource group. If you want to delete all of them, you can
select Delete resource group. If you want to delete only some of them, you can click into each resource
to delete them individually.

Next steps
In this tutorial, you configured an Azure Streaming Analytics job to analyze data from your IoT Edge device. You
then loaded this Azure Stream Analytics module on your IoT Edge device to process and react to temperature
increase locally, as well as sending the aggregated data stream to the cloud. To see how Azure IoT Edge can
create more solutions for your business, continue on to the other tutorials.
Deploy an Azure Machine Learning model as a module
Tutorial: Deploy Azure Machine Learning as an IoT
Edge module (preview)
12/2/2019 • 7 minutes to read • Edit Online

Use Azure Notebooks to develop a machine learning module and deploy it to a Linux device running Azure 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 deploying an Azure Machine Learning module that predicts when a
device fails based on simulated machine temperature data. For more information about Azure Machine Learning
on IoT Edge, see Azure Machine Learning documentation.
The Azure Machine Learning module that you create in this tutorial reads the environmental data generated by
your device and labels the messages as anomalous or not.
In this tutorial, you learn how to:
Create an Azure Machine Learning module
Push a module container to an Azure container registry
Deploy an Azure Machine Learning module to your IoT Edge device
View generated data

NOTE
Azure Machine Learning modules on Azure IoT Edge are in public preview.

If you don't have an Azure subscription, create a free account before you begin.

Prerequisites
An Azure IoT Edge device:
You can use an Azure virtual machine as an IoT Edge device by following the steps in the quickstart for Linux.
The Azure Machine Learning module doesn't support Windows containers.
The Azure Machine Learning module doesn't support ARM processors.
Cloud resources:
A free or standard-tier IoT Hub in Azure.
An Azure Machine Learning workspace. Follow the instructions in Use the Azure portal to get started with
Azure Machine Learning to create one and learn how to use it.
Make a note of the workspace name, resource group, and subscription ID. These values are all
available on the workspace overview in the Azure portal. You'll use these values later in the tutorial to
connect an Azure notebook to your workspace resources.

Create and deploy Azure Machine Learning module


In this section, you convert trained machine learning model files and into an Azure Machine Learning container.
All the components required for the Docker image are in the AI Toolkit for Azure IoT Edge Git repo. Follow these
steps to upload that repository into Microsoft Azure Notebooks to create the container and push it to Azure
Container Registry.
1. Navigate to your Azure Notebooks projects. You can get there from your Azure Machine Learning
workspace in the Azure portal or by signing in to Microsoft Azure Notebooks with your Azure account.
2. Select Upload GitHub Repo.
3. Provide the following GitHub repository name: Azure/ai-toolkit-iot-edge . Uncheck the Public box if you
want to keep your project private. Select Import.
4. Once the import is finished, navigate into the new ai-toolkit-iot-edge project and open the IoT Edge
anomaly detection tutorial folder.
5. Verify that your project is running. If not, select Run on Free Compute.

6. Open the aml_config/config.json file.


7. Edit the config file to include the values for your Azure subscription ID, a resource group in your
subscription, and your Azure Machine Learning workspace name. You can get all these values from the
Overview section of your workspace in Azure.
8. Save the config file.
9. Open the 00-anomaly-detection-tutorial.ipynb file.
10. When prompted, select the Python 3.6 kernel then select Set Kernel.
11. Edit the first cell in the notebook according to the instructions in the comments. Use the same resource
group, subscription ID, and workspace name that you added to the config file.
12. Run the cells in the notebook by selecting them and selecting Run or pressing Shift + Enter .

TIP
Some of the cells in the anomaly detection tutorial notebook are optional, because they create resources that some
users may or may not have yet, like an IoT Hub. If you put your existing resource information in the first cell, you'll
receive errors if you run the cells that create new resources because Azure won't create duplicate resources. This is
fine, and you can ignore the errors or skip those optional sections entirely.
By completing all the steps in the notebook, you trained an anomaly detection model, built it as a Docker
container image, and pushed that image to Azure Container Registry. Then, you tested the model and finally
deployed it to your IoT Edge device.

View container repository


Check that your container image was successfully created and stored in the Azure container registry associated
with your machine learning environment. The notebook that you used in the previous section automatically
provided the container image and the registry credentials to your IoT Edge device, but you should know where
they're stored so that you can find the information yourself later.
1. In the Azure portal, navigate to your Machine Learning service workspace.
2. The Overview section lists the workspace details as well its associated resources. Select the Registry
value, which should be your workspace name followed by random numbers.
3. In the container registry, select Repositories. You should see a repository called
tempanomalydetection that was created by the notebook you ran in the earlier section.
4. Select tempanomalydetection. You should see that the repository has one tag: 1.
Now that you know the registry name, repository name, and tag, you know the full image path of the
container. Image paths look like <registry_name>.azurecr.io/tempanomalydetection:1. You can use
the image path to deploy this container to IoT Edge devices.
5. In the container registry, select Access keys. You should see a number of access credentials, including
Login server and the Username, and Password for an admin user.
These credentials can be included in the deployment manifest to give your IoT Edge device access to pull
container images from the registry.
Now you know where the Machine Learning container image is stored. The next section walks through steps to
view the container running as a module on your IoT Edge device.

View generated data


You can view messages being generated by each IoT Edge module, and you can view messages that are
delivered to your IoT hub.
View data on your IoT Edge device
On your IoT Edge device, you can view the messages being sent from every individual module.
You may need to use sudo for elevated permissions to run iotedge commands. Signing out and signing back in
to your device automatically updates your permissions.
1. View all modules on your IoT Edge device.

iotedge list

2. View the messages being sent from a specific device. Use the module name from the output of the
previous command.

iotedge logs <module_name> -f

View data arriving at your IoT hub


You can view the device-to-cloud messages that your IoT hub receives by using the Azure IoT Hub Toolkit
extension for Visual Studio Code (formerly Azure IoT Toolkit extension).
The following steps show you how to set up Visual Studio Code to monitor device-to-cloud messages that arrive
at your IoT hub.
1. In Visual Studio Code, select IoT Hub Devices.
2. Select ... then select Set IoT Hub Connection String from the menu.

3. In the text box that opens at the top of the page, enter the iothubowner connection string for your IoT
Hub. Your IoT Edge device should appear in the IoT Hub Devices list.
4. Select ... again then select Start Monitoring Built-in Event Endpoint.
5. Observe the messages coming from tempSensor every five seconds. The message body contains a
property called anomaly, which the machinelearningmodule provides with a true or false value. The
AzureMLResponse property contains the value "OK" if the model ran successfully.

Clean up resources
If you plan to continue to the next recommended article, you can keep the resources and configurations that you
created and reuse them. You can also keep using the same IoT Edge device as a test device.
Otherwise, you can delete the local configurations and the Azure resources that you created in this article to
avoid charges.
Delete Azure resources
Deleting Azure resources and resource groups is irreversible. Make sure that you don't accidentally delete the
wrong resource group or resources. If you created the IoT hub inside an existing resource group that has
resources that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.
To delete the resources:
1. Sign in to the Azure portal and select Resource groups.
2. Select the name of the resource group that contains your IoT Edge test resources.
3. Review the list of resources contained in your resource group. If you want to delete all of them, you can
select Delete resource group. If you want to delete only some of them, you can click into each resource
to delete them individually.

Next steps
In this tutorial, you deployed an IoT Edge module powered by Azure Machine Learning. You can continue on to
any of the other tutorials to learn about other ways that Azure IoT Edge can help you turn data into business
insights at the edge.
Classify images with Custom Vision service
Tutorial: Perform image classification at the edge
with Custom Vision Service
12/2/2019 • 16 minutes to read • Edit Online

Azure IoT Edge can make your IoT solution more efficient by moving workloads out of the cloud and to the edge.
This capability lends itself well to services that process a lot of data, like computer vision models. The Custom
Vision Service lets you build custom image classifiers and deploy them to devices as containers. Together, these
two services enable you to find insights from images or video streams without having to transfer all of the data
off site first. Custom Vision provides a classifier that compares an image against a trained model to generate
insights.
For example, Custom Vision on an IoT Edge device could determine whether a highway is experiencing higher or
lower traffic than normal, or whether a parking garage has available parking spots in a row. These insights can be
shared with another service to take action.
In this tutorial, you learn how to:
Build an image classifier with Custom Vision.
Develop an IoT Edge module that queries the Custom Vision web server on your device.
Send the results of the image classifier to IoT Hub.

If you don't have an Azure subscription, create a free account before you begin.

Prerequisites
TIP
This tutorial is a simplified version of the Custom Vision and Azure IoT Edge on a Raspberry Pi 3 sample project. This
tutorial was designed to run on a cloud VM and uses static images to train and test the image classifier, which is useful for
someone just starting to evaluate Custom Vision on IoT Edge. The sample project uses physical hardware and sets up a live
camera feed to train and test the image classifier, which is useful for someone who wants to try a more detailed, real-life
scenario.
Before beginning this tutorial, you should have gone through the previous tutorial to set up your environment
for Linux container development: Develop IoT Edge modules for Linux devices. By completing that tutorial, you
should have the following prerequisites in place:
A free or standard-tier IoT Hub in Azure.
A Linux device running Azure IoT Edge
A container registry, like Azure Container Registry.
Visual Studio Code configured with the Azure IoT Tools.
Docker CE configured to run Linux containers.
To develop an IoT Edge module with the Custom Vision service, install the following additional prerequisites on
your development machine:
Python
Git
Python extension for Visual Studio Code

Build an image classifier with Custom Vision


To build an image classifier, you need to create a Custom Vision project and provide training images. For more
information about the steps that you take in this section, see How to build a classifier with Custom Vision.
Once your image classifier is built and trained, you can export it as a Docker container and deploy it to an IoT
Edge device.
Create a new project
1. In your web browser, navigate to the Custom Vision web page.
2. Select Sign in and sign in with the same account that you use to access Azure resources.
3. Select New project.
4. Create your project with the following values:

FIELD VALUE

Name Provide a name for your project, like EdgeTreeClassifier.

Description Optional project description.

Resource Select one of your Azure resource groups that includes a


Custom Vision Service resource or create new if you
haven't yet added one.

Project Types Classification

Classification Types Multiclass (single tag per image)

Domains General (compact)

Export Capabilities Basic platforms (Tensorflow, CoreML, ONNX, ...)

5. Select Create project.


Upload images and train your classifier
Creating an image classifier requires a set of training images, as well as test images.
1. Clone or download sample images from the Cognitive-CustomVision-Windows repo onto your local
development machine.

git clone https://github.com/Microsoft/Cognitive-CustomVision-Windows.git

2. Return to your Custom Vision project and select Add images.


3. Browse to the git repo that you cloned locally, and navigate to the first image folder, Cognitive-
CustomVision-Windows / Samples / Images / Hemlock. Select all 10 images in the folder and then
Open.
4. Add the tag hemlock to this group of images and press enter to apply the tag.
5. Select Upload 10 files.

6. When the images are uploaded successfully, select Done.


7. Select Add images again.
8. Browse to the second image folder, Cognitive-CustomVision-Windows / Samples / Images /
Japanese Cherry. Select all 10 images in the folder and then Open.
9. Add the tag japanese cherry to this group of images and press enter to apply the tag.
10. Select Upload 10 files. When the images are uploaded successfully, select Done.
11. When both sets of images are tagged and uploaded, select Train to train the classifier.
Export your classifier
1. After training your classifier, select Export on the Performance page of the classifier.
2. Select DockerFile for the platform.
3. Select Linux for the version.
4. Select Export.

5. When the export is complete, select Download and save the .zip package locally on your computer.
Extract all files from the package. You'll use these files to create an IoT Edge module that contains the
image classification server.
When you reach this point, you've finished creating and training your Custom Vision project. You'll use the
exported files in the next section, but you're done with the Custom Vision web page.

Create an IoT Edge solution


Now you have the files for a container version of your image classifier on your development machine. In this
section, you configure the image classifier container to run as an IoT Edge module. You also create a second
module that will be deployed alongside the image classifier. The second module posts requests to the classifier
and sends the results as messages to IoT Hub.
Create a new solution
A solution is a logical way of developing and organizing multiple modules for a single IoT Edge deployment. A
solution contains code for one or more modules as well as the deployment manifest that declares how to
configure them on an IoT Edge device.
1. Select View > Command Palette to open the VS Code command palette.
2. In the command palette, enter and run the command Azure IoT Edge: New IoT Edge solution. In the
command palette, provide the following information to create your solution:

FIELD VALUE

Select folder Choose the location on your development machine for


VS Code to create the solution files.

Provide a solution name Enter a descriptive name for your solution, like
CustomVisionSolution, or accept the default.

Select module template Choose Python Module.

Provide a module name Name your module classifier.

It's important that this module name be lowercase. IoT


Edge is case-sensitive when referring to modules, and
this solution uses a library that formats all requests in
lowercase.

Provide Docker image repository for the module An image repository includes the name of your container
registry and the name of your container image. Your
container image is prepopulated from the last step.
Replace localhost:5000 with the login server value from
your Azure container registry. You can retrieve the login
server from the Overview page of your container registry
in the Azure portal.

The final string looks like <registry


name>.azurecr.io/classifier.

The Visual Studio Code window loads your IoT Edge solution workspace.
Add your registry credentials
The environment file stores the credentials for your container registry and shares them with the IoT Edge
runtime. The runtime needs these credentials to pull your private images onto the IoT Edge device.
1. In the VS Code explorer, open the .env file.
2. Update the fields with the username and password values that you copied from your Azure container
registry.
3. Save this file.
Select your target architecture
Currently, Visual Studio Code can develop modules for Linux AMD64 and Linux ARM32v7 devices. You need to
select which architecture you're targeting with each solution, because the container is built and run differently for
each architecture type. The default is Linux AMD64, which is what we'll use for this tutorial.
1. Open the command palette and search for Azure IoT Edge: Set Default Target Platform for Edge
Solution, or select the shortcut icon in the side bar at the bottom of the window.
2. In the command palette, select the target architecture from the list of options. For this tutorial, we're using
an Ubuntu virtual machine as the IoT Edge device, so will keep the default amd64.
Add your image classifier
The Python module template in Visual Studio code contains some sample code that you can run to test IoT Edge.
You won't use that code in this scenario. Instead, use the steps in this section to replace the sample code with the
image classifier container that you exported previously.
1. In your file explorer, browse to the Custom Vision package that you downloaded and extracted. Copy all
the contents from the extracted package. It should be two folders, app and azureml, and two files,
Dockerfile and README.
2. In your file explorer, browse to the directory where you told Visual Studio Code to create your IoT Edge
solution.
3. Open the classifier module folder. If you used the suggested names in the previous section, the folder
structure looks like CustomVisionSolution / modules / classifier.
4. Paste the files into the classifier folder.
5. Return to the Visual Studio Code window. Your solution workspace should now show the image classifier
files in the module folder.

6. Open the module.json file in the classifier folder.


7. Update the platforms parameter to point to the new Dockerfile that you added, and remove all the
options besides AMD64, which is the only architecture we're using for this tutorial.

"platforms": {
"amd64": "./Dockerfile"
}
8. Save your changes.
Create a simulated camera module
In a real Custom Vision deployment, you would have a camera providing live images or video streams. For this
scenario, you simulate the camera by building a module that sends a test image to the image classifier.
Add and configure a new module
In this section, you add a new module to the same CustomVisionSolution and provide code to create the
simulated camera.
1. In the same Visual Studio Code window, use the command palette to run Azure IoT Edge: Add IoT
Edge Module. In the command palette, provide the following information for your new module:

PROMPT VALUE

Select deployment template file Select the deployment.template.json file in the


CustomVisionSolution folder.

Select module template Select Python Module

Provide a module name Name your module cameraCapture

Provide Docker image repository for the module Replace localhost:5000 with the login server value for
your Azure container registry.

The final string looks like


<registryname>.azurecr.io/cameracapture.

The VS Code window loads your new module in the solution workspace, and updates the
deployment.template.json file. Now you should see two module folders: classifier and cameraCapture.
2. Open the main.py file in the modules / cameraCapture folder.
3. Replace the entire file with the following code. This sample code sends POST requests to the image-
processing service running in the classifier module. We provide this module container with a sample
image to use in the requests. It then packages the response as an IoT Hub message and sends it to an
output queue.

# Copyright (c) Microsoft. All rights reserved.


# Licensed under the MIT license. See LICENSE file in the project root for
# full license information.

import time
import sys
import os
import requests
import json
from azure.iot.device import IoTHubModuleClient, Message

# global counters
SENT_IMAGES = 0

# global client
CLIENT = None

# Send a message to IoT Hub


# Route output1 to $upstream in deployment.template.json
def send_to_hub(strMessage):
message = Message(bytearray(strMessage, 'utf8'))
CLIENT.send_message_to_output(message, "output1")
global SENT_IMAGES
SENT_IMAGES += 1
print( "Total images sent: {}".format(SENT_IMAGES) )

# Send an image to the image classifying server


# Return the JSON response from the server with the prediction result
def sendFrameForProcessing(imagePath, imageProcessingEndpoint):
headers = {'Content-Type': 'application/octet-stream'}

with open(imagePath, mode="rb") as test_image:


try:
response = requests.post(imageProcessingEndpoint, headers = headers, data = test_image)
print("Response from classification service: (" + str(response.status_code) + ") " +
json.dumps(response.json()) + "\n")
except Exception as e:
print(e)
print("Response from classification service: (" + str(response.status_code))

return json.dumps(response.json())

def main(imagePath, imageProcessingEndpoint):


try:
print ( "Simulated camera module for Azure IoT Edge. Press Ctrl-C to exit." )

try:
global CLIENT
CLIENT = IoTHubModuleClient.create_from_edge_environment()
except Exception as iothub_error:
print ( "Unexpected error {} from IoTHub".format(iothub_error) )
return

print ( "The sample is now sending images for processing and will indefinitely.")

while True:
classification = sendFrameForProcessing(imagePath, imageProcessingEndpoint)
send_to_hub(classification)
time.sleep(10)

except KeyboardInterrupt:
print ( "IoT Edge module sample stopped" )

if __name__ == '__main__':
try:
# Retrieve the image location and image classifying server endpoint from container environment
IMAGE_PATH = os.getenv('IMAGE_PATH', "")
IMAGE_PROCESSING_ENDPOINT = os.getenv('IMAGE_PROCESSING_ENDPOINT', "")
except ValueError as error:
print ( error )
sys.exit(1)

if ((IMAGE_PATH and IMAGE_PROCESSING_ENDPOINT) != ""):


main(IMAGE_PATH, IMAGE_PROCESSING_ENDPOINT)
else:
print ( "Error: Image path or image-processing endpoint missing" )

4. Save the main.py file.


5. Open the requrements.txt file.
6. Add a new line for a library to include in the container.

requests

7. Save the requirements.txt file.


Add a test image to the container
Instead of using a real camera to provide an image feed for this scenario, we're going to use a single test image.
A test image is included in the GitHub repo that you downloaded for the training images earlier in this tutorial.
1. Navigate to the test image, located at Cognitive-CustomVision-Windows / Samples / Images / Test.
2. Copy test_image.jpg
3. Browse to your IoT Edge solution directory and paste the test image in the modules / cameraCapture
folder. The image should be in the same folder as the main.py file that you edited in the previous section.
4. In Visual Studio Code, open the Dockerfile.amd64 file for the cameraCapture module.
5. After the line that establishes the working directory, WORKDIR /app , add the following line of code:

ADD ./test_image.jpg .

6. Save the Dockerfile.


Prepare a deployment manifest
So far in this tutorial you've trained a Custom Vision model to classify images of trees, and packaged that model
up as an IoT Edge module. Then, you created a second module that can query the image classification server and
report its results back to IoT Hub. Now, you're ready to create the deployment manifest that will tell an IoT Edge
device how to start and run these two modules together.
The IoT Edge extension for Visual Studio Code provides a template in each IoT Edge solution to help you create
a deployment manifest.
1. Open the deployment.template.json file in the solution folder.
2. Find the modules section, which should contain three modules: the two that you created, classifier and
cameraCapture, and a third that's included by default, SimulatedTemperatureSensor.
3. Delete the SimulatedTemperatureSensor module with all of its parameters. This module is included to
provide sample data for test scenarios, but we don't need it in this deployment.
4. If you named the image classification module something other than classifier, check the name now and
ensure that it's all lowercase. The cameraCapture module calls the classifier module using a requests
library that formats all requests in lowercase, and IoT Edge is case-sensitive.
5. Update the createOptions parameter for the cameraCapture module with the following JSON. This
information creates environment variables in the module container that are retrieved in the main.py
process. By including this information in the deployment manifest, you can change the image or endpoint
without having to rebuild the module image.

"createOptions": "{\"Env\":
[\"IMAGE_PATH=test_image.jpg\",\"IMAGE_PROCESSING_ENDPOINT=http://classifier/image\"]}"

If you named your Custom Vision module something other than classifier, update the image-processing
endpoint value to match.
6. At the bottom of the file, update the routes parameter for the $edgeHub module. You want to route the
prediction results from cameraCapture to IoT Hub.

"routes": {
"CameraCaptureToIoTHub": "FROM /messages/modules/cameraCapture/outputs/* INTO $upstream"
},
If you named your second module something other than cameraCapture, update the route value to
match.
7. Save the deployment.template.json file.

Build and deploy your IoT Edge solution


With both modules created and the deployment manifest template configured, you're ready to build the
container images and push them to your container registry.
Once the images are in your registry, you can deploy the solution to an IoT Edge device. You can set modules on
a device through the IoT Hub, but you can also access your IoT Hub and devices through Visual Studio Code. In
this section, you set up access to your IoT Hub then use VS Code to deploy your solution to your IoT Edge
device.
First, build and push your solution to your container registry.
1. In the VS Code explorer, right-click the deployment.template.json file and select Build and push IoT
Edge solution. You can watch the progress of this operation in the integrated terminal in VS Code.
2. Notice that a new folder was added to your solution, config. Expand this folder and open the
deployment.json file inside.
3. Review the information in the deployment.json file. The deployment.json file is created (or updated)
automatically based on the deployment template file that you configured and information from the solution,
including the .env file and the module.json files.
Next, select your device and deploy your solution.
1. In the VS Code explorer, expand the Azure IoT Hub Devices section.
2. Right-click on the device that you want to target with your deployment and select Create deployment for
single device.
3. In the file explorer, navigate to the config folder inside your solution and choose deployment.json. Click
Select Edge deployment manifest.
If the deployment is successful, a confirmation message is printed in the VS Code output. In the VS Code
explorer, expand the details about the IoT Edge device that you used for this deployment. Hover your cursor on
the Azure IoT Hub Devices header to enable the refresh button if the modules don't show up right away. It
may take a few moments for the modules to start and report back to IoT Hub.
You can also check to see that all the modules are up and running on your device itself. On your IoT Edge device,
run the following command to see the status of the modules. It may take a few moments for the modules to
start.

iotedge list

View classification results


There are two ways to view the results of your modules, either on the device itself as the messages are generated
and sent, or from Visual Studio Code as the messages arrive at IoT Hub.
From your device, view the logs of the cameraCapture module to see the messages being sent and the
confirmation that they were received by IoT Hub.

iotedge logs cameraCapture


From Visual Studio Code, right-click on the name of your IoT Edge device and select Start Monitoring Built-in
Event Endpoint.
The results from the Custom Vision module, which are sent as messages from the cameraCapture module,
include the probability that the image is of either a hemlock or cherry tree. Since the image is hemlock, you
should see the probability as 1.0.

Clean up resources
If you plan to continue to the next recommended article, you can keep the resources and configurations that you
created and reuse them. You can also keep using the same IoT Edge device as a test device.
Otherwise, you can delete the local configurations and the Azure resources that you used in this article to avoid
charges.
Delete Azure resources
Deleting Azure resources and resource groups is irreversible. Make sure that you don't accidentally delete the
wrong resource group or resources. If you created the IoT hub inside an existing resource group that has
resources that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.
To delete the resources:
1. Sign in to the Azure portal and select Resource groups.
2. Select the name of the resource group that contains your IoT Edge test resources.
3. Review the list of resources contained in your resource group. If you want to delete all of them, you can
select Delete resource group. If you want to delete only some of them, you can click into each resource
to delete them individually.

Next steps
In this tutorial, you trained a Custom Vision model and deployed it as a module onto an IoT Edge device. Then
you built a module that can query the image classification service and report its results back to IoT Hub.
If you want to try a more in-depth version of this scenario with a live camera feed, see the Custom Vision and
Azure IoT Edge on a Raspberry Pi 3 GitHub project.
Continue on to the next tutorials to learn about other ways that Azure IoT Edge can help you turn data into
business insights at the edge.
Store data at the edge with SQL Server databases
Tutorial: Store data at the edge with SQL Server
databases
12/2/2019 • 12 minutes to read • Edit Online

Deploy a SQL Server module to store data on a Linux device running Azure IoT Edge.
Use Azure IoT Edge and SQL Server to store and query data at the edge. Azure IoT Edge has basic storage
capabilities to cache messages if a device goes offline, and then forward them when the connection is
reestablished. However, you may want more advanced storage capabilities, like being able to query data locally.
Your IoT Edge devices can use local databases to perform more complex computing without having to maintain a
connection to IoT Hub.
This article provides instructions for deploying a SQL Server database to an IoT Edge device. Azure Functions,
running on the IoT Edge device, structures the incoming data then sends it to the database. The steps in this article
can also be applied to other databases that work in containers, like MySQL or PostgreSQL.
In this tutorial, you learn how to:
Use Visual Studio Code to create an Azure Function
Deploy a SQL database to your IoT Edge device
Use Visual Studio Code to build modules and deploy them to your IoT Edge device
View generated data
If you don't have an Azure subscription, create a free account before you begin.

Prerequisites
Before beginning this tutorial, you should have gone through the previous tutorial to set up your development
environment for Linux container development: Develop IoT Edge modules for Linux devices. By completing that
tutorial, you should have the following prerequisites in place:
A free or standard-tier IoT Hub in Azure.
A Linux device running Azure IoT Edge
A container registry, like Azure Container Registry.
Visual Studio Code configured with the Azure IoT Tools.
Docker CE configured to run Linux containers.
This tutorial uses an Azure Functions module to send data to the SQL Server. To develop an IoT Edge module with
Azure Functions, install the following additional prerequisites on your development machine:
C# for Visual Studio Code (powered by OmniSharp) extension for Visual Studio Code.
.NET Core 2.1 SDK.

Create a function project


To send data into a database, you need a module that can structure the data properly and then stores it in a table.
Create a new project
The following steps show you how to create an IoT Edge function using Visual Studio Code and the Azure IoT
Tools.
1. Open Visual Studio Code.
2. Open the VS Code command palette by selecting View > Command palette.
3. In the command palette, type and run the command Azure IoT Edge: New IoT Edge solution. In the
command palette, provide the following information to create your solution:

FIELD VALUE

Select folder Choose the location on your development machine for VS


Code to create the solution files.

Provide a solution name Enter a descriptive name for your solution, like
SqlSolution, or accept the default.

Select module template Choose Azure Functions - C#.

Provide a module name Name your module sqlFunction.

Provide Docker image repository for the module An image repository includes the name of your container
registry and the name of your container image. Your
container image is prepopulated from the last step.
Replace localhost:5000 with the login server value from
your Azure container registry. You can retrieve the login
server from the Overview page of your container registry
in the Azure portal.

The final string looks like <registry


name>.azurecr.io/sqlfunction.

The VS Code window loads your IoT Edge solution workspace.


Add your registry credentials
The environment file stores the credentials for your container registry and shares them with the IoT Edge runtime.
The runtime needs these credentials to pull your private images onto the IoT Edge device.
1. In the VS Code explorer, open the .env file.
2. Update the fields with the username and password values that you copied from your Azure container registry.
3. Save this file.
Select your target architecture
Currently, Visual Studio Code can develop C modules for Linux AMD64 and Linux ARM32v7 devices. You need to
select which architecture you're targeting with each solution, because the container is built and run differently for
each architecture type. The default is Linux AMD64.
1. Open the command palette and search for Azure IoT Edge: Set Default Target Platform for Edge
Solution, or select the shortcut icon in the side bar at the bottom of the window.
2. In the command palette, select the target architecture from the list of options. For this tutorial, we're using
an Ubuntu virtual machine as the IoT Edge device, so will keep the default amd64.
Update the module with custom code
1. In the VS Code explorer, open modules > sqlFunction > sqlFunction.cs.
2. Replace the entire contents of the file with the following code:

using System;
using System.Collections.Generic;
using System.IO;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Client;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.EdgeHub;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Sql = System.Data.SqlClient;

namespace Functions.Samples
{
public static class sqlFunction
{
[FunctionName("sqlFunction")]
public static async Task FilterMessageAndSendMessage(
[EdgeHubTrigger("input1")] Message messageReceived,
[EdgeHub(OutputName = "output1")] IAsyncCollector<Message> output,
ILogger logger)
{
const int temperatureThreshold = 20;
byte[] messageBytes = messageReceived.GetBytes();
var messageString = System.Text.Encoding.UTF8.GetString(messageBytes);

if (!string.IsNullOrEmpty(messageString))
{
logger.LogInformation("Info: Received one non-empty message");
// Get the body of the message and deserialize it.
var messageBody = JsonConvert.DeserializeObject<MessageBody>(messageString);

//Store the data in SQL db


const string str = "<sql connection string>";
using (Sql.SqlConnection conn = new Sql.SqlConnection(str))
{
conn.Open();
var insertMachineTemperature = "INSERT INTO
MeasurementsDB.dbo.TemperatureMeasurements VALUES (CONVERT(DATETIME2,'" + messageBody.timeCreated + "',
127), 'machine', " + messageBody.machine.temperature + ");";
var insertAmbientTemperature = "INSERT INTO
MeasurementsDB.dbo.TemperatureMeasurements VALUES (CONVERT(DATETIME2,'" + messageBody.timeCreated + "',
127), 'ambient', " + messageBody.ambient.temperature + ");";
using (Sql.SqlCommand cmd = new Sql.SqlCommand(insertMachineTemperature + "\n" +
insertAmbientTemperature, conn))
{
//Execute the command and log the # rows affected.
var rows = await cmd.ExecuteNonQueryAsync();
logger.LogInformation($"{rows} rows were updated");
}
}

if (messageBody != null && messageBody.machine.temperature > temperatureThreshold)


{
// Send the message to the output as the temperature value is greater than the
threashold.
using (var filteredMessage = new Message(messageBytes))
{
// Copy the properties of the original message into the new Message object.
foreach (KeyValuePair<string, string> prop in messageReceived.Properties)
{filteredMessage.Properties.Add(prop.Key, prop.Value);}
// Add a new property to the message to indicate it is an alert.
filteredMessage.Properties.Add("MessageType", "Alert");
// Send the message.
await output.AddAsync(filteredMessage);
logger.LogInformation("Info: Received and transferred a message with
temperature above the threshold");
}
}
}
}
}
//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;}
}
}

3. In line 35, replace the string <sql connection string> with the following string. The Data Source property
references the SQL Server container, which doesn't exist yet but you will create it with the name SQL in the
next section.

Data Source=tcp:sql,1433;Initial Catalog=MeasurementsDB;User


Id=SA;Password=Strong!Passw0rd;TrustServerCertificate=False;Connection Timeout=30;

4. Save the sqlFunction.cs file.


5. Open the sqlFunction.csproj file.
6. Find the group of package references, and add a new one to include SqlClient.

<PackageReference Include="System.Data.SqlClient" Version="4.5.1"/>

7. Save the sqlFunction.csproj file.

Add the SQL Server container


A Deployment manifest declares which modules the IoT Edge runtime will install on your IoT Edge device. You
provided the code to make a customized Function module in the previous section, but the SQL Server module is
already built and available in the Azure Marketplace. You just need to tell the IoT Edge runtime to include it, then
configure it on your device.
1. In Visual Studio Code, open the command palette by selecting View > Command palette.
2. In the command palette, type and run the command Azure IoT Edge: Add IoT Edge module. In the
command palette, provide the following information to add a new module:

FIELD VALUE

Select deployment template file The command palette highlights the


deployment.template.json file in your current solution
folder. Select that file.

Select module template Select Module from Azure Marketplace.

3. In the Azure IoT Edge module marketplace, search for and select SQL Server Module.
4. Change the module name to sql, all lowercase. This name matches the container name declared in the
connection string in the sqlFunction.cs file.
5. Select Import to add the module to your solution.
6. In your solution folder, open the deployment.template.json file.
7. Find the modules section. You should see three modules. The module SimulatedTemperatureSensor is
included by default in new solutions, and provides test data to use with your other modules. The module
sqlFunction is the module that you initially created and updated with new code. Finally, the module sql was
imported from the Azure Marketplace.

TIP
The SQL Server module comes with a default password set in the environment variables of the deployment manifest.
Any time that you create a SQL Server container in a production environment, you should change the default system
administrator password.

8. Close the deployment.template.json file.

Build your IoT Edge solution


In the previous sections, you created a solution with one module, and then added another to the deployment
manifest template. The SQL Server module is hosted publicly by Microsoft, but you need to containerize the code
in the Functions module. In this section, you build the solution, create container images for the sqlFunction
module, and push the image to your container registry.
1. In Visual Studio Code, open the integrated terminal by selecting View > Terminal.
2. Sign in to your container registry in Visual Studio Code so that you can push your images to your registry.
Use the same Azure Container Registry (ACR ) credentials that you added to the .env file. Enter the following
command in the integrated terminal:

docker login -u <ACR username> -p <ACR password> <ACR login server>

You might see a security warning recommending the use of the --password-stdin parameter. While its use is
outside the scope of this article, we recommend following this best practice. For more information, see the
docker login command reference.
3. In the VS Code explorer, right-click the deployment.template.json file and select Build and Push IoT
Edge solution.
When you tell Visual Studio Code to build your solution, it first takes the information in the deployment template
and generates a deployment.json file in a new folder named config. Then, it runs two commands in the integrated
terminal: docker build and docker push . These two commands build your code, containerize the module, and
then push the code to the container registry that you specified when you initialized the solution.
You can verify that the sqlFunction module was successfully pushed to your container registry. In the Azure portal,
navigate to your container registry. Select repositories and search for sqlFunction. The other two modules,
SimulatedTemperatureSensor and sql, won't be pushed to your container registry because you're already pointing
to their repositories in the Microsoft registries.

Deploy the solution to a device


You can set modules on a device through the IoT Hub, but you can also access your IoT Hub and devices through
Visual Studio Code. In this section, you set up access to your IoT Hub then use VS Code to deploy your solution to
your IoT Edge device.
1. In the VS Code explorer, expand the Azure IoT Hub Devices section.
2. Right-click on the device that you want to target with your deployment and select Create deployment for
single device.
3. In the file explorer, navigate to the config folder inside your solution and choose deployment.amd64.
Click Select Edge deployment manifest.
Do not use the deployment.template.json file as a deployment manifest.
If the deployment is successful, a confirmation message is printed in the VS Code output.
Refresh the status of your device in the Azure IoT Hub Devices section of VS Code. The new modules are listed
and will start to report as running over the next few minutes as the containers are installed and started. You can
also check to see that all the modules are up and running on your device. On your IoT Edge device, run the
following command to see the status of the modules.

iotedge list

Create the SQL database


When you apply the deployment manifest to your device, you get three modules running. The
SimulatedTemperatureSensor module generates simulated environment data. The sqlFunction module takes the
data and formats it for a database. This section guides you through setting up the SQL database to store the
temperature data.
Run the following commands on your IoT Edge device. These commands connect to the sql module running on
your device and create a database and table to hold the temperature data being sent to it.
1. In a command-line tool on your IoT Edge device, connect to your database.

sudo docker exec -it sql bash

2. Open the SQL command tool.

/opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P 'Strong!Passw0rd'

3. Create your database:

CREATE DATABASE MeasurementsDB


ON
(NAME = MeasurementsDB, FILENAME = '/var/opt/mssql/measurementsdb.mdf')
GO

4. Define your table.

CREATE TABLE MeasurementsDB.dbo.TemperatureMeasurements (measurementTime DATETIME2, location


NVARCHAR(50), temperature FLOAT)
GO

You can customize your SQL Server docker file to automatically set up your SQL Server to be deployed on
multiple IoT Edge devices. For more information, see the Microsoft SQL Server container demo project.

View the local data


Once your table is created, the sqlFunction module starts storing data in a local SQL Server 2017 database on
your IoT Edge device.
From inside the SQL command tool, run the following command to view your formatted table data:

SELECT * FROM MeasurementsDB.dbo.TemperatureMeasurements


GO

Clean up resources
If you plan to continue to the next recommended article, you can keep the resources and configurations that you
created and reuse them. You can also keep using the same IoT Edge device as a test device.
Otherwise, you can delete the local configurations and the Azure resources that you created in this article to avoid
charges.
Delete Azure resources
Deleting Azure resources and resource groups is irreversible. Make sure that you don't accidentally delete the
wrong resource group or resources. If you created the IoT hub inside an existing resource group that has resources
that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.
To delete the resources:
1. Sign in to the Azure portal and select Resource groups.
2. Select the name of the resource group that contains your IoT Edge test resources.
3. Review the list of resources contained in your resource group. If you want to delete all of them, you can
select Delete resource group. If you want to delete only some of them, you can click into each resource to
delete them individually.

Next steps
In this tutorial, you created an Azure Functions module that contains code to filter raw data generated by your IoT
Edge device. When you're ready to build your own modules, you can learn more about how to Develop Azure
Functions with Azure IoT Edge for Visual Studio Code.
If you want to try another storage method at the edge, read about how to use Azure Blob Storage on IoT Edge.
Store data at the edge with Azure Blob Storage on IoT Edge
Tutorial: An end-to-end solution using Azure
Machine Learning and IoT Edge
11/14/2019 • 6 minutes to read • Edit Online

Frequently, IoT applications want to take advantage of the intelligent cloud and the intelligent edge. In this tutorial,
we walk you through training a machine learning model with data collected from IoT devices in the cloud,
deploying that model to IoT Edge, and maintaining and refining the model periodically.
The primary objective of this tutorial is to introduce the processing of IoT data with machine learning, specifically
on the edge. While we touch many aspects of a general machine learning workflow, this tutorial is not intended as
an in-depth introduction to machine learning. As a case in point, we do not attempt to create a highly optimized
model for the use case – we just do enough to illustrate the process of creating and using a viable model for IoT
data processing.

Target audience and roles


This set of articles is intended for developers without previous experience in IoT development or machine
learning. Deploying machine learning at the edge requires knowledge of how to connect a wide range of
technologies. Therefore, this tutorial covers an entire end-to-end scenario to demonstrate one way of joining these
technologies together for an IoT solution. In a real-world environment, these tasks might be distributed among
several people with different specializations. For example, developers would focus on either device or cloud code,
while data scientists designed the analytics models. To enable an individual developer to successfully complete this
tutorial, we have provided supplemental guidance with insights and links to more information we hope is
sufficient to understand what is being done, as well as why.
Alternatively, you may team up with coworkers of different roles to follow the tutorial together, bringing your full
expertise to bear, and learn as a team how things fit together.
In either case, to help orient the reader(s), each article in this tutorial indicates the role of the user. Those roles
include:
Cloud development (including a cloud developer working in a DevOps capacity)
Data analytics

Use case: Predictive maintenance


We based this scenario on a use case presented at the Conference on Prognostics and Health Management
(PHM08) in 2008. The goal is to predict remaining useful life (RUL ) of a set of turbofan airplane engines. This data
was generated using C -MAPSS, the commercial version of MAPSS (Modular Aero-Propulsion System
Simulation) software. This software provides a flexible turbofan engine simulation environment to conveniently
simulate the health, control, and engine parameters.
The data used in this tutorial is taken from the Turbofan engine degradation simulation data set.
From the readme file:
Experimental Scenario
Data sets consist of multiple multivariate time series. Each data set is further divided into training and test subsets.
Each time series is from a different engine – i.e., the data can be considered to be from a fleet of engines of the
same type. Each engine starts with different degrees of initial wear and manufacturing variation which is
unknown to the user. This wear and variation is considered normal, i.e., it is not considered a fault condition. There
are three operational settings that have a substantial effect on engine performance. These settings are also
included in the data. The data is contaminated with sensor noise.
The engine is operating normally at the start of each time series and develops a fault at some point during the
series. In the training set, the fault grows in magnitude until system failure. In the test set, the time series ends some
time prior to system failure. The objective of the competition is to predict the number of remaining operational
cycles before failure in the test set, i.e., the number of operational cycles after the last cycle that the engine will
continue to operate. Also provided a vector of true Remaining Useful Life (RUL ) values for the test data.
Because the data was published for a competition, several approaches to derive machine learning models have
been published independently. We found that studying examples is helpful in understanding the process and
reasoning involved in the creation of a specific machine learning model. See for example:
Aircraft engine failure prediction model by GitHub user jancervenka.
Turbofan engine degradation by GitHub user hankroark.

Process
The picture below illustrates the rough steps we follow in this tutorial:

1. Collect training data: The process begins by collecting training data. In some cases, data has already been
collected and is available in a database, or in form of data files. In other cases, especially for IoT scenarios,
the data needs to be collected from IoT devices and sensors and stored in the cloud.
We assume that you don't have a collection of turbofan engines, so the project files include a simple device
simulator that sends the NASA device data to the cloud.
2. Prepare data. In most cases, the raw data as collected from devices and sensors will require preparation
for machine learning. This step may involve data clean up, data reformatting, or preprocessing to inject
additional information machine learning can key off.
For our airplane engine machine data, data preparation involves calculating explicit time-to-failure times for
every data point in the sample based on the actual observations on the data. This information allows the
machine learning algorithm to find correlations between actual sensor data patterns and the expected
remaining life time of the engine. This step is highly domain-specific.
3. Build a machine learning model. Based on the prepared data, we can now experiment with different
machine learning algorithms and parameterizations to train models and compare the results to one
another.
In this case, for testing we compare the predicted outcome computed by the model with the real outcome
observed on a set of engines. In Azure Machine Learning, we can manage the different iterations of models
we create in a model registry.
4. Deploy the model. Once we have a model that satisfies our success criteria, we can move to deployment.
That involves wrapping the model into a web service app that can be fed with data using REST calls and
return analysis results. The web service app is then packaged into a docker container, which in turn can be
deployed either in the cloud or as an IoT Edge module. In this example, we focus on deployment to IoT
Edge.
5. Maintain and refine the model. Our work is not done once the model is deployed. In many cases, we
want to continue collecting data and periodically upload that data to the cloud. We can then use this data to
retrain and refine our model, which we then can redeploy to IoT Edge.

Prerequisites
To complete the tutorial, you need access to an Azure subscription in which you have rights to create resources.
Several of the services used in this tutorial will incur Azure charges. If you do not already have an Azure
subscription, you may be able to get started with an Azure Free Account.
You also need a machine with PowerShell installed where you can run scripts to set up an Azure Virtual Machine
as your development machine.
In this document, we use the following set of tools:
An Azure IoT hub for data capture
Azure Notebooks as our main front end for data preparation and machine learning experimentation.
Running python code in a notebook on a subset of the sample data is a great way to get fast iterative and
interactive turnaround during data preparation. Jupyter notebooks can also be used to prepare scripts to
run at scale in a compute backend.
Azure Machine Learning as a backend for machine learning at scale and for machine learning image
generation. We drive the Azure Machine Learning backend using scripts prepared and tested in Jupyter
notebooks.
Azure IoT Edge for off-cloud application of a machine learning image
Obviously, there are other options available. In certain scenarios, for example, IoT Central can be used as a no-
code alternative to capture initial training data from IoT devices.

Next steps
This tutorial is divided into the following sections:
1. Set up your development machine and Azure services.
2. Generate the training data for the machine learning module.
3. Train and deploy the machine learning module.
4. Configure an IoT Edge device to act as a transparent gateway.
5. Create and deploy IoT Edge modules.
6. Send data to your IoT Edge device.
Continue to the next article to set up a development machine and provision Azure resources.
Set up an environment for machine learning on IoT Edge
Tutorial: Set up an environment for machine learning
on IoT Edge
11/14/2019 • 7 minutes to read • Edit Online

NOTE
This article is part of a series for a tutorial about using Azure Machine Learning on IoT Edge. If you have arrived at this article
directly, we encourage you to begin with the first article in the series for the best results.

This article from the end-to-end Azure Machine Learning on IoT Edge tutorial helps you prepare your
environment for development and deployment. First, set up a development machine with all the tools you need.
Then, create the necessary cloud resources in Azure.

Set up a development machine


This step is typically performed by a cloud developer. Some of the software may also be helpful for a data scientist.
Over the course of this article we perform various developer tasks including coding, compiling, configuring, and
deploying IoT Edge modules and IoT devices. For ease of use, we created a PowerShell script that creates an Azure
virtual machine with many of the prerequisites already configured. The VM that we create needs to be able to
handle nested virtualization, which is why we chose a Standard_D8s_v3 machine size.
The development VM will be set up with:
Windows 10
Chocolatey
Docker Desktop for Windows
Git for Windows
Git Credential Manager for Windows
.Net Core SDK
Python 3
Visual Studio Code
Azure PowerShell
VS Code Extensions
Azure IoT Tools
Python
C#
Docker
PowerShell
The developer VM is not strictly necessary – all the development tools can be run on a local machine. However, we
strongly recommend using the VM to ensure a level playing field.
It takes about 30 minutes to create and configure the virtual machine.
Get the script
Clone or download the PowerShell script from the Machine Learning and IoT Edge sample repository.
Create an Azure virtual machine
The DevVM directory contains the files needed to create an Azure virtual machine appropriate for completing this
tutorial.
1. Open Powershell as an administrator and navigate to the directory where you downloaded the code. We
will refer to the root directory for your source as <srcdir> .

cd <srcdir>\IoTEdgeAndMlSample\DevVM

2. Run the following command to allow execution of scripts. Choose Yes to All when prompted.

Set-ExecutionPolicy Bypass -Scope Process

3. Run Create-AzureDevVM.ps1 from this directory.

.\Create-AzureDevVm.ps1

When prompted, provide the following information:


Azure Subscription ID: Your subscription ID, which can be found in the Azure portal
Resource Group Name: The name of a new or existing resource group in Azure
Location: Choose an Azure location where the virtual machine will be created. For example,
westus2 or northeurope. For more information, see Azure locations.
AdminUsername: Provide a memorable name for the admin account you want to create and use
on the virtual machine.
AdminPassword: Set a password for the admin account on the virtual machine.
If you do not have Azure PowerShell installed, the script will install Azure PowerShell Az module
You will be prompted to sign in to Azure.
The script confirms the information for the creation of your VM. Press y or Enter to continue.
The script runs for several minutes as it executes the following steps:
Create the resource group if it does not exist
Deploy the virtual machine
Enable Hyper-V on the VM
Install software need for development and clone the sample repository
Restart the VM
Create an RDP file on your desktop for connecting to the VM
Set auto -shutdown schedule
To help you reduce cost, the VM has been created with an automatic shutdown schedule that is set to 1900 PST.
You may need to update this timing depending on your location and schedule. To update the shutdown schedule:
1. Sign in to the Azure portal.
2. Navigate to your virtual machine in the resource group that you provided in the previous section.
3. Select Auto-shutdown on the side navigator.
4. Enter a new shutdown time in Scheduled shutdown or change the Time zone then click Save.
Connect and configure development machine
Now that we have created a VM we need to finish installing the software needed to complete the tutorial.
Start a remote desktop session
1. The VM creation script created an RDP file on your desktop.
2. Double-click on the file with the name <Azure VM name>.rdp.
3. You will be presented with a dialog saying the publisher of the remote connection is unknown. Click the
Don’t ask me again for connections to this computer checkbox then select Connect.
4. When prompted, provide the AdminPassword that you used when running the script to set up the VM and
click OK.
5. You will be prompted to accept the certificate for the VM. Select Don’t ask me again for connections to
this computer and choose Yes.
Install Visual Studio Code extensions
Now that you have connected to the development machine, add some useful extensions to Visual Studio Code to
make the development experience easier.
1. In a PowerShell window, navigate to C:\source\IoTEdgeAndMlSample\DevVM.
2. Allow scripts to be executed on the virtual machine by typing.

Set-ExecutionPolicy Bypass -Scope CurrentUser -Force

3. Run the script.

.\Enable-CodeExtensions.ps1

4. The script will run for a few minutes installing VS code extensions:
Azure IoT Tools
Python
C#
Docker
PowerShell

Set up IoT Hub and Storage


These steps are typically performed by a cloud developer.
Azure IoT Hub is the heart of any IoT application. It handles secure communication between IoT devices and the
cloud. It is the main coordination point for the operation of the IoT Edge machine learning solution.
IoT Hub uses routes to direct incoming data from IoT devices to other downstream services. We will take
advantage of IoT Hub routes to send device data to Azure Storage where it can be consumed by Azure
Machine Learning to train our remaining useful life (RUL ) classifier.
Later in the tutorial, we will use IoT Hub to configure and manage our Azure IoT Edge device.
In this section, you use a script to create an Azure IoT hub and an Azure Storage account. Then, you configure a
route that forwards data received by the hub to an Azure Storage Blob container using the Azure portal. These
steps take about 10 minutes to complete.
Create cloud resources
1. On your development machine, open a PowerShell window.
2. Change to the IoTHub directory.

cd C:\source\IoTEdgeAndMlSample\IoTHub

3. Run the creation script. Use the same values for subscription ID, location, and resource group as you did
when creating the development VM.

.\New-HubAndStorage.ps1 -SubscriptionId <subscription id> -Location


<location> -ResourceGroupName <resource group>

You will be prompted to sign in to Azure.


The script confirms the information for the creation of your Hub and Storage account. Press y or
Enter to continue.

The script takes about two minutes to run. Once complete, the script outputs the name of the hub and the storage
account.
Review route to storage in IoT Hub
As part of creating the IoT hub, the script that we ran in the previous section also created a custom endpoint and a
route. IoT Hub routes consist of a query expression and an endpoint. If a message matches the expression, the data
is sent along the route to the associated endpoint. Endpoints can be Event Hubs, Service Bus Queues, and Topics.
In this case, the endpoint is a Blob container in a storage account. Let’s use the Azure portal to review the route
created by our script.
1. Open the Azure portal.
2. Choose all services from the left navigator, type IoT in the search box, and select IoT Hub.
3. Choose the IoT Hub created in the previous step.
4. In the IoT Hub side navigator, choose Message routing.
5. The message routing page has two tabs, Routes and Custom endpoints. Select the Custom endpoints
tab.
6. Under Blob storage, select turbofanDeviceStorage.
7. Note that this endpoint points to a blob container called devicedata in the storage account created in the
last step, which is named iotedgeandml<unique suffix>.
8. Also note the Blob file name format has been changed from the default format to instead place the
partition as the last element in the name. We find this format is more convenient for the file operations we
will do with Azure Notebooks later in the tutorial.
9. Close the endpoint details blade to return to the Message routing page.
10. Select the Routes tab.
11. Select the route named turbofanDeviceDataToStorage.
12. Note that the route’s endpoint is the turbofanDeviceStorage custom endpoint.
13. Look at the routing query, which is set to true. This means that all device telemetry messages will match
this route and therefore all messages will be sent to the turbofanDeviceStorage endpoint.
14. Close the route details.
Next steps
In this article, we created an IoT Hub and configured a route to an Azure Storage account. In the next article, we
will send data from a set of simulated devices through the IoT Hub into the storage account. Later in the tutorial,
after we have configured our IoT Edge device and modules, we will revisit routes and look a little more at the
routing query.
For more information about the steps covered in this portion of the Machine Learning on IoT Edge tutorial, see:
Azure IoT Fundamentals
Configure message routing with IoT Hub
Create an IoT hub using the Azure portal
Continue to the next article to create a simulated device to monitor.
Generate device data
Tutorial: Generate simulated device data
12/2/2019 • 6 minutes to read • Edit Online

NOTE
This article is part of a series for a tutorial about using Azure Machine Learning on IoT Edge. If you have arrived at this article
directly, we encourage you to begin with the first article in the series for the best results.

In this article, we use machine learning training data to simulate a device sending telemetry to IoT Hub. As stated
in the introduction, this end-to-end tutorial uses the Turbofan engine degradation simulation data set to simulate
data from a set of airplane engines for training and testing.
From the accompanying readme.txt we know that:
The data consists of multiple multivariate time series
Each data set is divided into training and test subsets
Each time series is from a different engine
Each engine starts with different degrees of initial wear and manufacturing variation
For this tutorial, we use the training data subset of a single data set (FD003).
In reality, each engine would be an independent IoT device. Assuming you do not have a collection of internet-
connected turbofan engines available, we will build a software stand-in for these devices.
The simulator is a C# program that uses the IoT Hub APIs to programmatically register virtual devices with IoT
Hub. We then read the data for each device from the NASA-provided data subset and send it to your IoT hub
using a simulated IoT Device. All the code for this portion of the tutorial can be found in the DeviceHarness
directory of the repository.
The DeviceHarness project is a .NET core project written in C# consisting of four classes:
Program: The entry point for execution responsible for handling user input and overall coordination.
TrainingFileManager: responsible for reading and parsing the selected data file.
CycleData: represents a single row of data in a file converted to message format.
TurbofanDevice: responsible for creating an IoT Device that corresponds to a single device (time series) in the
data and transmitting the data to IoT Hub via the IoT Device.
The tasks described in this article should take about 20 minutes to complete.
The real-world equivalent to the work in this step would likely be performed by device developers and cloud
developers.

Configure Visual Studio Code and build DeviceHarness project


1. Open a remote desktop session to your virtual machine, as demonstrated in the previous article.
2. Open Visual Studio Code.
3. In Visual Studio Code, select File > Open Folder....
4. In the Folder textbox, enter C:\source\IoTEdgeAndMlSample\DeviceHarness and click the Select Folder button.
If OmniSharp errors appear in the output window, you’ll need to uninstall the C# extension, close and
reopen VS Code, install the C# extension, and then reload the window.
5. Since you're using extensions on this machine for the first time, some extensions will update and install their
dependencies. You may be prompted to update extension. If so, select Reload Window.
6. You will be prompted to add required assets for DeviceHarness. Select Yes to add them.
The notification may take a few seconds to appear.
If you missed this notification, check the “bell” icon in the lower right-hand corner.

7. Select Restore to restore the package dependencies.

8. Validate that your environment is properly set up by triggering a build, Ctrl + Shift + B or Terminal >
Run Build Task.
9. You are prompted to select the build task to run. Select Build.
10. The build runs and outputs a success message.

11. You can make this build the default build task by selecting Terminal > Configure Default Build Task...
and choosing Build from the prompt.

Connect to IoT Hub and run DeviceHarness


Now that we have the project building, connect to your IoT hub to access the connection string and monitor the
progress of the data generation.
Sign in to Azure in Visual Studio Code
1. Sign into your Azure subscription in Visual Studio Code by opening the command palette,
Ctrl + Shift + P or View > Command Palette....

2. At the prompt search for and select Azure: Sign In.


3. A browser window opens and prompts you for your credentials. When you are redirected to a success page,
you can close the browser.
Connect to your IoT hub and retrieve hub connection string
1. In the bottom section of the Visual Studio Code explorer, select the Azure IoT Hub devices frame to
expand it.
2. In the expanded frame, click on Select IoT Hub.
3. When prompted, select your Azure subscription and then your IoT hub.
4. Click into the Azure IoT Hub devices frame and click ... for more actions. Select Copy IoT Hub
connection string.

Run the DeviceHarness project


1. Select View > Terminal to open the Visual Studio Code terminal.
If you do not see a prompt, select Enter.
2. Enter dotnet run in the terminal.
3. When prompted for the IoT Hub Connection String, paste the connection string copied in the previous
section.
4. In the Azure IoT Hub devices frame, click on the refresh button.

5. Note that devices are added to the IoT Hub and that the devices show up in green to indicate that data is
being sent via that device.
6. You can view the messages being sent to the hub by right-clicking on any device and selecting Start
Monitoring Built-in Event Endpoint. The messages will show in the output pane in Visual Studio Code.
7. Stop monitoring by clicking in the Azure IoT Hub Toolkit output pane and choose Stop Monitoring
Built-in Event Endpoint.
8. Let the application run to completion, which takes a few minutes.

Check IoT Hub for activity


The data sent by the DeviceHarness went to your IoT hub. It is easy to verify that data has reached your hub using
the Azure portal.
1. Open the Azure portal and navigate to your IoT hub.
2. In the overview page you should see that data has been sent to the hub:

Validate data in Azure Storage


The data we just sent to your IoT hub was routed to the storage container that we created in the previous article.
Let’s look at the data in our storage account.
1. In the Azure portal, navigate to your storage account.
2. From the storage account navigator, select Storage Explorer (preview).
3. In the storage explorer, select Blob Containers then devicedata.
4. In the content pane click on the folder for the name of the IoT hub, then the year, the month, the day, and the
hour. You will see several folders representing the minutes when the data was written.

5. Click into one of those folders to find data files labeled 00 and 01 corresponding to the partition.
6. The files are written in Avro format but double-clicking on one of these files will open another browser tab
and partially render the data. If instead you are prompted to open the file in a program, you can choose VS
Code and it will render correctly.
7. There is no need to try to read or interpret the data right now; we will do it in next article.

Next steps
In this article, we used a .NET Core project to create a set of virtual devices and send data through those devices
through our IoT Hub and into an Azure Storage container. This project simulates a real-world scenario where
physical devices send data including sensor readings, operational settings, failure signals and modes, and so on, to
an IoT Hub and onward into a curated storage. Once enough data has been collected, we use it to train models that
predict the remaining useful life (RUL ) for the device, which we will demonstrate in the next article.
Continue to the next article to train a machine learning model with the data.
Train and deploy an Azure Machine Learning model
Tutorial: Train and deploy an Azure Machine Learning
model
12/2/2019 • 5 minutes to read • Edit Online

NOTE
This article is part of a series for a tutorial about using Azure Machine Learning on IoT Edge. If you have arrived at this article
directly, we encourage you to begin with the first article in the series for the best results.

In this article, we use Azure Notebooks first to train a machine learning model using Azure Machine Learning and
then package that model as a container image that can be deployed as an Azure IoT Edge Module. The Azure
Notebooks take advantage of an Azure Machine Learning workspace, which is a foundational block used to
experiment, train, and deploy machine learning models.
The activities in this portion of the tutorial are broken up across two notebooks.
01-turbofan_regression.ipynb: This notebook walks through the steps to train and publish a model using
Azure Machine Learning. Broadly, the steps involved are:
1. Download, prepare, and explore the training data
2. Use the service workspace to create and run a machine learning experiment
3. Evaluate the model results from the experiment
4. Publish the best model to the service workspace
02-turbofan_deploy_model.ipynb: This notebook takes the model created in the previous notebook and
uses it to create a container image ready to be deployed to an Azure IoT Edge device.
1. Create a scoring script for the model
2. Create and publish the image
3. Deploy the image as a web service on Azure Container Instance
4. Use the web service to validate the model and the image work as expected
The steps in this article might be typically performed by data scientists.

Set up Azure Notebooks


We use Azure Notebooks to host the two Jupyter Notebooks and supporting files. Here we create and configure
an Azure Notebooks project. If you have not used Jupyter and/or Azure Notebooks, here are a couple of
introductory documents:
Quickstart: Create and share a notebook
Tutorial: Create and run a Jupyter notebook with Python
As with the developer virtual machine before, using Azure notebooks ensures a consistent environment for the
exercise.

NOTE
Once set up, the Azure Notebooks service can be accessed from any machine. During setup, you should use the
development virtual machine, which has all of the files that you will need.
Create an Azure Notebooks account
Azure Notebook accounts are independent from Azure subscriptions. To use Azure Notebooks, you need to create
an account.
1. Navigate to Azure notebooks.
2. Click Sign In in the upper, right-hand corner of the page.
3. Sign in with either your work or school account (Azure Active Directory) or your personal account
(Microsoft Account).
4. If you have not used Azure Notebooks before, you will be prompted to grant access for the Azure
Notebooks app.
5. Create a user ID for Azure Notebooks.
Upload Jupyter notebooks files
In this step, we create a new Azure Notebooks project and upload files to it. Specifically, the files that we upload
are:
01-turbofan_regression.ipynb: Jupyter notebook file that walks through the process of downloading the
data generated by the device harness from the Azure storage account; exploring and preparing the data for
training the classifier; training the model; testing the data using the test dataset found in the Test_FD003.txt
file; and, finally saving the classifier model in the Machine Learning service workspace.
02-turbofan_deploy_model.ipynb: Jupyter notebook that guides you through the process of using the
classifier model saved in the Machine Learning service workspace to produce a container image. Once the
image is created, the notebook walks you through the process of deploying the image as a web service so
that you can validate it is working as expected. The validated image will be deployed to our IoT Edge device
in the Create and deploy custom IoT Edge modules portion of this tutorial.
Test_FD003.txt: This file contains the data we will use as our test set when validating our trained classifier.
We chose to use the test data as provided for the original contest as our test set for simplicity of the
example.
RUL_FD003.txt: This file contains the RUL for the last cycle of each device in the Test_FD003.txt file. See
the readme.txt and the Damage Propagation Modeling.pdf files in the
C:\source\IoTEdgeAndMlSample\data\Turbofan for a detailed explanation of the data.
Utils.py: Contains a set of Python utility functions for working with data. The first notebook contains a
detailed explanation of the functions.
README.md: Readme describing the use of the notebooks.
Create a new project and upload the files to your notebook.
1. Select My Projects from the top menu bar.
2. Select + New Project. Provide a name and an ID. There is no need for the project to be public or to have a
readme.
3. Select Upload and choose From Computer.
4. Select Choose files.
5. Navigate to C:\source\IoTEdgeAndMlSample\AzureNotebooks. Select all files and click Open.
6. Select Upload to begin uploading and then select Done once the process is complete.
Run Azure Notebooks
Now that the project is created, run the 01-turbofan_regression.ipynb notebook.
1. From the turbofan project page, select 01-turbofan_regression.ipynb.

2. If prompted, choose the Python 3.6 Kernel from the dialog and select Set Kernel.
3. If the notebook is listed as Not Trusted, click on the Not Trusted widget in the top right of the notebook.
When the dialog comes up, select Trust.
4. Follow the instructions in the notebook.
Ctrl + Enter runs a cell.
Shift + Enter runs a cell and navigates to the next cell.
When a cell is running, it has an asterisk between the square brackets, like [*]. When it is complete, the
asterisk will be replaced with a number and relevant output may be appear below. Since cells often build
on the work of the previous ones, only one cell can run at a time.
5. When you have finished running the 01-turbofan_regression.ipynb notebook, return to the project page.
6. Open 02-turbofan_deploy_model.ipynb and repeat the steps in this section to run the second notebook.

Next steps
In this article, we used two Jupyter Notebooks running in Azure Notebooks to use the data from the turbofan
devices to train a remaining useful life (RUL ) classifier, to save the classifier as a model, to create a container image,
and to deploy and test the image as a web service.
Continue to the next article to create an IoT Edge device.
Configure an IoT Edge device
Tutorial: Configure an IoT Edge device
12/2/2019 • 10 minutes to read • Edit Online

NOTE
This article is part of a series for a tutorial about using Azure Machine Learning on IoT Edge. If you have arrived at this article
directly, we encourage you to begin with the first article in the series for the best results.

In this article, we configure an Azure Virtual Machine running Linux to be an Azure IoT Edge device that acts as a
transparent gateway. The transparent gateway configuration allows devices to connect to Azure IoT Hub through
the gateway without knowing that the gateway exists. At the same time, a user interacting with the devices in IoT
Hub is unaware of the intermediate gateway device. Ultimately, we use the transparent gateway to add edge
analytics to our system by adding IoT Edge modules to the gateway.
The steps in this article are typically performed by a cloud developer.

Generate certificates
For a device to function as a gateway it needs to be able to securely connect to downstream devices. Azure IoT
Edge allows you to use a public key infrastructure (PKI) to set up secure connections between devices. In this case,
we’re allowing a downstream device to connect to an IoT Edge device acting as a transparent gateway. To maintain
reasonable security, the downstream device should confirm the identity of the IoT Edge device. For more
information about how IoT Edge devices use certificates, see Azure IoT Edge certificate usage details.
In this section, we create the self-signed certificates using a Docker image that we then build and run. We chose to
use a Docker image to complete this step as it significantly reduced the number of steps needed to create the
certificates on the Windows development machine. See Generate certificates with Windows for the details on how
to produce the certificates without using a container. Generate certificates with Linux has the set of instructions
that we automated with the Docker image.
1. Sign in to your development virtual machine.
2. Open a command-line prompt and run the following command to create a directory on the VM.

mkdir c:\edgeCertificates

3. Start Docker for Windows from the Windows Start menu.


4. Open Visual Studio Code.
5. Select File > Open Folder... and choose C:\source\IoTEdgeAndMlSample\CreateCertificates.
6. Right-click on the dockerfile and choose Build Image.
7. In the dialog, accept the default value for the image name and tag: createcertificates:latest.
8. Wait for the build to complete.
NOTE
You may see a warning for about a missing public key. It is safe to ignore this warning. Likewise, you will see a
security warning that recommends you check/reset permissions on your image, which is safe to ignore for this image.

9. In the Visual Studio Code terminal window, run the createcertificates container.

docker run --name createcertificates --rm -v c:\edgeCertificates:/edgeCertificates createcertificates


/edgeCertificates

10. Docker will prompt for access to the c:\ drive. Select Share it.
11. Provide your credentials when prompted.
12. Once the container finishes running, check for the following files in c:\edgeCertificates:
c:\edgeCertificates\certs\azure-iot-test-only.root.ca.cert.pem
c:\edgeCertificates\certs\new -edge-device-full-chain.cert.pem
c:\edgeCertificates\certs\new -edge-device.cert.pem
c:\edgeCertificates\certs\new -edge-device.cert.pfx
c:\edgeCertificates\private\new -edge-device.key.pem

Upload certificates to Azure Key Vault


To store our certificates securely and to make them accessible from multiple devices, we will upload the certificates
into Azure Key Vault. As you can see from the list above, we have two types of certificate files: PFX and PEM. We
will treat the PFX as Key Vault Certificates to be uploaded to Key Vault. The PEM files are plain text and we will
treat them as Key Vault Secrets. We will use the Key Vault associated with the Azure Machine Learning workspace
we created by running the Azure Notebooks.
1. From the Azure portal, navigate to your Azure Machine Learning workspace.
2. From the overview page of the Azure Machine Learning workspace, find the name of the Key Vault.

3. On your development machine, upload the certificates to Key Vault. Replace <subscriptionId> and
<keyvaultname> with your resource information.

c:\source\IoTEdgeAndMlSample\CreateCertificates\upload-keyvaultcerts.ps1 -SubscriptionId
<subscriptionId> -KeyVaultName <keyvaultname>

4. If prompted, sign in to Azure.


5. The script will run for few minutes with output that lists the new Key Vault entries.
Create IoT Edge device
To connect an Azure IoT Edge device to an IoT hub, we first create an identity for the device in the hub. We take the
connection string from the device identity in the cloud and use it to configure the runtime on our IoT Edge device.
Once the device has been configured and connects to the hub, we are able to deploy modules and send messages.
We can also change the configuration of the physical IoT Edge device by changing the configuration of the
corresponding device identity in IoT hub.
For this tutorial, we create the new device identity using Visual Studio Code. You can also complete these steps
using the Azure portal, or Azure CLI.
1. On your development machine, open Visual Studio Code.
2. Open the Azure IoT Hub devices frame from the Visual Studio Code explorer view.
3. Click on the ellipsis and select Create IoT Edge Device.
4. Give the device a name. For convenience, we use aaTurbofanEdgeDevice so it sorts ahead of all of the
client devices we created earlier through the device harness to send the test data.
5. The new device will appear in the list of devices.

Deploy Azure Virtual Machine


We use the Azure IoT Edge on Ubuntu image from the Azure Marketplace to create our IoT Edge device for this
tutorial. The Azure IoT Edge on Ubuntu image installs the latest Azure IoT Edge runtime and its dependencies on
startup. We deploy the VM using a PowerShell script, Create-EdgeVM.ps1 ; a Resource Manager template,
IoTEdgeVMTemplate.json ; and a shell script, install packages.sh .

Enable programmatic deployment


To use the image from the marketplace in a scripted deployment, we need to enable programmatic deployment for
the image.
1. Sign in to the Azure portal.
2. Select All services.
3. In the search bar, enter and select Marketplace.
4. In the search bar, enter and select Azure IoT Edge on Ubuntu.
5. Select the Want to deploy programmatically? Get started hyperlink.
6. Select the Enable button, then Save.
7. You will see a success notification.
Create virtual machine
Next, run the script to create the virtual machine for your IoT Edge device.
1. Open a PowerShell window and navigate to the EdgeVM directory.

cd c:\source\IoTEdgeAndMlSample\EdgeVM

2. Run the script to create the virtual machine.

.\Create-EdgeVm.ps1

3. When prompted, provide values for each parameter. For subscription, resource group, and location we
recommend you use the same as you have for all resources throughout this tutorial.
Azure Subscription ID: found in the Azure portal
Resource Group Name: memorable name for grouping the resources for this tutorial
Location: Azure location where the virtual machine will be created. For example, westus2 or
northeurope. For more, see all Azure locations.
AdminUsername: the name for the admin account you will use to sign in to the virtual machine
AdminPassword: the password to set for the AdminUsername on the virtual machine
4. For the script to be able to set up the VM, you need to sign in to Azure with the credentials associated with
the Azure Subscription you are using.
5. The script confirms the information for the creation of your VM. Select y or Enter to continue.
6. The script runs for several minutes as it executes the following steps:
Create the resource group if it does not exist already
Create the virtual machine
Add NSG exceptions for the VM for ports 22 (SSH), 5671 (AMQP ), 5672 (AMPQ ), and 443 (SSL )
Install the Azure CLI)
7. The script outputs the SSH connection string for connecting to the VM. Copy the connection string for the
next step.

Connect to your IoT Edge device


The next several sections configure the Azure virtual machine we created. The first step is to connect to the virtual
machine.
1. Open a command prompt and paste the SSH connection string you copied from the script output. Enter
your own information for username, suffix, and region according to the values you supplied to the
PowerShell script in the previous section.

ssh -l <username> iotedge-<suffix>.<region>.cloudapp.azure.com

2. When prompted to validate the authenticity of the host, type yes and select Enter.
3. When prompted, provide your password.
4. Ubuntu displays a welcome message and then you should see a prompt like <username>@<machinename>:~$ .

Download Key Vault certificates


Earlier in this article, we uploaded certificates to Key Vault to make them available for our IoT Edge device and our
leaf device, which is a downstream device that uses the IoT Edge device as a gateway to communicate with IoT
Hub. We will deal with the leaf device later in the tutorial. In this section, download the certificates to the IoT Edge
device.
1. From the SSH session on the Linux virtual machine, sign in to Azure with the Azure CLI.

az login

2. You will be prompted to open a browser to https://microsoft.com/devicelogin and provide a unique code.
You can perform these steps on your local machine. Close the browser window when you're done
authenticating.
3. When you successfully authenticate, the Linux VM will sign in and list your Azure subscriptions.
4. ASet the Azure subscription that you want to use for Azure CLI commands.

az account set --subscription <subscriptionId>

5. Create a directory on the VM for the certificates.

sudo mkdir /edgeMlCertificates

6. Download the certificates that you stored in the key vault: new -edge-device-full-chain.cert.pem, new -edge-
device.key.pem, and azure-iot-test-only.root.ca.cert.pem

key_vault_name="<key vault name>"


sudo az keyvault secret download --vault-name $key_vault_name --name new-edge-device-full-chain-cert-pem
-f /edgeMlCertificates/new-edge-device-full-chain.cert.pem
sudo az keyvault secret download --vault-name $key_vault_name --name new-edge-device-key-pem -f
/edgeMlCertificates/new-edge-device.key.pem
sudo az keyvault secret download --vault-name $key_vault_name --name azure-iot-test-only-root-ca-cert-
pem -f /edgeMlCertificates/azure-iot-test-only.root.ca.cert.pem

Update the IoT Edge device configuration


The IoT Edge runtime uses the file /etc/iotedge/config.yaml to persist its configuration. We need to update three
pieces of information in this file:
Device connection string: the connection string from this device's identity in IoT Hub
Certificates: the certificates to use for connections made with downstream devices
Hostname: the fully qualified domain name (FQDN ) of the VM IoT Edge device.
The Azure IoT Edge on Ubuntu image that we used to create the IoT Edge VM comes with a shell script that
updates the config.yaml with the connection string.
1. In Visual Studio Code right-click on the IoT Edge device, then select Copy Device Connection String.

2. In your SSH session, run the command to update the config.yaml file with your device connection string.

sudo /etc/iotedge/configedge.sh "<your_iothub_edge_device_connection_string>"

Next we will update the certificates and hostname by directly editing the config.yaml.
1. Open the config.yaml file.
sudo nano /etc/iotedge/config.yaml

2. Update the certificates section of the config.yaml by removing the leading # and setting the path so the file
looks like the following example:

certificates:
device_ca_cert: "/edgeMlCertificates/new-edge-device-full-chain.cert.pem"
device_ca_pk: "/edgeMlCertificates/new-edge-device.key.pem"
trusted_ca_certs: "/edgeMlCertificates/azure-iot-test-only.root.ca.cert.pem"

Make sure the “certificates:” has no preceding whitespace and that each of the certificates is preceded by
two spaces.
Right-clicking in nano will paste the contents of your clipboard to the current cursor position. To replace the
string, use your keyboard arrows to navigate to the string you want to replace, delete the string, then right-
click to paste from the buffer.
3. In the Azure portal, navigate to your virtual machine. Copy the DNS name (FQDN of the machine) from the
Overview section.
4. Paste the FQDN into the hostname section of the config.yml. Make sure that the name is all lowercase.

hostname: '<machinename>.<region>.cloudapp.azure.com'

5. Save and close the file ( Ctrl + X , Y , Enter ).


6. Restart the iotedge daemon.

sudo systemctl restart iotedge

7. Check the status of the IoT Edge Daemon (after the command, type “:q” to exit).

systemctl status iotedge

8. If you see errors (colored text prefixed with “[ERROR ]”) in the status Examine daemon logs for detailed
error information.

journalctl -u iotedge --no-pager --no-full

Next steps
We just completed configuring an Azure VM as Azure IoT Edge Transparent Gateway. We started by generating
test certificates, which we uploaded to Azure Key Vault. Next, we used a script and Resource Manager template to
deploy the VM with the “Ubuntu Server 16.04 LTS + Azure IoT Edge runtime” image from the Azure marketplace.
The script took the extra step of installing the Azure CLI (Install Azure CLI with apt). With the VM up and running
we connected via SSH, signed into Azure, downloaded certificates from Key Vault, and made several updates to the
configuration of the IoT Edge Runtime by updating the config.yaml file. For more information about using IoT
Edge as a gateway, see How an IoT Edge device can be used as a gateway. For more information on how to
configure an IoT Edge device as a transparent gateway, see Configure an IoT Edge device to act as a transparent
gateway.
Continue to the next article to build IoT Edge modules.
Create and deploy custom IoT Edge modules
Tutorial: Create and deploy custom IoT Edge
modules
12/2/2019 • 23 minutes to read • Edit Online

NOTE
This article is part of a series for a tutorial about using Azure Machine Learning on IoT Edge. If you have arrived at this article
directly, we encourage you to begin with the first article in the series for the best results.

In this article, we create three IoT Edge modules that receive messages from leaf devices, run the data through
your machine learning model, and then forward insights to IoT Hub.
IoT Edge hub facilitates module to module communication. Using the IoT Edge hub as a message broker keeps
modules independent from each other. Modules only need to specify the inputs on which they accept messages
and the outputs to which they write messages.
We want the IoT Edge device to accomplish four things for us:
Receive data from the leaf devices
Predict remaining useful life (RUL ) for the device that sent the data
Send a message with only the RUL for the device to IoT Hub (this function could be modified to only send data
if the RUL drops below some level)
Save the leaf device data to a local file on the IoT Edge device. This data file is periodically uploaded to IoT Hub
via file upload to refine training of the machine learning model. Using file upload instead of constant message
streaming is more cost effective.
To accomplish these tasks, we use three custom modules:
RUL Classifier: The turboFanRulClassifier module we created in Train and deploy an Azure Machine
Learning model is a standard machine learning module, which exposes an input called "amlInput" and an
output called "amlOutput". The "amlInput" expects its input to look exactly like the input that we sent to the
ACI-based web service. Likewise, "amlOutput" returns the same data as the web service.
Avro writer: This module receives messages on the "avroModuleInput" input and persists the message in
Avro format to disk for later upload to IoT Hub.
Router Module: The router module receives messages from downstream leaf devices, then formats and
sends the messages to the classifier. The module then receives the messages from the classifier and
forwards the message onto the Avro writer module. Finally, the module sends just the RUL prediction to
the IoT Hub.
Inputs:
deviceInput: receives messages from leaf devices
rulInput: receives messages from the "amlOutput"
Outputs:
classify: sends messages to "amlInput"
writeAvro: sends messages "avroModuleInput"
toIotHub: sends messages to $upstream, which passes the messages to the connected IoT Hub
The diagram below shows the modules, inputs, outputs, and the IoT Edge Hub routes for the full solution:

The steps in this article are typically performed by a cloud developer.

Create a new IoT Edge solution


During execution of the second of our two Azure Notebooks, we created and published a container image
containing our RUL model. Azure Machine Learning, as part of the image creation process, packaged that model
so that the image is deployable as an Azure IoT Edge module. In this step, we are going to create an Azure IoT
Edge solution using the “Azure Machine Learning” module and point the module to the image we published using
Azure Notebooks.
1. Open a remote desktop session to your development machine.
2. Open folder C:\source\IoTEdgeAndMlSample in Visual Studio Code.
3. Right click on the explorer panel (in the blank space) and select New IoT Edge Solution.

4. Accept the default solution name EdgeSolution.


5. Choose Azure Machine Learning as the module template.
6. Name the module turbofanRulClassifier.
7. Choose your machine learning workspace.
8. Select the image you created while running the Azure Notebook.
9. Look at the solution and notice the files that have been created:
deployment.template.json: This file contains the definition of each of the modules in the solution.
There are three sections to pay attention to in this file:
Registry credentials: Defines the set of custom container registries you are using in your
solution. Right now, it should contain the registry from your machine learning workspace,
which is where your Azure Machine Learning image was stored. You can have any number of
container registries, but for simplicity we will use this one registry for all modules

"registryCredentials": {
"<your registry>": {
"username": "$CONTAINER_REGISTRY_USERNAME_<your registry>",
"password": "$CONTAINER_REGISTRY_PASSWORD_<your registry>",
"address": "<your registry>.azurecr.io"
}
}

Modules: This section contains the set of user-defined modules that go with this solution. You
will notice that this section currently contains two modules: SimulatedTemperatureSensor and
turbofanRulClassifier. The SimulatedTemperatureSensor was installed by the Visual Studio
Code template, but we don’t need it for this solution. You can delete the
SimulatedTemperatureSensor module definition from the modules section. Note that the
turbofanRulClassifier module definition points to the image in your container registry. As we
add more modules to the solution, they will show up in this section.

"modules": {
"SimulatedTemperatureSensor": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0",
"createOptions": {}
}
},
"turbofanRulClassifier": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "<your registry>.azurecr.io/edgemlsample:1",
"createOptions": {}
}
}
}

Routes: we will be working with routes quite a bit in this tutorial. Routes define how modules
communicate with each other. The two routes defined by the template do not match with the
routing we need. The first route sends all the data from any output of the classifier to the IoT
Hub ($upstream). The other route is for SimulatedTemperatureSensor, which we just deleted.
Delete the two default routes.
"$edgeHub": {
"properties.desired": {
"schemaVersion": "1.0",
"routes": {
"turbofanRulClassifierToIoTHub": "FROM
/messages/modules/turbofanRulClassifier/outputs/\* INTO $upstream",
"sensorToturbofanRulClassifier": "FROM
/messages/modules/SimulatedTemperatureSensor/outputs/temperatureOutput INTO
BrokeredEndpoint(\\"/modules/turbofanRulClassifier/inputs/input1\\")"
},
"storeAndForwardConfiguration": {
"timeToLiveSecs": 7200
}
}
}

deployment.debug.template.json: this file is the debug version of deployment.template.json. We


should mirror all of the changes from the deployment.template.json into this file.
.env: this file is where you should supply the username and password for accessing your registry.

CONTAINER_REGISTRY_USERNAME_<your registry name>=<ACR username>


CONTAINER_REGISTRY_PASSWORD_<your registry name>=<ACR password>

10. Right click on the deployment.template.json file in Visual Studio Code explorer and select Build IoT Edge
Solution.
11. Notice that this command creates a config folder with a deployment.amd64.json file. This file is the concrete
deployment template for the solution.

Add Router module


Next, we add the Router module to our solution. The Router module handles several responsibilities for our
solution:
Receive messages from leaf devices: as messages arrive to the IoT Edge device from downstream devices,
the Router module receives the message and begins orchestrating the routing of the message.
Send messages to the RUL Classifier module: when a new message is received from a downstream device,
the Router module transforms the message to the format that the RUL Classifier expects. The Router sends the
message to the RUL Classifier for a RUL prediction. Once the classifier has made a prediction, it sends the
message back to the Router module.
Send RUL messages to IoT Hub: when the Router receives messages from the classifier, it transforms the
message to contain only the essential information, device ID and RUL, and sends the abbreviated message to
the IoT hub. A further refinement, which we have not done here, would send messages to the IoT Hub only
when the RUL prediction falls below a threshold (for example, when the RUL is fewer than 100 cycles). Filtering
in this way would reduce volume of messages and reduce cost of the IoT hub.
Send message to the Avro Writer module: to preserve all the data sent by the downstream device, the
Router module sends the entire message received from the classifier to the Avro Writer module, which will
persist and upload the data using IoT Hub file upload.

NOTE
The description of the module responsibilities may make the processing seem sequential, but the flow is message/event
based. This is why we need an orchestration module like our Router module.
Create module and copy files
1. Right click on the modules folder in Visual Studio Code and choose Add IoT Edge Module.
2. Choose C# module.
3. Name the module turbofanRouter.
4. When prompted for your Docker Image Repository, use the registry from the machine learning workspace
(you can find the registry in the registryCredentials node of your deployment.template.json file). This value
is the fully qualified address to the registry, like <your registry>.azurecr.io/turbofanrouter.

NOTE
In this article, we use the Azure Container Registry created by the Azure Machine Learning workspace, which we used
to train and deploy our classifier. This is purely for convenience. We could have created a new container registry and
published our modules there.

5. Open a new terminal window in Visual Studio Code (View > Terminal) and copy files from the modules
directory.

copy c:\source\IoTEdgeAndMlSample\EdgeModules\modules\turbofanRouter\*.cs
c:\source\IoTEdgeAndMlSample\EdgeSolution\modules\turbofanRouter\

6. When prompted to overwrite program.cs, press y and then hit Enter .


Build router module
1. In Visual Studio Code, select Terminal > Configure Default Build Task.
2. Click on Create tasks.json file from template.
3. Click on .NET Core.
4. When tasks.json opens replace the contents with:

{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "shell",
"group": {
"kind": "build",
"isDefault": true
},
"args": [
"build",
"${workspaceFolder}/modules/turbofanRouter"
],
"presentation": {
"reveal": "always"
},
"problemMatcher": "$msCompile"
}
]
}

5. Save and close tasks.json.


6. Run build with Ctrl + Shift + B or Terminal > Run Build Task.
Set up module routes
As mentioned above, the IoT Edge runtime uses routes configured in the deployment.template.json file to manage
communication between loosely coupled modules. In this section, we drill into how to set up the routes for the
turbofanRouter module. We will cover the input routes first and then move on the outputs.
Inputs
1. In the Init() method of Program.cs we register two callbacks for the module:

await ioTHubModuleClient.SetInputMessageHandlerAsync(EndpointNames.FromLeafDevice,
LeafDeviceInputMessageHandler, ioTHubModuleClient);
await ioTHubModuleClient.SetInputMessageHandlerAsync(EndpointNames.FromClassifier,
ClassifierCallbackMessageHandler, ioTHubModuleClient);

2. The first callback listens for messages sent to the deviceInput sink. From the diagram above, we see that
we want to route messages from any leaf device to this input. In the deployment.template.json file, add a
route that tells the edge hub to route any message received by the IoT Edge device that was not sent by an
IoT Edge module into the input called "deviceInput" on the turbofanRouter module:

"leafMessagesToRouter": "FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO


BrokeredEndpoint(\"/modules/turbofanRouter/inputs/deviceInput\")"

3. Next add a route for messages from the rulClassifier module into the turbofanRouter module:

"classifierToRouter": "FROM /messages/modules/turbofanRulClassifier/outputs/amloutput INTO


BrokeredEndpoint(\"/modules/turbofanRouter/inputs/rulInput\")"

Outputs
Add four additional routes to the $edgeHub route parameter, to handle outputs from the Router module.
1. Program.cs defines the method SendMessageToClassifier(), which uses the module client to send a
message to the RUL classifier using the route:

"routerToClassifier": "FROM /messages/modules/turbofanRouter/outputs/classOutput INTO


BrokeredEndpoint(\"/modules/turbofanRulClassifier/inputs/amlInput\")"

2. SendRulMessageToIotHub() uses the module client to send just the RUL data for the device to the IoT Hub
via the route:

"routerToIoTHub": "FROM /messages/modules/turboFanRouter/outputs/hubOutput INTO $upstream"

3. SendMessageToAvroWriter() uses the module client to send the message with the RUL data added to the
avroFileWriter module.

"routerToAvro": "FROM /messages/modules/turbofanRouter/outputs/avroOutput INTO


BrokeredEndpoint(\"/modules/avroFileWriter/inputs/avroModuleInput\")"

4. HandleBadMessage() sends failed messages upstream the IoT Hub where they can be routed for later.

"deadLetter": "FROM /messages/modules/turboFanRouter/outputs/deadMessages INTO $upstream"


With all the routes taken together your “$edgeHub” node should look like the following JSON:

"$edgeHub": {
"properties.desired": {
"schemaVersion": "1.0",
"routes": {
"leafMessagesToRouter": "FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO
BrokeredEndpoint(\"/modules/turbofanRouter/inputs/deviceInput\")",
"classifierToRouter": "FROM /messages/modules/turbofanRulClassifier/outputs/amlOutput INTO
BrokeredEndpoint(\"/modules/turbofanRouter/inputs/rulInput\")",
"routerToClassifier": "FROM /messages/modules/turbofanRouter/outputs/classOutput INTO
BrokeredEndpoint(\"/modules/turbofanRulClassifier/inputs/amlInput\")",
"routerToIoTHub": "FROM /messages/modules/turboFanRouter/outputs/hubOutput INTO $upstream",
"routerToAvro": "FROM /messages/modules/turbofanRouter/outputs/avroOutput INTO
BrokeredEndpoint(\"/modules/avroFileWriter/inputs/avroModuleInput\")",
"deadLetter": "FROM /messages/modules/turboFanRouter/outputs/deadMessages INTO $upstream"
},
"storeAndForwardConfiguration": {
"timeToLiveSecs": 7200
}
}
}

NOTE
Adding the turbofanRouter module created the following additional route:
turbofanRouterToIoTHub": "FROM /messages/modules/turbofanRouter/outputs/* INTO $upstream . Remove this route,
leaving only the routes listed above in your deployment.template.json file.

Copy routes to deployment.debug.template.json


As a final step, to keep our files in sync, mirror the changes you made to deployment.template.json in
deployment.debug.template.json.

Add Avro Writer module


The Avro Writer module has two responsibilities in our solution, to store messages and upload files.
Store messages: when the Avro Writer module receives a message, it writes the message to the local file
system in Avro format. We use a bind mount, which mounts a directory (in this case /data/avrofiles) into a
path in the module’s container. This mount allows the module to write to a local path (/avrofiles) and have
those files accessible directly from the IoT Edge device.
Upload files: the Avro Writer module uses the Azure IoT Hub file upload feature to upload files to an
Azure storage account. Once a file is successfully uploaded, the module deletes the file from disk
Create module and copy files
1. In the command palette, search for then select Python: Select Interpreter.
2. Choose the interpreter found in C:\Python37.
3. Open the command palette again and search for then select Terminal: Select Default Shell.
4. When prompted, choose Command Prompt.
5. Open a new terminal shell, Terminal > New Terminal.
6. Right click on the modules folder in Visual Studio Code and choose Add IoT Edge Module.
7. Choose Python Module.
8. Name the module "avroFileWriter".
9. When prompted for your Docker Image Repository, use the same registry as you used when adding the
Router module.
10. Copy files from the sample module into the solution.

copy C:\source\IoTEdgeAndMlSample\EdgeModules\modules\avroFileWriter\*.py
C:\source\IoTEdgeAndMlSample\EdgeSolution\modules\avroFileWriter\

11. If prompted to overwrite main.py, type y and then hit Enter .


12. Notice that filemanager.py and schema.py have been added to the solution and main.py has been updated.

NOTE
When you open a Python file you may be prompted to install pylint. You do not need to install the linter to complete this
tutorial.

Bind mount for data files


As mentioned in the intro, the writer module relies on the presence of bind mount to write Avro files to the
device’s file system.
Add directory to device
1. Connect to your IoT Edge device VM using SSH.

ssh -l <user>@IoTEdge-<extension>.<region>.cloudapp.azure.com

2. Create the directory that will hold the saved leaf device messages.

sudo mkdir -p /data/avrofiles

3. Update directory permissions to make it writeable by the container.

sudo chmod ugo+rw /data/avrofiles

4. Validate the directory now has write (w ) permission for user, group, and owner.

ls -la /data

Add directory to the module


To add the directory to the module’s container, we will modify the Dockerfiles associated with the avroFileWriter
module. There are three Dockerfiles associated with the module: Dockerfile.amd64, Dockerfile.amd64.debug, and
Dockerfile.arm32v7. These files should be kept in sync in case we wish to debug or deploy to an arm32 device. For
this article, focus only on Dockerfile.amd64.
1. On your development machine, open the Dockerfile.amd64 file.
2. Modify the file so that is looks like the following example:

FROM ubuntu:xenial

WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends libcurl4-openssl-dev


python3-pip libboost-python1.58-dev libpython3-dev && rm -rf /var/lib/apt/lists/*

RUN pip3 install --upgrade pip


COPY requirements.txt ./
RUN pip install -r requirements.txt

COPY . .

RUN useradd -ms /bin/bash moduleuser


RUN mkdir /avrofiles && chown moduleuser /avrofiles
USER moduleuser

CMD [ "python3", "-u", "./main.py" ]

The mkdir and chown commands instruct the Docker build process to create a top-level directory called
/avrofiles in the image and then to make the moduleuser the owner of that directory. It is important that
these commands are inserted after the module user is added to the image with the useradd command and
before the context switches to the moduleuser (USER moduleuser).
3. Make the corresponding changes to Dockerfile.amd64.debug and Dockerfile.arm32v7.
Update the module configuration
The final step of creating the bind is to update the deployment.template.json (and
deployment.debug.template.json) files with the bind information.
1. Open deployment.template.json.
2. Modify the module definition for avroFileWriter by adding the Binds parameter that points the container
directory /avrofiles to the local directory on the edge device. Your module definition should match this
example:

"avroFileWriter": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "${MODULES.avroFileWriter}",
"createOptions": {
"HostConfig": {
"Binds": [
"/data/avrofiles:/avrofiles"
]
}
}
}
}

3. Make the corresponding changes to deployment.debug.template.json.


Bind mount for access to config.yaml
We need to add one more bind for the writer module. This bind gives the module access to read the connection
string from the /etc/iotedge/config.yaml file on the IoT Edge device. We need the connection string to create an
IoTHubClient so that we can call the upload_blob_async method to upload files to the IoT hub. The steps for
adding this bind are similar to the ones in the previous section.
Update directory permission
1. Connect to your IoT Edge device using SSH.

ssh -l <user>@IoTEdge-<extension>.<region>.cloudapp.azure.com

2. Add read permission to the config.yaml file.

sudo chmod +r /etc/iotedge/config.yaml

3. Validate the permissions are set correctly.

ls -la /etc/iotedge/

4. Ensure that the permissions for config.yaml are -r--r--r--.


Add directory to module
1. On your development machine, open the Dockerfile.amd64 file.
2. Add an additional set of mkdir and chown commands to the file so that is looks like:

FROM ubuntu:xenial

WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends libcurl4-openssl-dev


python3-pip libboost-python1.58-dev libpython3-dev && rm -rf /var/lib/apt/lists/\*

RUN pip3 install --upgrade pip


COPY requirements.txt ./
RUN pip install -r requirements.txt

COPY . .

RUN useradd -ms /bin/bash moduleuser


RUN mkdir /avrofiles && chown moduleuser /avrofiles
RUN mkdir -p /app/iotconfig && chown moduleuser /app/iotconfig

USER moduleuser

CMD "python3", "-u", "./main.py"]

3. Make the corresponding changes to Dockerfile.amd64.debug and Dockerfile.arm32v7.


Update the module configuration
1. Open the deployment.template.json file.
2. Modify the module definition for avroFileWriter by adding a second line to the Binds parameter that
points the container directory (/app/iotconfig) to the local directory on the device (/etc/iotedge).
"avroFileWriter": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "${MODULES.avroFileWriter}",
"createOptions": {
"HostConfig": {
"Binds": [
"/data/avrofiles:/avrofiles",
"/etc/iotedge:/app/iotconfig"
]
}
}
}
}

3. Make the corresponding changes to deployment.debug.template.json.

Install dependencies
The writer module takes a dependency on two Python libraries, fastavro and PyYAML. We need to install the
dependencies on our development machine and instruct the Docker build process to install them in our module’s
image.
PyYAML
1. On your development machine, open the requirements.txt file and add pyyaml.

azure-iothub-device-client~=1.4.3
pyyaml

2. Open the Dockerfile.amd64 file and add a pip install command to upgrade setuptools.

FROM ubuntu:xenial

WORKDIR /app

RUN apt-get update && \


apt-get install -y --no-install-recommends libcurl4-openssl-dev python3-pip libboost-python1.58-dev
libpython3-dev && \
rm -rf /var/lib/apt/lists/\*

RUN pip3 install --upgrade pip


RUN pip install -U pip setuptools
COPY requirements.txt ./
RUN pip install -r requirements.txt

COPY . .

RUN useradd -ms /bin/bash moduleuser


RUN mkdir /avrofiles && chown moduleuser /avrofiles
RUN mkdir -p /app/iotconfig && chown moduleuser /app/iotconfig
USER moduleuser

CMD [ "python3", "-u", "./main.py" ]

3. Make the corresponding changes to Dockerfile.amd64.debug.


4. Install pyyaml locally by opening a terminal in Visual Studio Code and typing
pip install pyyaml

Fastavro
1. In requirements.txt, add fastavro after pyyaml.

azure-iothub-device-client~=1.4.3
pyyaml
fastavro

2. Install fastavro to your development machine using the Visual Studio Code terminal.

pip install fastavro

Reconfigure IoT Hub


By introducing the IoT Edge device and modules to the system, we have changed our expectations about what
data will be sent to the hub and for what purpose. We need to reconfigure the routing in the hub to deal with our
new reality.

NOTE
We reconfigure the hub before deploying modules because some of the hub settings, specifically file upload, needs to be
correctly set up for the avroFileWriter module to run correctly

Set up route for RUL messages in IoT Hub


With the router and classifier in place, we expect to receive regular messages containing only the device ID and the
RUL prediction for the device. We want to route the RUL data to its own storage location where we can monitor
the status of the devices, build reports and fire alerts as needed. At the same time, we want any device data that is
still being sent directly by a leaf device that has not yet been attached to our IoT Edge device to continue to route
to the current storage location.
Create a RUL message route
1. In the Azure portal, navigate to your IoT Hub.
2. From the left navigation, choose Message routing.
3. Select Add.
4. Name the route RulMessageRoute.
5. Select Add next to the Endpoint selector and choose Blob storage.
6. In the Add a storage endpoint form, name the endpoint ruldata.
7. Select Pick a container.
8. Choose the storage account used throughout this tutorial, which is named like iotedgeandml<unique
suffix>.
9. Choose the ruldata container and click Select.
10. Click Create to create the storage endpoint.
11. For the Routing query, enter the following query:
IS_DEFINED($body.PredictedRul) AND NOT IS_DEFINED($body.OperationalSetting1)

12. Expand the Test section and then the Message body section. Replace the message with this example of our
expected messages:

{
"ConnectionDeviceId": "aaLeafDevice_1",
"CorrelationId": "b27e97bb-06c5-4553-a064-e9ad59c0fdd3",
"PredictedRul": 132.62721409309165,
"CycleTime": 64.0
}

13. Select Test route. If the test is successful, you see “The message matched the query.”
14. Click Save.
Update turbofanDeviceToStorage route
We don't want to route the new prediction data to our old storage location, so update the route to prevent it.
1. In the IoT Hub Message routing page, select the Routes tab.
2. Select turbofanDeviceDataToStorage, or whatever name you gave to your initial device data route.
3. Update the routing query to

IS_DEFINED($body.OperationalSetting1)

4. Expand the Test section and then the Message body section. Replace the message with this example of our
expected messages:

{
"Sensor13": 2387.96,
"OperationalSetting1": -0.0008,
"Sensor6": 21.61,
"Sensor11": 47.2,
"Sensor9": 9061.45,
"Sensor4": 1397.86,
"Sensor14": 8140.39,
"Sensor18": 2388.0,
"Sensor12": 522.87,
"Sensor2": 642.42,
"Sensor17": 391.0,
"OperationalSetting3": 100.0,
"Sensor1": 518.67,
"OperationalSetting2": 0.0002,
"Sensor20": 39.03,
"DeviceId": 19.0,
"Sensor5": 14.62,
"PredictedRul": 212.00132402791962,
"Sensor8": 2388.01,
"Sensor16": 0.03,
"CycleTime": 42.0,
"Sensor21": 23.3188,
"Sensor15": 8.3773,
"Sensor3": 1580.09,
"Sensor10": 1.3,
"Sensor7": 554.57,
"Sensor19": 100.0
}
5. Select Test route. If the test is successful, you see “The message matched the query.”
6. Select Save.
Configure file upload
Configure the IoT Hub file upload feature to enable the file writer module to upload files to storage.
1. From the left navigator in your IoT Hub, choose File upload.
2. Select Azure Storage Container.
3. Select your storage account from the list.
4. Select the uploadturbofanfiles container and click Select.
5. Select Save. The portal notifies you when the save is complete.

NOTE
We aren't turning on upload notification for this tutorial, but see Receive a file upload notification for details on how to
handle file upload notification.

Build, publish, and deploy modules


Now that we have made the configuration changes, we are ready to build the images and publish them to our
Azure container registry. The build process uses the deployment.template.json file to determine which modules
need to be built. The settings for each module, including version, are found in the module.json file in the module
folder. The build process first runs a Docker build on the Dockerfiles matching the current configuration found in
the module.json file to create an image. Then it publishes the image to the registry from the module.json file with a
version tag matching the one in the module.json file. Finally, it produces a configuration-specific deployment
manifest (for example, deployment.amd64.json), which we will deploy to the IoT Edge device. The IoT Edge device
reads the information from the deployment manifest, and based on the instructions will download the modules,
configure the routes, and set any desired properties. This deployment method has two side effects that you should
be aware of:
Deployment lag: since the IoT Edge runtime must recognize the change to its desired properties before it
starts to reconfigure, it can take some amount of time after you deploy your modules until the runtime
picks them up and starts to update the IoT Edge device.
Module versions matter: if you publish a new version of a module’s container to your container registry
using the same version tags as the previous module, the runtime will not download the new version of the
module. It does a comparison of the version tag of the local image and the desired image from the
deployment manifest. If those versions match, the runtime takes no action. Therefore, it is important to
increment the version of your module each time you wish to deploy new changes. Increment the version by
changing the version property under the tag property in the module.json file for the module you are
changing. Then build and publish the module.
{
"$schema-version": "0.0.1",
"description": "",
"image": {
"repository": "<your registry>.azurecr.io/avrofilewriter",
"tag": {
"version": "0.0.1",
"platforms": {
"amd64": "./Dockerfile.amd64",
"amd64.debug": "./Dockerfile.amd64.debug",
"arm32v7": "./Dockerfile.arm32v7"
}
},
"buildOptions": []
},
"language": "python"
}

Build and publish


1. In Visual Studio Code on your development VM, open a Visual Studio Code terminal window and login to
your container registry.

docker login -u <ACR username> -p <ACR password> <ACR login server>

2. In Visual Studio Code, right-click on deployment.template.json and choose Build and Push IoT Edge
Solution.
View modules in the registry
Once the build successfully completes, we will be able to use the Azure portal to review our published modules.
1. In the Azure portal, navigate to your Azure Machine Learning workspace and click the hyperlink for
Registry.

2. From the registry side navigator, select Repositories.


3. Note that both modules you created, avrofilewriter and turbofanrouter, appear as repositories.
4. Select turbofanrouter and note that you have published one image tagged as 0.0.1-amd64.
Deploy modules to IoT Edge device
We have built and configured the modules in our solution, now we will deploy the modules to the IoT Edge device.
1. In Visual Studio Code, right click on the deployment.amd64.json file in the config folder.
2. Choose Create Deployment for Single Device.
3. Choose your IoT Edge device, aaTurboFanEdgeDevice.
4. Refresh the Azure IoT Hub devices panel in Visual Studio Code explorer. You should see that the three new
modules are deployed but not yet running.
5. Refresh again after a few minutes and you will see the modules running.

NOTE
It can take several minutes for the modules to start and settle into a steady running state. During that time, you may see
modules start and stop as they try to establish a connection with the IoT Edge hub module.

Diagnosing failures
In this section, we share a few techniques for understanding what has gone wrong with a module or modules.
Often a failure can first be spotted from the status in the Visual Studio Code.
Identify failed modules
Visual Studio Code: Look at the Azure IoT Hub devices panel. If most modules are in a running state but
one is stopped, you need to investigate that stopped module further. If all modules are in a stopped state for
a long period of time, it may indicate failure as well.
Azure portal: By navigating to your IoT hub in the portal and then finding the device details page (under
IoT Edge, drill into your device) you may find that a module has reported an error or has never reported
anything to the IoT hub.
Diagnosing from the device
By logging into the IoT Edge device, you can gain access to a good deal of information about the status of your
modules. The main mechanism we use are the Docker commands that let us examine the containers and images
on the device.
1. List all running containers. We expect to see a container for each module with a name that corresponds to
the module. Also, this command lists the exact image for the container including version so you can match
with your expectation. You can also list images by substituting “image” for “container” in the command.

sudo docker container ls

2. Get the logs for a container. This command outputs whatever has been written to StdErr and StdOut in the
container. This command works for containers that have started and then died for some reason. It is also
useful for understanding what has been happening with the edgeAgent or edgeHub containers.
sudo docker container logs <container name>

3. Inspect a container. This command gives a ton of information about the image. The data can be filtered
depending on what you are looking for. As an example, if you want to see if the binds on the avroFileWriter
are correct you can use the command:

sudo docker container inspect -f "{{ json .Mounts }}" avroFileWriter | python -m json.tool

4. Connect to a running container. This command can be helpful if you want to examine the container while it
is running:

sudo docker exec -it avroFileWriter bash

Next steps
In this article, we created an IoT Edge Solution in Visual Studio Code with three modules, a classifier, a router, and
a file writer/uploader. We set up the routes to allow the modules to communicate with each other on the edge
device, modified the configuration of the edge device, and updated the Dockerfiles to install dependencies and add
bind mounts to the modules’ containers. Next, we updated the configuration of the IoT Hub to route our messages
based on type and to handle file uploads. With everything in place, we deployed the modules to the IoT Edge
device and ensured the modules were running correctly.
More information can be found at the following pages:
Learn how to deploy modules and establish routes in IoT Edge
IoT Hub message routing query syntax
IoT Hub message routing: now with routing on message body
Upload files with IoT Hub
Upload files from your device to the cloud with IoT Hub
Continue to the next article to start sending data and see your solution in action.
Send data via transparent gateway
Tutorial: Send data via transparent gateway
12/2/2019 • 6 minutes to read • Edit Online

NOTE
This article is part of a series for a tutorial about using Azure Machine Learning on IoT Edge. If you have arrived at this article
directly, we encourage you to begin with the first article in the series for the best results.

In this article, we once again use the development machine as a simulated device, but instead of sending data
directly to the IoT Hub the device sends data to the IoT Edge device configured as a transparent gateway.
We monitor the operation of the IoT Edge device while the simulated device is sending data. Once the device is
finished running, we look at the data in our storage account to validate everything worked as expected.
This step is typically performed by a cloud or device developer.

Review device harness


Reuse the DeviceHarness project to simulate the downstream (or leaf) device. Connecting to the transparent
gateway requires two additional things:
Register the certificate to make the downstream device (in this case our development machine) trust the
certificate authority being used by the IoT Edge runtime.
Add the edge gateway fully qualified domain name (FQDN ) to the device connection string.
Look at the code to see how these two items are implemented.
1. On your development machine open Visual Studio Code.
2. Use File > Open Folder... to open C:\source\IoTEdgeAndMlSample\DeviceHarness.
3. Look at the InstallCertificate() method in Program.cs.
4. Note that if the code finds the certificate path, it calls the CertificateManager.InstallCACert method to install
the certificate on the machine.
5. Now look at the GetIotHubDevice method on the TurbofanDevice class.
6. When the user specifies the FQDN of the gateway using the “-g” option, that value is passed to this method
as gatewayFqdn, which gets appended to the device connection string.

connectionString = $"{connectionString};GatewayHostName={gatewayFqdn.ToLower()}";

Build and run leaf device


1. With the DeviceHarness project still open in Visual Studio Code, build the project (Ctrl + Shift + B or
Terminal > Run Build Task...) and select Build from the dialog.
2. Find the fully qualified domain name (FQDN ) for your edge gateway by navigating to your IoT Edge device
virtual machine in the portal and copying the value for DNS name from the overview.
3. Open the Visual Studio Code terminal (Terminal > New terminal) and run the following command,
replacing <edge_device_fqdn> with the DNS name that you copied from the virtual machine:

dotnet run -- --gateway-host-name "<edge_device_fqdn>" --certificate C:\edgecertificates\certs\azure-


iot-test-only.root.ca.cert.pem --max-devices 1

4. The application attempts to install the certificate onto your development machine. When it does, accept the
security warning.
5. When prompted for the IoT Hub connection string click the ellipsis (...) on the Azure IoT Hub devices panel
and select Copy IoT Hub Connection String. Paste the value into the terminal.
6. You will see output like:

Found existing device: Client_001


Using device connection string: HostName=<your hub>.azure-
devices.net;DeviceId=Client_001;SharedAccessKey=xxxxxxx; GatewayHostName=iotedge-xxxxxx.
<region>.cloudapp.azure.com
Device: 1 Message count: 50
Device: 1 Message count: 100
Device: 1 Message count: 150
Device: 1 Message count: 200
Device: 1 Message count: 250

Note the addition of the “GatewayHostName” to the device connection string, which causes the device to
communicate through the IoT Hub through the IoT Edge transparent gateway.

Check output
IoT Edge device output
The output from the avroFileWriter module can be readily observed by looking at the IoT Edge device.
1. SSH into your IoT Edge virtual machine.
2. Look for files written to disk.

find /data/avrofiles -type f

3. Output of the command will look like the following example:

/data/avrofiles/2019/4/18/22/10.avro

You may have more than a single file depending on timing of the run.
4. Pay attention to the time stamps. The avroFileWriter module uploads the files to the cloud once the last
modification time is more than 10 minutes in the past (see MODIFIED_FILE_TIMEOUT in uploader.py in
the avroFileWriter module).
5. Once the 10 minutes have elapsed, the module should upload the files. If the upload is successful, it deletes
the files from disk.
Azure storage
We can observe the results of our leaf device sending data by looking at the storage accounts where we expect
data to be routed.
1. On the development machine open Visual Studio Code.
2. In the “AZURE STORAGE” panel in the explore window, navigate the tree to find your storage account.
3. Expand the Blob Containers node.
4. From the work we did in the previous portion of the tutorial, we expect that the ruldata container should
contain messages with RUL. Expand the ruldata node.
5. You will see one or more blob files named like:
<IoT Hub Name>/<partition>/<year>/<month>/<day>/<hour>/<minute> .
6. Right click on one of the files and choose Download Blob to save the file to your development machine.
7. Next expand the uploadturbofanfiles node. In the previous article, we set this location as the target for
files uploaded by the avroFileWriter module.
8. Right click on the files and choose Download Blob to save it to your development machine.
Read Avro file contents
We included a simple command-line utility for reading an Avro file and returning a JSON string of the messages in
the file. In this section, we will install and run it.
1. Open a terminal in Visual Studio Code (Terminal > New terminal).
2. Install hubavroreader:

pip install c:\source\IoTEdgeAndMlSample\HubAvroReader

3. Use hubavroreader to read the Avro file that you downloaded from ruldata.

hubavroreader <avro file with ath> | more

4. Note that the body of the message looks as we expected with device ID and predicted RUL.

{
"Body": {
"ConnectionDeviceId": "Client_001",
"CorrelationId": "3d0bc256-b996-455c-8930-99d89d351987",
"CycleTime": 1.0,
"PredictedRul": 170.1723693909444
},
"EnqueuedTimeUtc": "<time>",
"Properties": {
"ConnectionDeviceId": "Client_001",
"CorrelationId": "3d0bc256-b996-455c-8930-99d89d351987",
"CreationTimeUtc": "01/01/0001 00:00:00",
"EnqueuedTimeUtc": "01/01/0001 00:00:00"
},
"SystemProperties": {
"connectionAuthMethod": "
{\"scope\":\"module\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}",
"connectionDeviceGenerationId": "636857841798304970",
"connectionDeviceId": "aaTurbofanEdgeDevice",
"connectionModuleId": "turbofanRouter",
"contentEncoding": "utf-8",
"contentType": "application/json",
"correlationId": "3d0bc256-b996-455c-8930-99d89d351987",
"enqueuedTime": "<time>",
"iotHubName": "mledgeiotwalkthroughhub"
}
}
5. Run the same command passing the Avro file that you downloaded from uploadturbofanfiles.
6. As expected, these messages contain all the sensor data and operational settings from the original message.
This data could be used to improve the RUL model on our edge device.

{
"Body": {
"CycleTime": 1.0,
"OperationalSetting1": -0.0005000000237487257,
"OperationalSetting2": 0.00039999998989515007,
"OperationalSetting3": 100.0,
"PredictedRul": 170.17236328125,
"Sensor1": 518.6699829101562,
"Sensor10": 1.2999999523162842,
"Sensor11": 47.29999923706055,
"Sensor12": 522.3099975585938,
"Sensor13": 2388.010009765625,
"Sensor14": 8145.31982421875,
"Sensor15": 8.424599647521973,
"Sensor16": 0.029999999329447746,
"Sensor17": 391.0,
"Sensor18": 2388.0,
"Sensor19": 100.0,
"Sensor2": 642.3599853515625,
"Sensor20": 39.11000061035156,
"Sensor21": 23.353700637817383,
"Sensor3": 1583.22998046875,
"Sensor4": 1396.8399658203125,
"Sensor5": 14.619999885559082,
"Sensor6": 21.610000610351562,
"Sensor7": 553.969970703125,
"Sensor8": 2387.9599609375,
"Sensor9": 9062.169921875
},
"ConnectionDeviceId": "Client_001",
"CorrelationId": "70df0c98-0958-4c8f-a422-77c2a599594f",
"CreationTimeUtc": "0001-01-01T00:00:00+00:00",
"EnqueuedTimeUtc": "<time>"
}

Clean up resources
If you plan to explore the resources used by this end-to-end tutorial, wait until you are done to clean up the
resources that you created. If you do not plan to continue, use the following steps to delete them:
1. Delete the resource group(s) created to hold the Dev VM, IoT Edge VM, IoT Hub, storage account, machine
learning workspace service (and created resources: container registry, application insights, key vault, storage
account).
2. Delete the machine learning project in Azure notebooks.
3. If you cloned the repo locally, close any PowerShell or VS Code windows referring to the local repo, then
delete the repo directory.
4. If you created certificates locally, delete the folder c:\edgeCertificates.

Next steps
In this article, we used our development machine to simulate a leaf device sending sensor and operational data to
our edge device. We validated that the modules on the device routed, classified, persisted, and uploaded the data
first by examining the real-time operation of the edge device and then by looking at the files uploaded to the
storage account.
More information can be found at the following pages:
Connect a downstream device to an Azure IoT Edge gateway
Store data at the edge with Azure Blob Storage on IoT Edge (preview )
Understand the Azure IoT Edge runtime and its
architecture
11/24/2019 • 7 minutes to read • Edit Online

The IoT Edge runtime is a collection of programs that turn a device into an IoT Edge device. Collectively, the IoT
Edge runtime components enable IoT Edge devices to receive code to run at the edge and communicate the
results.
The IoT Edge runtime is responsible for the following functions on IoT Edge devices:
Install and update workloads on the device.
Maintain Azure IoT Edge security standards on the device.
Ensure that IoT Edge modules are always running.
Report module health to the cloud for remote monitoring.
Manage communication between downstream devices and IoT Edge devices.
Manage communication between modules on the IoT Edge device.
Manage communication between the IoT Edge device and the cloud.

The responsibilities of the IoT Edge runtime fall into two categories: communication and module management.
These two roles are performed by two components that are part of the IoT Edge runtime. The IoT Edge hub is
responsible for communication, while the IoT Edge agent deploys and monitors the modules.
Both the IoT Edge hub and the IoT Edge agent are modules, just like any other module running on an IoT Edge
device. They're sometimes referred to as the runtime modules.

IoT Edge hub


The IoT Edge hub is one of two modules that make up the Azure IoT Edge runtime. It acts as a local proxy for IoT
Hub by exposing the same protocol endpoints as IoT Hub. This consistency means that clients (whether devices
or modules) can connect to the IoT Edge runtime just as they would to IoT Hub.

NOTE
IoT Edge hub supports clients that connect using MQTT or AMQP. It does not support clients that use HTTP.

The IoT Edge hub is not a full version of IoT Hub running locally. There are some things that the IoT Edge hub
silently delegates to IoT Hub. For example, IoT Edge hub forwards authentication requests to IoT Hub when a
device first tries to connect. After the first connection is established, security information is cached locally by IoT
Edge hub. Subsequent connections from that device are allowed without having to authenticate to the cloud.
To reduce the bandwidth your IoT Edge solution uses, the IoT Edge hub optimizes how many actual connections
are made to the cloud. IoT Edge hub takes logical connections from clients like modules or downstream devices
and combines them for a single physical connection to the cloud. The details of this process are transparent to the
rest of the solution. Clients think they have their own connection to the cloud even though they are all being sent
over the same connection.

IoT Edge hub can determine whether it's connected to IoT Hub. If the connection is lost, IoT Edge hub saves
messages or twin updates locally. Once a connection is reestablished, it syncs all the data. The location used for
this temporary cache is determined by a property of the IoT Edge hub’s module twin. The size of the cache is not
capped and will grow as long as the device has storage capacity. For more information, see Offline capabilities.
Module communication
IoT Edge hub facilitates module to module communication. Using IoT Edge hub as a message broker keeps
modules independent from each other. Modules only need to specify the inputs on which they accept messages
and the outputs to which they write messages. A solution developer can stitch these inputs and outputs together
so that the modules process data in the order specific to that solution.

To send data to the IoT Edge hub, a module calls the SendEventAsync method. The first argument specifies on
which output to send the message. The following pseudocode sends a message on output1:

ModuleClient client = await ModuleClient.CreateFromEnvironmentAsync(transportSettings);


await client.OpenAsync();
await client.SendEventAsync("output1", message);

To receive a message, register a callback that processes messages coming in on a specific input. The following
pseudocode registers the function messageProcessor to be used for processing all messages received on input1:

await client.SetInputMessageHandlerAsync("input1", messageProcessor, userContext);

For more information about the ModuleClient class and its communication methods, see the API reference for
your preferred SDK language: C#, C, Python, Java, or Node.js.
The solution developer is responsible for specifying the rules that determine how IoT Edge hub passes messages
between modules. Routing rules are defined in the cloud and pushed down to IoT Edge hub in its module twin.
The same syntax for IoT Hub routes is used to define routes between modules in Azure IoT Edge. For more
information, see Learn how to deploy modules and establish routes in IoT Edge.

IoT Edge agent


The IoT Edge agent is the other module that makes up the Azure IoT Edge runtime. It is responsible for
instantiating modules, ensuring that they continue to run, and reporting the status of the modules back to IoT
Hub. This configuration data is written as a property of the IoT Edge agent module twin.
The IoT Edge security daemon starts the IoT Edge agent on device startup. The agent retrieves its module twin
from IoT Hub and inspects the deployment manifest. The deployment manifest is a JSON file that declares the
modules that need to be started.
Each item in the deployment manifest contains specific information about a module and is used by the IoT Edge
agent for controlling the module’s lifecycle. Some of the more interesting properties are:
settings.image – The container image that the IoT Edge agent uses to start the module. The IoT Edge agent
must be configured with credentials for the container registry if the image is protected by a password.
Credentials for the container registry can be configured remotely using the deployment manifest, or on the
IoT Edge device itself by updating the config.yaml file in the IoT Edge program folder.
settings.createOptions – A string that is passed directly to the Moby container daemon when starting a
module’s container. Adding options in this property allows for advanced configurations like port forwarding or
mounting volumes into a module’s container.
status – The state in which the IoT Edge agent places the module. Usually, this value is set to running as most
people want the IoT Edge agent to immediately start all modules on the device. However, you could specify
the initial state of a module to be stopped and wait for a future time to tell the IoT Edge agent to start a
module. The IoT Edge agent reports the status of each module back to the cloud in the reported properties. A
difference between the desired property and the reported property is an indicator of a misbehaving device.
The supported statuses are:
Downloading
Running
Unhealthy
Failed
Stopped
restartPolicy – How the IoT Edge agent restarts a module. Possible values include:
never – The IoT Edge agent never restarts the module.
on-failure - If the module crashes, the IoT Edge agent restarts it. If the module shuts down cleanly, the
IoT Edge agent does not restart it.
on-unhealthy - If the module crashes or is considered unhealthy, the IoT Edge agent restarts it.
always - If the module crashes, is considered unhealthy, or shuts down in any way, the IoT Edge agent
restarts it.
imagePullPolicy - Whether the IoT Edge agent attempts to pull the latest image for a module automatically
or not. If you don't specify a value, the default is onCreate. Possible values include:
on-create - When starting a module or updating a module based on a new deployment manifest, the
IoT Edge agent will attempt to pull the module image from the container registry.
never - The IoT Edge agent will never attempt to pull the module image from the container registry.
The expectation is that the module image is cached on the device, and any module image updates are
made manually or managed by a third-party solution.
The IoT Edge agent sends runtime response to IoT Hub. Here is a list of possible responses:
200 - OK
400 - The deployment configuration is malformed or invalid.
417 - The device doesn't have a deployment configuration set.
412 - The schema version in the deployment configuration is invalid.
406 - The IoT Edge device is offline or not sending status reports.
500 - An error occurred in the IoT Edge runtime.
For more information, see Learn how to deploy modules and establish routes in IoT Edge.
Security
The IoT Edge agent plays a critical role in the security of an IoT Edge device. For example, it performs actions like
verifying a module’s image before starting it.
For more information about the Azure IoT Edge security framework, read about the IoT Edge security manager.

Next steps
Understand Azure IoT Edge modules
Understand Azure IoT Edge modules
11/24/2019 • 3 minutes to read • Edit Online

Azure IoT Edge lets you deploy and manage business logic on the edge in the form of modules. Azure IoT Edge
modules are the smallest unit of computation managed by IoT Edge, and can contain Azure services (such as
Azure Stream Analytics) or your own solution-specific code. To understand how modules are developed,
deployed, and maintained, it helps to think of the four conceptual elements of a module:
A module image is a package containing the software that defines a module.
A module instance is the specific unit of computation running the module image on an IoT Edge device. The
module instance is started by the IoT Edge runtime.
A module identity is a piece of information (including security credentials) stored in IoT Hub, that is
associated to each module instance.
A module twin is a JSON document stored in IoT Hub, that contains state information for a module instance,
including metadata, configurations, and conditions.

Module images and instances


IoT Edge module images contain applications that take advantage of the management, security, and
communication features of the IoT Edge runtime. You can develop your own module images, or export one from
a supported Azure service, such as Azure Stream Analytics. The images exist in the cloud and they can be
updated, changed, and deployed in different solutions. For instance, a module that uses machine learning to
predict production line output exists as a separate image than a module that uses computer vision to control a
drone.
Each time a module image is deployed to a device and started by the IoT Edge runtime, a new instance of that
module is created. Two devices in different parts of the world could use the same module image. However, each
device would have its own module instance when the module is started on the device.
In implementation, modules images exist as container images in a repository, and module instances are
containers on devices.

Module identities
When a new module instance is created by the IoT Edge runtime, the instance is associated with a corresponding
module identity. The module identity is stored in IoT Hub, and is employed as the addressing and security scope
for all local and cloud communications for that specific module instance.
The identity associated with a module instance depends on the identity of the device on which the instance is
running and the name you provide to that module in your solution. For instance, if you call insight a module
that uses an Azure Stream Analytics, and you deploy it on a device called Hannover01 , the IoT Edge runtime
creates a corresponding module identity called /devices/Hannover01/modules/insight .
Clearly, in scenarios when you need to deploy one module image multiple times on the same device, you can
deploy the same image multiple times with different names.
Module twins
Each module instance also has a corresponding module twin that you can use to configure the module instance.
The instance and the twin are associated with each other through the module identity.
A module twin is a JSON document that stores module information and configuration properties. This concept
parallels the device twin concept from IoT Hub. The structure of a module twin is the same as a device twin. The
APIs used to interact with both types of twins are also the same. The only difference between the two is the
identity used to instantiate the client SDK.

// Create a ModuleClient object. This ModuleClient will act on behalf of a


// module since it is created with a module’s connection string instead
// of a device connection string.
ModuleClient client = new ModuleClient.CreateFromEnvironmentAsync(settings);
await client.OpenAsync();

// Get the module twin


Twin twin = await client.GetTwinAsync();

Offline capabilities
Azure IoT Edge modules can operate offline indefinitely after syncing with IoT Hub at least once. IoT Edge
devices can also extend this offline capability to other IoT devices. For more information, see Understand
extended offline capabilities for IoT Edge devices, modules, and child devices.

Next steps
Understand the requirements and tools for developing IoT Edge modules
Understand the Azure IoT Edge runtime and its architecture
Properties of the IoT Edge agent and IoT Edge hub
module twins
12/1/2019 • 6 minutes to read • Edit Online

The IoT Edge agent and IoT Edge hub are two modules that make up the IoT Edge runtime. For more information
about what duties each module performs, see Understand the Azure IoT Edge runtime and its architecture.
This article provides the desired properties and reported properties of the runtime module twins. For more
information on how to deploy modules on IoT Edge devices, see Learn how to deploy modules and establish
routes in IoT Edge.
A module twin includes:
Desired properties. The solution backend can set desired properties, and the module can read them. The
module can also receive notifications of changes in the desired properties. Desired properties are used
along with reported properties to synchronize module configuration or conditions.
Reported properties. The module can set reported properties, and the solution backend can read and
query them. Reported properties are used along with desired properties to synchronize module
configuration or conditions.

EdgeAgent desired properties


The module twin for the IoT Edge agent is called $edgeAgent and coordinates the communications between the
IoT Edge agent running on a device and IoT Hub. The desired properties are set when applying a deployment
manifest on a specific device as part of a single-device or at-scale deployment.

PROPERTY DESCRIPTION REQUIRED

schemaVersion Has to be "1.0" Yes

runtime.type Has to be "docker" Yes

runtime.settings.minDockerVersion Set to the minimum Docker version Yes


required by this deployment manifest

runtime.settings.loggingOptions A stringified JSON containing the No


logging options for the IoT Edge agent
container. Docker logging options

runtime.settings.registryCredentials The username of the container registry. No


.{registryId}.username For Azure Container Registry, the
username is usually the registry name.

Registry credentials are necessary for


any module images that are not public.

runtime.settings.registryCredentials The password for the container registry. No


.{registryId}.password
PROPERTY DESCRIPTION REQUIRED

runtime.settings.registryCredentials The address of the container registry. No


.{registryId}.address For Azure Container Registry, the
address is usually {registry
name}.azurecr.io.

systemModules.edgeAgent.type Has to be "docker" Yes

systemModules.edgeAgent.settings.ima The URI of the image of the IoT Edge Yes


ge agent. Currently, the IoT Edge agent is
not able to update itself.

systemModules.edgeAgent.settings A stringified JSON containing the No


.createOptions options for the creation of the IoT Edge
agent container. Docker create options

systemModules.edgeAgent.configuratio The ID of the deployment that IoT Hub sets this property when the
n.id deployed this module. manifest is applied using a deployment.
Not part of a deployment manifest.

systemModules.edgeHub.type Has to be "docker" Yes

systemModules.edgeHub.status Has to be "running" Yes

systemModules.edgeHub.restartPolicy Has to be "always" Yes

systemModules.edgeHub.settings.imag The URI of the image of the IoT Edge Yes


e hub.

systemModules.edgeHub.settings A stringified JSON containing the No


.createOptions options for the creation of the IoT Edge
hub container. Docker create options

systemModules.edgeHub.configuration.i The ID of the deployment that IoT Hub sets this property when the
d deployed this module. manifest is applied using a deployment.
Not part of a deployment manifest.

modules.{moduleId}.version A user-defined string representing the Yes


version of this module.

modules.{moduleId}.type Has to be "docker" Yes

modules.{moduleId}.status {"running" | "stopped"} Yes

modules.{moduleId}.restartPolicy {"never" | "on-failure" | "on-unhealthy" | Yes


"always"}

modules.{moduleId}.imagePullPolicy {"on-create" | "never"} No

modules.{moduleId}.settings.image The URI to the module image. Yes

modules. A stringified JSON containing the No


{moduleId}.settings.createOptions options for the creation of the module
container. Docker create options
PROPERTY DESCRIPTION REQUIRED

modules.{moduleId}.configuration.id The ID of the deployment that IoT Hub sets this property when the
deployed this module. manifest is applied using a deployment.
Not part of a deployment manifest.

EdgeAgent reported properties


The IoT Edge agent reported properties include three main pieces of information:
1. The status of the application of the last-seen desired properties;
2. The status of the modules currently running on the device, as reported by the IoT Edge agent; and
3. A copy of the desired properties currently running on the device.
This last piece of information, a copy of the current desired properties, is useful to tell whether the device has
applied the latest desired properties or is still running a previous deployment manifest.

NOTE
The reported properties of the IoT Edge agent are useful as they can be queried with the IoT Hub query language to
investigate the status of deployments at scale. For more information on how to use the IoT Edge agent properties for status,
see Understand IoT Edge deployments for single devices or at scale.

The following table does not include the information that is copied from the desired properties.

PROPERTY DESCRIPTION

lastDesiredVersion This integer refers to the last version of the desired properties
processed by the IoT Edge agent.

lastDesiredStatus.code This status code refers to the last desired properties seen by
the IoT Edge agent. Allowed values: 200 Success, 400
Invalid configuration, 412 Invalid schema version, 417 the
desired properties are empty, 500 Failed

lastDesiredStatus.description Text description of the status

deviceHealth healthy if the runtime status of all modules is either


running or stopped , unhealthy otherwise

configurationHealth.{deploymentId}.health healthy if the runtime status of all modules set by the


deployment {deploymentId} is either running or stopped ,
unhealthy otherwise

runtime.platform.OS Reporting the OS running on the device

runtime.platform.architecture Reporting the architecture of the CPU on the device

systemModules.edgeAgent.runtimeStatus The reported status of IoT Edge agent: {"running" |


"unhealthy"}

systemModules.edgeAgent.statusDescription Text description of the reported status of the IoT Edge agent.
PROPERTY DESCRIPTION

systemModules.edgeHub.runtimeStatus Status of IoT Edge hub: { "running" | "stopped" | "failed" |


"backoff" | "unhealthy" }

systemModules.edgeHub.statusDescription Text description of the status of IoT Edge hub if unhealthy.

systemModules.edgeHub.exitCode The exit code reported by the IoT Edge hub container if the
container exits

systemModules.edgeHub.startTimeUtc Time when IoT Edge hub was last started

systemModules.edgeHub.lastExitTimeUtc Time when IoT Edge hub last exited

systemModules.edgeHub.lastRestartTimeUtc Time when IoT Edge hub was last restarted

systemModules.edgeHub.restartCount Number of times this module was restarted as part of the


restart policy.

modules.{moduleId}.runtimeStatus Status of the module: { "running" | "stopped" | "failed" |


"backoff" | "unhealthy" }

modules.{moduleId}.statusDescription Text description of the status of the module if unhealthy.

modules.{moduleId}.exitCode The exit code reported by the module container if the


container exits

modules.{moduleId}.startTimeUtc Time when the module was last started

modules.{moduleId}.lastExitTimeUtc Time when the module last exited

modules.{moduleId}.lastRestartTimeUtc Time when the module was last restarted

modules.{moduleId}.restartCount Number of times this module was restarted as part of the


restart policy.

EdgeHub desired properties


The module twin for the IoT Edge hub is called $edgeHub and coordinates the communications between the IoT
Edge hub running on a device and IoT Hub. The desired properties are set when applying a deployment manifest
on a specific device as part of a single-device or at-scale deployment.

PROPERTY DESCRIPTION REQUIRED IN THE DEPLOYMENT MANIFEST

schemaVersion Has to be "1.0" Yes

routes.{routeName} A string representing an IoT Edge hub The routes element can be present
route. For more information, see but empty.
Declare routes.
PROPERTY DESCRIPTION REQUIRED IN THE DEPLOYMENT MANIFEST

storeAndForwardConfiguration.timeToLi The time in seconds that IoT Edge hub Yes


veSecs keeps messages if disconnected from
routing endpoints, whether IoT Hub or
a local module. The value can be any
positive integer.

EdgeHub reported properties


PROPERTY DESCRIPTION

lastDesiredVersion This integer refers to the last version of the desired properties
processed by the IoT Edge hub.

lastDesiredStatus.code The status code referring to last desired properties seen by


the IoT Edge hub. Allowed values: 200 Success, 400 Invalid
configuration, 500 Failed

lastDesiredStatus.description Text description of the status.

clients.{device or moduleId}.status The connectivity status of this device or module. Possible


values {"connected" | "disconnected"}. Only module identities
can be in disconnected state. Downstream devices connecting
to IoT Edge hub appear only when connected.

clients.{device or moduleId}.lastConnectTime Last time the device or module connected.

clients.{device or moduleId}.lastDisconnectTime Last time the device or module disconnected.

Next steps
To learn how to use these properties to build out deployment manifests, see Understand how IoT Edge modules
can be used, configured, and reused.
Develop your own IoT Edge modules
11/24/2019 • 4 minutes to read • Edit Online

Azure IoT Edge modules can connect with other Azure services and contribute to your larger cloud data pipeline.
This article describes how you can develop modules to communicate with the IoT Edge runtime and IoT Hub,
and therefore the rest of the Azure cloud.

IoT Edge runtime environment


The IoT Edge runtime provides the infrastructure to integrate the functionality of multiple IoT Edge modules and
to deploy them onto IoT Edge devices. At a high level, any program can be packaged as an IoT Edge module.
However, to take full advantage of IoT Edge communication and management functionalities, a program
running in a module can connect to the local IoT Edge hub, integrated in the IoT Edge runtime.

Using the IoT Edge hub


The IoT Edge hub provides two main functionalities: proxy to IoT Hub, and local communications.
IoT Hub primitives
IoT Hub sees a module instance analogously to a device, in the sense that:
it has a module twin that is distinct and isolated from the device twin and the other module twins of that
device;
it can send device-to-cloud messages;
it can receive direct methods targeted specifically at its identity.
Currently, a module cannot receive cloud-to-device messages nor use the file upload feature.
When writing a module, you can use the Azure IoT Device SDK to connect to the IoT Edge hub and use the
above functionality as you would when using IoT Hub with a device application, the only difference being that,
from your application back-end, you have to refer to the module identity instead of the device identity.
Device -to -cloud messages
To enable complex processing of device-to-cloud messages, IoT Edge hub provides declarative routing of
messages between modules, and between modules and IoT Hub. Declarative routing allows modules to
intercept and process messages sent by other modules and propagate them into complex pipelines. For more
information, see deploy modules and establish routes in IoT Edge.
An IoT Edge module, as opposed to a normal IoT Hub device application, can receive device-to-cloud messages
that are being proxied by its local IoT Edge hub in order to process them.
IoT Edge hub propagates the messages to your module based on declarative routes described in the deployment
manifest. When developing an IoT Edge module, you can receive these messages by setting message handlers.
To simplify the creation of routes, IoT Edge adds the concept of module input and output endpoints. A module
can receive all device-to-cloud messages routed to it without specifying any input, and can send device-to-cloud
messages without specifying any output. Using explicit inputs and outputs, though, makes routing rules simpler
to understand.
Finally, device-to-cloud messages handled by the Edge hub are stamped with the following system properties:
PROPERTY DESCRIPTION

$connectionDeviceId The device ID of the client that sent the message

$connectionModuleId The module ID of the module that sent the message

$inputName The input that received this message. Can be empty.

$outputName The output used to send the message. Can be empty.

Connecting to IoT Edge hub from a module


Connecting to the local IoT Edge hub from a module involves two steps:
1. Create a ModuleClient instance in your application.
2. Make sure your application accepts the certificate presented by the IoT Edge hub on that device.
Create a ModuleClient instance to connect your module to the IoT Edge hub running on the device, similar to
how DeviceClient instances connect IoT devices to IoT Hub. For more information about the ModuleClient class
and its communication methods, see the API reference for your preferred SDK language: C#, C, Python, Java, or
Node.js.

Language and architecture support


IoT Edge supports multiple operating systems, device architectures, and development languages so that you can
build the scenario that matches your needs. Use this section to understand your options for developing custom
IoT Edge modules. You can learn more about tooling support and requirements for each language in Prepare
your development and test environment for IoT Edge.
Linux
For all languages in the following table, IoT Edge supports development for AMD64 and ARM32 Linux devices.

DEVELOPMENT LANGUAGE DEVELOPMENT TOOLS

C Visual Studio Code


Visual Studio 2017/2019

C# Visual Studio Code


Visual Studio 2017/2019

Java Visual Studio Code

Node.js Visual Studio Code

Python Visual Studio Code

NOTE
Develop and debugging support for ARM64 Linux devices is in public preview. For more information, see Develop and
debug ARM64 IoT Edge modules in Visual Studio Code (preview).

Windows
For all languages in the following table, IoT Edge supports development for AMD64 Windows devices.
DEVELOPMENT LANGUAGE DEVELOPMENT TOOLS

C Visual Studio 2017/2019

C# Visual Studio Code (no debugging capabilities)


Visual Studio 2017/2019

Next steps
Prepare your development and test environment for IoT Edge
Use Visual Studio to develop C# modules for IoT Edge
Use Visual Studio Code to develop modules for IoT Edge
Understand and use Azure IoT Hub SDKs
Prepare your development and test environment for
IoT Edge
7/12/2019 • 7 minutes to read • Edit Online

Azure IoT Edge moves your existing business logic to devices operating at the edge. To prepare your applications
and workloads to run as IoT Edge modules, you need to build them as containers. This article provides guidance
around how to configure your development environment so that you can successfully create an IoT Edge solution.
Once you have your development environment set up, then you can learn how to Develop your own IoT Edge
modules.
In any IoT Edge solution, there are at least two machines to consider. One is the IoT Edge device (or devices) itself,
which runs the IoT Edge module. The other is the development machine that you use to build, test, and deploy
modules. This article focuses primarily on the development machine. For testing purposes, the two machines can
be the same. You can run IoT Edge on your development machine and deploy modules to it.

Operating system
Azure IoT Edge runs on a specific set of supported operating systems. For developing for IoT Edge, you can use
most operating systems that can run a container engine. The container engine is a requirement on the
development machine to build your modules as containers and push them to a container registry.
If your development machine can't run Azure IoT Edge, continue in this article to learn about testing tools that
help you test and debug locally.
The operating system of your development machine doesn't have to match the operating system of your IoT Edge
device. However, the container operating system must be consistent between development machine and IoT Edge
device. For example, you can develop modules on a Windows machine and deploy them to a Linux device. The
Windows machine needs to run Linux containers to build the modules for the Linux device.

Container engine
The central concept of IoT Edge is that you can remotely deploy your business and cloud logic to devices by
packaging it into containers. To build containers, you need a container engine on your development machine.
The only supported container engine for IoT Edge devices in production is Moby. However, any container engine
compatible with the Open Container Initiative, like Docker, is capable of building IoT Edge module images.

Development tools
Both Visual Studio and Visual Studio Code have add-on extensions to help develop IoT Edge solutions. These
extensions provide language-specific templates to help create and deploy new IoT Edge scenarios. The Azure IoT
Edge extensions for Visual Studio and Visual Studio Code help you code, build, deploy, and debug your IoT Edge
solutions. You can create an entire IoT Edge solution that contains multiple modules, and the extensions
automatically update a deployment manifest template with each new module addition. With the extensions, you
can also manage your IoT devices from within Visual Studio or Visual Studio Code. Deploy modules to a device,
monitor the status, and view messages as they arrive at IoT Hub. Both extensions use the IoT EdgeHub dev tool to
enable local running and debugging of modules on your development machine as well.
If you prefer to develop with other editors or from the CLI, the Azure IoT Edge dev tool provides commands so
that you can develop and test from the command line. You can create new IoT Edge scenarios, build module
images, run modules in a simulator, and monitor messages sent to IoT Hub.
Visual Studio Code extension
The Azure IoT Edge extension for Visual Studio Code provides IoT Edge module templates built on programming
languages including C, C#, Java, Node.js, and Python as well as Azure functions in C#.
For more information and to download, see Azure IoT Tools for Visual Studio Code.
In addition to the IoT Edge extensions, you may find it helpful to install additional extensions for developing. For
example, you can use Docker Support for Visual Studio Code to manage your images, containers, and registries.
Additionally, all the major supported languages have extensions for Visual Studio Code that can help when you're
developing modules.
Prerequisites
The module templates for some languages and services have prerequisites that are necessary to build the project
folders on your development machine with Visual Studio Code.

MODULE TEMPLATE PREREQUISITE

Azure Functions .NET Core 2.1 SDK

C Git

C# .NET Core 2.1 SDK

Java Java SE Development Kit 10


Set the JAVA_HOME environment variable
Maven

Node.js Node.js
Yeoman
Azure IoT Edge Node.js module generator

Python Python
Pip
Git

Visual Studio 2017/2019 extension


The Azure IoT Edge tools for Visual Studio provide an IoT Edge module template built on C# and C.
For more information and to download, see Azure IoT Edge Tools for Visual Studio 2017 or Azure IoT Edge Tools
for Visual Studio 2019.
IoT Edge dev tool
The Azure IoT Edge dev tool simplifies IoT Edge development with command-line abilities. This tool provides CLI
commands to develop, debug, and test modules. The IoT Edge dev tool works with your development system,
whether you've manually installed the dependencies on your machine or are using the IoT Edge dev container.
For more information and to get started, see IoT Edge dev tool wiki.

Testing tools
Several testing tools exist to help you simulate IoT Edge devices or debug modules more efficiently. The following
table shows a high-level comparison between the tools, and then individual sections describe each tool more
specifically.
Only the IoT Edge runtime is supported for production deployments, but the following tools allow you to simulate
or easily create IoT Edge devices for development and testing purposes. These tools aren't mutually exclusive, but
can work together for a complete development experience.

TOOL ALSO KNOWN AS SUPPORTED PLATFORMS BEST FOR

IoT EdgeHub dev tool iotedgehubdev Windows, Linux, MacOS Simulating a device to debug
modules.

IoT Edge dev container microsoft/iotedgedev Windows, Linux, MacOS Developing without
installing dependencies.

IoT Edge runtime in a iotedgec Windows, Linux, MacOS, Testing on a device that may
container ARM not support the runtime.

IoT Edge device container toolboc/azure-iot-edge- Windows, Linux, MacOS, Testing a scenario with many
device-container ARM IoT Edge devices at scale.

IoT EdgeHub dev tool


The Azure IoT EdgeHub dev tool provides a local development and debug experience. The tool helps start IoT
Edge modules without the IoT Edge runtime so that you can create, develop, test, run, and debug IoT Edge
modules and solutions locally. You don't have to push images to a container registry and deploy them to a device
for testing.
The IoT EdgeHub dev tool was designed to work in tandem with the Visual Studio and Visual Studio Code
extensions, as well as with the IoT Edge dev tool. It supports inner loop development as well as outer loop testing,
so integrates with the DevOps tools too.
For more information and to install, see Azure IoT EdgeHub dev tool.
IoT Edge dev container
The Azure IoT Edge dev container is a Docker container that has all the dependencies that you need for IoT Edge
development. This container makes it easy to get started with whichever language you want to develop in,
including C#, Python, Node.js, and Java. All you need to install is a container engine, like Docker or Moby, to pull
the container to your development machine.
For more information, see Azure IoT Edge dev container.
IoT Edge runtime in a container
The IoT Edge runtime in a container provides a complete runtime that takes your device connection string as an
environment variable. This container enables you to test IoT Edge modules and scenarios on a system that may
not support the runtime natively, like MacOS. Any modules that you deploy will be started outside of the runtime
container. If you want the runtime and any deployed modules to exist within the same container, consider the IoT
Edge device container instead.
For more information, see Running Azure IoT Edge in a container.
IoT Edge device container
The IoT Edge device container is a complete IoT Edge device, ready to be launched on any machine with a
container engine. The device container includes the IoT Edge runtime and a container engine itself. Each instance
of the container is a fully functional self-provisioning IoT Edge device. The device container supports remote
debugging of modules, as long as there is a network route to the module. The device container is good for quickly
creating large numbers of IoT Edge devices to test at-scale scenarios or Azure Pipelines. It also supports
deployment to kubernetes via helm.
For more information, see Azure IoT Edge device container.

DevOps tools
When you're ready to develop at-scale solutions for extensive production scenarios, take advantage of modern
DevOps principles including automation, monitoring, and streamlined software engineering processes. IoT Edge
has extensions to support DevOps tools including Azure DevOps, Azure DevOps Projects, and Jenkins. If you
want to customize an existing pipeline or use a different DevOps tool like CircleCI or TravisCI, you can do so with
the CLI features included in the IoT Edge dev tool.
For more information, guidance, and examples, see the following pages:
Continuous integration and continuous deployment to Azure IoT Edge
Create a CI/CD pipeline for IoT Edge with Azure DevOps Projects
Azure IoT Edge Jenkins plugin
IoT Edge DevOps GitHub repo
Learn how to deploy modules and establish routes
in IoT Edge
12/1/2019 • 7 minutes to read • Edit Online

Each IoT Edge device runs at least two modules: $edgeAgent and $edgeHub, which are part of the IoT Edge
runtime. IoT Edge device can run multiple additional modules for any number of processes. Use a deployment
manifest to tell your device which modules to install and how to configure them to work together.
The deployment manifest is a JSON document that describes:
The IoT Edge agent module twin, which includes three components.
The container image for each module that runs on the device.
The credentials to access private container registries that contain module images.
Instructions for how each module should be created and managed.
The IoT Edge hub module twin, which includes how messages flow between modules and eventually to IoT
Hub.
Optionally, the desired properties of any additional module twins.
All IoT Edge devices must be configured with a deployment manifest. A newly installed IoT Edge runtime
reports an error code until configured with a valid manifest.
In the Azure IoT Edge tutorials, you build a deployment manifest by going through a wizard in the Azure IoT
Edge portal. You can also apply a deployment manifest programmatically using REST or the IoT Hub Service
SDK. For more information, see Understand IoT Edge deployments.

Create a deployment manifest


At a high level, a deployment manifest is a list of module twins that are configured with their desired properties.
A deployment manifest tells an IoT Edge device (or a group of devices) which modules to install and how to
configure them. Deployment manifests include the desired properties for each module twin. IoT Edge devices
report back the reported properties for each module.
Two modules are required in every deployment manifest: $edgeAgent , and $edgeHub . These modules are part of
the IoT Edge runtime that manages the IoT Edge device and the modules running on it. For more information
about these modules, see Understand the IoT Edge runtime and its architecture.
In addition to the two runtime modules, you can add up to 20 modules of your own to run on an IoT Edge
device.
A deployment manifest that contains only the IoT Edge runtime (edgeAgent and edgeHub) is valid.
Deployment manifests follow this structure:
{
"modulesContent": {
"$edgeAgent": { // required
"properties.desired": {
// desired properties of the Edge agent
// includes the image URIs of all modules
// includes container registry credentials
}
},
"$edgeHub": { //required
"properties.desired": {
// desired properties of the Edge hub
// includes the routing information between modules, and to IoT Hub
}
},
"module1": { // optional
"properties.desired": {
// desired properties of module1
}
},
"module2": { // optional
"properties.desired": {
// desired properties of module2
}
},
...
}
}

Configure modules
Define how the IoT Edge runtime installs the modules in your deployment. The IoT Edge agent is the runtime
component that manages installation, updates, and status reporting for an IoT Edge device. Therefore, the
$edgeAgent module twin requires the configuration and management information for all modules. This
information includes the configuration parameters for the IoT Edge agent itself.
For a complete list of properties that can or must be included, see Properties of the IoT Edge agent and IoT
Edge hub.
The $edgeAgent properties follow this structure:
"$edgeAgent": {
"properties.desired": {
"schemaVersion": "1.0",
"runtime": {
"settings":{
"registryCredentials":{ // give the edge agent access to container images that aren't public
}
}
}
},
"systemModules": {
"edgeAgent": {
// configuration and management details
},
"edgeHub": {
// configuration and management details
}
},
"modules": {
"module1": { // optional
// configuration and management details
},
"module2": { // optional
// configuration and management details
}
}
}
},

Declare routes
The IoT Edge hub manages communication between modules, IoT Hub, and any leaf devices. Therefore, the
$edgeHub module twin contains a desired property called routes that declares how messages are passed within
a deployment. You can have multiple routes within the same deployment.
Routes are declared in the $edgeHub desired properties with the following syntax:

"$edgeHub": {
"properties.desired": {
"routes": {
"route1": "FROM <source> WHERE <condition> INTO <sink>",
"route2": "FROM <source> WHERE <condition> INTO <sink>"
},
}
}

Every route needs a source and a sink, but the condition is an optional piece that you can use to filter messages.
Source
The source specifies where the messages come from. IoT Edge can route messages from modules or leaf
devices.
Using the IoT SDKs, modules can declare specific output queues for their messages using the ModuleClient
class. Output queues aren't necessary, but are helpful for managing multiple routes. Leaf devices can use the
DeviceClient class of the IoT SDKs to send messages to IoT Edge gateway devices in the same way that they
would send messages to IoT Hub. For more information, see Understand and use Azure IoT Hub SDKs.
The source property can be any of the following values:
SOURCE DESCRIPTION

/* All device-to-cloud messages or twin change notifications


from any module or leaf device

/twinChangeNotifications Any twin change (reported properties) coming from any


module or leaf device

/messages/* Any device-to-cloud message sent by a module through


some or no output, or by a leaf device

/messages/modules/* Any device-to-cloud message sent by a module through


some or no output

/messages/modules/<moduleId>/* Any device-to-cloud message sent by a specific module


through some or no output

/messages/modules/<moduleId>/outputs/* Any device-to-cloud message sent by a specific module


through some output

/messages/modules/<moduleId>/outputs/<output> Any device-to-cloud message sent by a specific module


through a specific output

Condition
The condition is optional in a route declaration. If you want to pass all messages from the source to the sink, just
leave out the WHERE clause entirely. Or you can use the IoT Hub query language to filter for certain messages
or message types that satisfy the condition. IoT Edge routes don't support filtering messages based on twin tags
or properties.
The messages that pass between modules in IoT Edge are formatted the same as the messages that pass
between your devices and Azure IoT Hub. All messages are formatted as JSON and have systemProperties,
appProperties, and body parameters.
You can build queries around any of the three parameters with the following syntax:
System properties: $<propertyName> or {$<propertyName>}
Application properties: <propertyName>
Body properties: $body.<propertyName>

For examples about how to create queries for message properties, see Device-to-cloud message routes query
expressions.
An example that is specific to IoT Edge is when you want to filter for messages that arrived at a gateway device
from a leaf device. Messages that come from modules include a system property called connectionModuleId.
So if you want to route messages from leaf devices directly to IoT Hub, use the following route to exclude
module messages:

FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO $upstream

Sink
The sink defines where the messages are sent. Only modules and IoT Hub can receive messages. Messages can't
be routed to other devices. There are no wildcard options in the sink property.
The sink property can be any of the following values:
SINK DESCRIPTION

$upstream Send the message to IoT Hub

BrokeredEndpoint("/modules/<moduleId>/inputs/<input>") Send the message to a specific input of a specific module

IoT Edge provides at-least-once guarantees. The IoT Edge hub stores messages locally in case a route can't
deliver the message to its sink. For example, if the IoT Edge hub can't connect to IoT Hub, or the target module
isn't connected.
IoT Edge hub stores the messages up to the time specified in the storeAndForwardConfiguration.timeToLiveSecs
property of the IoT Edge hub desired properties.

Define or update desired properties


The deployment manifest specifies desired properties for each module deployed to the IoT Edge device. Desired
properties in the deployment manifest overwrite any desired properties currently in the module twin.
If you do not specify a module twin's desired properties in the deployment manifest, IoT Hub won't modify the
module twin in any way. Instead, you can set the desired properties programmatically.
The same mechanisms that allow you to modify device twins are used to modify module twins. For more
information, see the module twin developer guide.

Deployment manifest example


The following example shows what a valid deployment manifest document may look like.

{
"modulesContent": {
"$edgeAgent": {
"properties.desired": {
"schemaVersion": "1.0",
"runtime": {
"type": "docker",
"settings": {
"minDockerVersion": "v1.25",
"loggingOptions": "",
"registryCredentials": {
"ContosoRegistry": {
"username": "myacr",
"password": "<password>",
"address": "myacr.azurecr.io"
}
}
}
},
"systemModules": {
"edgeAgent": {
"type": "docker",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-agent:1.0",
"createOptions": ""
}
},
"edgeHub": {
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-hub:1.0",
"createOptions": ""
"createOptions": ""
}
}
},
"modules": {
"SimulatedTemperatureSensor": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0",
"createOptions": "{}"
}
},
"filtermodule": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "myacr.azurecr.io/filtermodule:latest",
"createOptions": "{}"
}
}
}
}
},
"$edgeHub": {
"properties.desired": {
"schemaVersion": "1.0",
"routes": {
"sensorToFilter": "FROM /messages/modules/SimulatedTemperatureSensor/outputs/temperatureOutput
INTO BrokeredEndpoint(\"/modules/filtermodule/inputs/input1\")",
"filterToIoTHub": "FROM /messages/modules/filtermodule/outputs/output1 INTO $upstream"
},
"storeAndForwardConfiguration": {
"timeToLiveSecs": 10
}
}
}
}
}

Next steps
For a complete list of properties that can or must be included in $edgeAgent and $edgeHub, see
Properties of the IoT Edge agent and IoT Edge hub.
Now that you know how IoT Edge modules are used, Understand the requirements and tools for
developing IoT Edge modules.
Understand IoT Edge automatic deployments for
single devices or at scale
11/24/2019 • 7 minutes to read • Edit Online

Azure IoT Edge devices follow a device lifecycle that is similar to other types of IoT devices:
1. Provision new IoT Edge devices by imaging a device with an OS and installing the IoT Edge runtime.
2. Configure the devices to run IoT Edge modules, and then monitor their health.
3. Finally, retire devices when they are replaced or become obsolete.
Azure IoT Edge provides two ways to configure the modules to run on IoT Edge devices: one for development
and fast iterations on a single device (you used this method in the Azure IoT Edge tutorials), and one for
managing large fleets of IoT Edge devices. Both of these approaches are available in the Azure portal and
programmatically. For targeting groups or a large number of devices, you can specify which devices you'd like to
deploy your modules to using tags in the device twin. The following steps talk about a deployment to a
Washington State device group identified through the tags property.
This article focuses on the configuration and monitoring stages for fleets of devices, collectively referred to as IoT
Edge automatic deployments. The overall deployment steps are as follows:
1. An operator defines a deployment that describes a set of modules as well as the target devices. Each
deployment has a deployment manifest that reflects this information.
2. The IoT Hub service communicates with all targeted devices to configure them with the desired modules.
3. The IoT Hub service retrieves status from the IoT Edge devices and makes them available to the operator. For
example, an operator can see when an Edge device is not configured successfully or if a module fails during
runtime.
4. At any time, new IoT Edge devices that meet the targeting conditions are configured for the deployment. For
example, a deployment that targets all IoT Edge devices in Washington State automatically configures a new
IoT Edge device once it is provisioned and added to the Washington State device group.
This article describes each component involved in configuring and monitoring a deployment. For a walkthrough
of creating and updating a deployment, see Deploy and monitor IoT Edge modules at scale.

Deployment
An IoT Edge automatic deployment assigns IoT Edge module images to run as instances on a targeted set of IoT
Edge devices. It works by configuring an IoT Edge deployment manifest to include a list of modules with the
corresponding initialization parameters. A deployment can be assigned to a single device (based on Device ID ) or
to a group of devices (based on tags). Once an IoT Edge device receives a deployment manifest, it downloads and
installs the container images from the respective container repositories, and configures them accordingly. Once a
deployment is created, an operator can monitor the deployment status to see whether targeted devices are
correctly configured.
Only IoT Edge devices can be configured with a deployment. The following prerequisites must be on the device
before it can receive the deployment:
The base operating system
A container management system, like Moby or Docker
Provisioning of the IoT Edge runtime
Deployment manifest
A deployment manifest is a JSON document that describes the modules to be configured on the targeted IoT
Edge devices. It contains the configuration metadata for all the modules, including the required system modules
(specifically the IoT Edge agent and IoT Edge hub).
The configuration metadata for each module includes:
Version
Type
Status (for example, running or stopped)
Restart policy
Image and container registry
Routes for data input and output
If the module image is stored in a private container registry, the IoT Edge agent holds the registry credentials.
Target condition
The target condition is continuously evaluated throughout the lifetime of the deployment. Any new devices that
meet the requirements are included, and any existing devices that no longer do are removed. The deployment is
reactivated if the service detects any target condition change.
For instance, you have a deployment A with a target condition tags.environment = 'prod'. When you kick off the
deployment, there are 10 production devices. The modules are successfully installed in these 10 devices. The IoT
Edge Agent Status is shown as 10 total devices, 10 successful responses, 0 failure responses, and 0 pending
responses. Now you add five more devices with tags.environment = 'prod'. The service detects the change and
the IoT Edge Agent Status becomes 15 total devices, 10 successful responses, 0 failure responses, and 5 pending
responses when it tries to deploy to the five new devices.
Use any Boolean condition on device twins tags or deviceId to select the target devices. If you want to use
condition with tags, you need to add "tags":{} section in the device twin under the same level as properties. Learn
more about tags in device twin
Target condition examples:
deviceId ='linuxprod1'
tags.environment ='prod'
tags.environment = 'prod' AND tags.location = 'westus'
tags.environment = 'prod' OR tags.location = 'westus'
tags.operator = 'John' AND tags.environment = 'prod' NOT deviceId = 'linuxprod1'
Here are some constrains when you construct a target condition:
In device twin, you can only build a target condition using tags or deviceId.
Double quotes aren't allowed in any portion of the target condition. Use single quotes.
Single quotes represent the values of the target condition. Therefore, you must escape the single quote with
another single quote if it's part of the device name. For example, to target a device called operator'sDevice ,
write deviceId='operator''sDevice' .
Numbers, letters, and the following characters are allowed in target condition values: -:.+%_#*?!(),=@;$ .
Priority
A priority defines whether a deployment should be applied to a targeted device relative to other deployments. A
deployment priority is a positive integer, with larger numbers denoting higher priority. If an IoT Edge device is
targeted by more than one deployment, the deployment with the highest priority applies. Deployments with
lower priorities are not applied, nor are they merged. If a device is targeted with two or more deployments with
equal priority, the most recently created deployment (determined by the creation timestamp) applies.
Labels
Labels are string key/value pairs that you can use to filter and group of deployments. A deployment may have
multiple labels. Labels are optional and do no impact the actual configuration of IoT Edge devices.
Deployment status
A deployment can be monitored to determine whether it applied successfully for any targeted IoT Edge device. A
targeted Edge device will appear in one or more of the following status categories:
Target shows the IoT Edge devices that match the Deployment targeting condition.
Actual shows the targeted IoT Edge devices that are not targeted by another deployment of higher priority.
Healthy shows the IoT Edge devices that have reported back to the service that the modules have been
deployed successfully.
Unhealthy shows the IoT Edge devices have reported back to the service that one or modules have not been
deployed successfully. To further investigate the error, connect remotely to those devices and view the log files.
Unknown shows the IoT Edge devices that did not report any status pertaining this deployment. To further
investigate, view service info and log files.

Phased rollout
A phased rollout is an overall process whereby an operator deploys changes to a broadening set of IoT Edge
devices. The goal is to make changes gradually to reduce the risk of making wide scale breaking changes.
A phased rollout is executed in the following phases and steps:
1. Establish a test environment of IoT Edge devices by provisioning them and setting a device twin tag like
tag.environment='test' . The test environment should mirror the production environment that the deployment
will eventually target.
2. Create a deployment including the desired modules and configurations. The targeting condition should target
the test IoT Edge device environment.
3. Validate the new module configuration in the test environment.
4. Update the deployment to include a subset of production IoT Edge devices by adding a new tag to the
targeting condition. Also, ensure that the priority for the deployment is higher than other deployments
currently targeted to those devices
5. Verify that the deployment succeeded on the targeted IoT Devices by viewing the deployment status.
6. Update the deployment to target all remaining production IoT Edge devices.

Rollback
Deployments can be rolled back if you receive errors or misconfigurations. Because a deployment defines the
absolute module configuration for an IoT Edge device, an additional deployment must also be targeted to the
same device at a lower priority even if the goal is to remove all modules.
Perform rollbacks in the following sequence:
1. Confirm that a second deployment is also targeted at the same device set. If the goal of the rollback is to
remove all modules, the second deployment should not include any modules.
2. Modify or remove the target condition expression of the deployment you wish to roll back so that the devices
no longer meet the targeting condition.
3. Verify that the rollback succeeded by viewing the deployment status.
The rolled-back deployment should no longer show status for the devices that were rolled back.
The second deployment should now include deployment status for the devices that were rolled back.
Next steps
Walk through the steps to create, update, or delete a deployment in Deploy and monitor IoT Edge modules at
scale.
Learn more about other IoT Edge concepts like the IoT Edge runtime and IoT Edge modules.
Understand extended offline capabilities for IoT Edge
devices, modules, and child devices
12/8/2019 • 6 minutes to read • Edit Online

Azure IoT Edge supports extended offline operations on your IoT Edge devices, and enables offline operations on
non-IoT Edge child devices too. As long as an IoT Edge device has had one opportunity to connect to IoT Hub,
that device and any child devices can continue to function with intermittent or no internet connection.

How it works
When an IoT Edge device goes into offline mode, the IoT Edge hub takes on three roles. First, it stores any
messages that would go upstream and saves them until the device reconnects. Second, it acts on behalf of IoT
Hub to authenticate modules and child devices so that they can continue to operate. Third, it enables
communication between child devices that normally would go through IoT Hub.
The following example shows how an IoT Edge scenario operates in offline mode:
1. Configure devices
IoT Edge devices automatically have offline capabilities enabled. To extend that capability to other IoT
devices, you need to declare a parent-child relationship between the devices in IoT Hub. Then, you
configure the child devices to trust their assigned parent device and route the device-to-cloud
communications through the parent as a gateway.
2. Sync with IoT Hub
At least once after installation of the IoT Edge runtime, the IoT Edge device needs to be online to sync with
IoT Hub. In this sync, the IoT Edge device gets details about any child devices assigned to it. The IoT Edge
device also securely updates its local cache to enable offline operations and retrieves settings for local
storage of telemetry messages.
3. Go offline
While disconnected from IoT Hub, the IoT Edge device, its deployed modules, and any children IoT devices
can operate indefinitely. Modules and child devices can start and restart by authenticating with the IoT
Edge hub while offline. Telemetry bound upstream to IoT Hub is stored locally. Communication between
modules or between child IoT devices is maintained through direct methods or messages.
4. Reconnect and resync with IoT Hub
Once the connection with IoT Hub is restored, the IoT Edge device syncs again. Locally stored messages are
delivered to the IoT Hub right away, but are dependant on the speed of the connection, IoT Hub latency,
and related factors. They are delivered in the same order in which they were stored.
Any differences between the desired and reported properties of the modules and devices are reconciled.
The IoT Edge device updates any changes to its set of assigned child IoT devices.

Restrictions and limits


The extended offline capabilities described in this article are available in IoT Edge version 1.0.7 or higher. Earlier
versions have a subset of offline features. Existing IoT Edge devices that don't have extended offline capabilities
can't be upgraded by changing the runtime version, but must be reconfigured with a new IoT Edge device identity
to gain these features.
Extended offline support is available in all regions where IoT Hub is available, except East US.
Only non-IoT Edge devices can be added as child devices.
IoT Edge devices and their assigned child devices can function indefinitely offline after the initial, one-time sync.
However, storage of messages depends on the time to live (TTL ) setting and the available disk space for storing
the messages.

Set up parent and child devices


For an IoT Edge device to extend its extended offline capabilities to child IoT devices, you need to complete two
steps. First, declare the parent-child relationships in the Azure portal. Second, create a trust relationship between
the parent device and any child devices, then configure device-to-cloud communications to go through the parent
as a gateway.
Assign child devices
Child devices can be any non-IoT Edge device registered to the same IoT Hub. Parent devices can have multiple
child devices, but a child device only has one parent. There are three options to set child devices to an edge device:
through the Azure portal, using the Azure CLI, or using the IoT Hub service SDK.
The following sections provide examples of how you can declare the parent/child relationship in IoT Hub for
existing IoT devices. If you're creating new device identities for your child devices, see Authenticate a downstream
device to Azure IoT Hub for more information.
Option 1: IoT Hub Portal
You can declare the parent-child relationship when creating a new device. Or for existing devices, you can declare
the relationship from the device details page of either the parent IoT Edge device or the child IoT device.

Option 2: Use the az command-line tool


Using the Azure command-line interface with IoT extension (v0.7.0 or newer), you can manage parent child
relationships with the device-identity subcommands. The example below uses a query to assign all non-IoT Edge
devices in the hub to be child devices of an IoT Edge device.
# Set IoT Edge parent device
egde_device="edge-device1"

# Get All IoT Devices


device_list=$(az iot hub query \
--hub-name replace-with-hub-name \
--subscription replace-with-sub-name \
--resource-group replace-with-rg-name \
-q "SELECT * FROM devices WHERE capabilities.iotEdge = false" \
--query 'join(`, `, [].deviceId)' -o tsv)

# Add all IoT devices to IoT Edge (as child)


az iot hub device-identity add-children \
--device-id $egde_device \
--child-list $device_list \
--hub-name replace-with-hub-name \
--resource-group replace-with-rg-name \
--subscription replace-with-sub-name

You can modify the query to select a different subset of devices. The command may take several seconds if you
specify a large set of devices.
Option 3: Use IoT Hub Service SDK
Finally, you can manage parent child relationships programmatically using either C#, Java or Node.js IoT Hub
Service SDK. Here is an example of assigning a child device using the C# SDK.
Set up the parent device as a gateway
You can think of a parent/child relationship as a transparent gateway, where the child device has its own identity in
IoT Hub but communicates through the cloud via its parent. For secure communication, the child device needs to
be able to verify that the parent device comes from a trusted source. Otherwise, third-parties could set up
malicious devices to impersonate parents and intercept communications.
One way to create this trust relationship is described in detail in the following articles:
Configure an IoT Edge device to act as a transparent gateway
Connect a downstream (child) device to an Azure IoT Edge gateway

Specify DNS servers


To improve robustness, it is highly recommended you specify the DNS server addresses used in your
environment. To set your DNS server for IoT Edge, see the resolution for Edge Agent module continually reports
'empty config file' and no modules start on device in the troubleshooting article.

Optional offline settings


If your devices go offline, the IoT Edge parent device stores all device-to-cloud messages until the connection is
reestablished. The IoT Edge hub module manages the storage and forwarding of offline messages. For devices
that may go offline for extended periods of time, optimize performance by configuring two IoT Edge hub settings.
First, increase the time to live setting so that the IoT Edge hub will keep messages long enough for your device to
reconnect. Then, add additional disk space for message storage.
Time to live
The time to live setting is the amount of time (in seconds) that a message can wait to be delivered before it expires.
The default is 7200 seconds (two hours). The maximum value is only limited by the maximum value of an integer
variable, which is around 2 billion.
This setting is a desired property of the IoT Edge hub, which is stored in the module twin. You can configure it in
the Azure portal or directly in the deployment manifest.

"$edgeHub": {
"properties.desired": {
"schemaVersion": "1.0",
"routes": {},
"storeAndForwardConfiguration": {
"timeToLiveSecs": 7200
}
}
}

Host storage for system modules


Messages and module state information are stored in the IoT Edge hub's local container filesystem by default. For
improved reliability, especially when operating offline, you can also dedicate storage on the host IoT Edge device.
For more information, see Give modules access to a device's local storage

Next steps
Learn more about how to set up a transparent gateway for your parent/child device connections:
Configure an IoT Edge device to act as a transparent gateway
Authenticate a downstream device to Azure IoT Hub
Connect a downstream device to an Azure IoT Edge gateway
How an IoT Edge device can be used as a gateway
11/24/2019 • 4 minutes to read • Edit Online

Gateways in IoT Edge solutions provide device connectivity and edge analytics to IoT devices that otherwise
wouldn't have those capabilities. Azure IoT Edge can be used to satisfy all needs for an IoT gateway regardless of
whether they are related to connectivity, identity, or edge analytics. Gateway patterns in this article only refer to
characteristics of downstream device connectivity and device identity, not how device data is processed on the
gateway.

Patterns
There are three patterns for using an IoT Edge device as a gateway: transparent, protocol translation, and identity
translation:
Transparent – Devices that theoretically could connect to IoT Hub can connect to a gateway device instead. The
downstream devices have their own IoT Hub identities and are using any of the MQTT, AMQP, or HTTP
protocols. The gateway simply passes communications between the devices and IoT Hub. The devices are
unaware that they are communicating with the cloud via a gateway, and a user interacting with the devices in
IoT Hub is unaware of the intermediate gateway device. Thus, the gateway is transparent. Refer to Create a
transparent gateway for specifics on using an IoT Edge device as a transparent gateway.
Protocol translation – Also known as an opaque gateway pattern, devices that do not support MQTT, AMQP,
or HTTP can use a gateway device to send data to IoT Hub on their behalf. The gateway understands the
protocol used by the downstream devices, and is the only device that has an identity in IoT Hub. All information
looks like it is coming from one device, the gateway. Downstream devices must embed additional identifying
information in their messages if cloud applications want to analyze the data on a per-device basis. Additionally,
IoT Hub primitives like twins and methods are only available for the gateway device, not downstream devices.
Identity translation - Devices that cannot connect to IoT Hub can connect to a gateway device, instead. The
gateway provides IoT Hub identity and protocol translation on behalf of the downstream devices. The gateway
is smart enough to understand the protocol used by the downstream devices, provide them identity, and
translate IoT Hub primitives. Downstream devices appear in IoT Hub as first-class devices with twins and
methods. A user can interact with the devices in IoT Hub and is unaware of the intermediate gateway device.
Use cases
All gateway patterns provide the following benefits:
Analytics at the edge – Use AI services locally to process data coming from downstream devices without
sending full-fidelity telemetry to the cloud. Find and react to insights locally and only send a subset of data to
IoT Hub.
Downstream device isolation – The gateway device can shield all downstream devices from exposure to the
internet. It can sit in between an OT network that does not have connectivity and an IT network that provides
access to the web.
Connection multiplexing - All devices connecting to IoT Hub through an IoT Edge gateway use the same
underlying connection.
Traffic smoothing - The IoT Edge device will automatically implement exponential backoff if IoT Hub throttles
traffic, while persisting the messages locally. This benefit makes your solution resilient to spikes in traffic.
Offline support - The gateway device stores messages and twin updates that cannot be delivered to IoT Hub.
A gateway that does protocol translation can also perform edge analytics, device isolation, traffic smoothing, and
offline support to existing devices and new devices that are resource constrained. Many existing devices are
producing data that can power business insights; however they were not designed with cloud connectivity in mind.
Opaque gateways allow this data to be unlocked and used in an IoT solution.
A gateway that does identity translation provides the benefits of protocol translation and additionally allows for
full manageability of downstream devices from the cloud. All devices in your IoT solution show up in IoT Hub
regardless of the protocol they use.

Cheat sheet
Here is a quick cheat sheet that compares IoT Hub primitives when using transparent, opaque (protocol), and
proxy gateways.

TRANSPARENT GATEWAY PROTOCOL TRANSLATION IDENTITY TRANSLATION

Identities stored in the IoT Identities of all connected Only the identity of the Identities of all connected
Hub identity registry devices gateway device devices

Device twin Each connected device has Only the gateway has a Each connected device has
its own device twin device and module twins its own device twin

Direct methods and cloud- The cloud can address each The cloud can only address The cloud can address each
to-device messages connected device individually the gateway device connected device individually

IoT Hub throttles and Apply to each device Apply to the gateway device Apply to each device
quotas

When using an opaque gateway (protocol translation) pattern, all devices connecting through that gateway share
the same cloud-to-device queue, which can contain at most 50 messages. It follows that the opaque gateway
pattern should be used only when few devices are connecting through each field gateway, and their cloud-to-
device traffic is low.

Next steps
Learn how to set up a transparent gateway:
Configure an IoT Edge device to act as a transparent gateway
Authenticate a downstream device to Azure IoT Hub
Connect a downstream device to an Azure IoT Edge gateway
Security standards for Azure IoT Edge
11/24/2019 • 5 minutes to read • Edit Online

Azure IoT Edge addresses the risks that are inherent when moving your data and analytics to the intelligent edge.
The IoT Edge security standards balance flexibility for different deployment scenarios with the protection that you
expect from all Azure services.
IoT Edge runs on various makes and models of hardware, supports several operating systems, and applies to
diverse deployment scenarios. The risk of a deployment scenario depends on factors that include solution
ownership, deployment geography, data sensitivity, privacy, application vertical, and regulatory
requirements. Rather than offering concrete solutions for specific scenarios, IoT Edge is an extensible security
framework based on well-grounded principles that are designed for scale. This article provides an overview of
the IoT Edge security framework. For more information, see Securing the intelligent edge.

Standards
Standards promote ease of scrutiny and ease of implementation, both of which are hallmarks of security. A security
solution should lend itself to scrutiny under evaluation to build trust and shouldn't be a hurdle to deployment. The
design of the framework to secure Azure IoT Edge is based on time-tested and industry proven security protocols
for familiarity and reuse.

Authentication
When you deploy an IoT solution, you need to know that only trusted actors, devices, and modules have access to
your solution. Certificate-based authentication is the primary mechanism for authentication for the Azure IoT Edge
platform. This mechanism is derived from a set of standards governing Public Key Infrastructure (PKiX) by the
Internet Engineering Task Force (IETF ).
All devices, modules, and actors interacting with the Azure IoT Edge device, whether physically or through a
network connection, should have unique certificate identities. Not every scenario or component may lend itself to
certificate-based authentication, so the extensibility of the security framework offers secure alternatives.
For more information, see Azure IoT Edge certificate usage.

Authorization
The principle of least privilege says that users and components of a system should have access only to the
minimum set of resources and data needed to perform their roles. Devices, modules, and actors should access only
the resources and data within their permission scope, and only when it is architecturally allowable. Some
permissions are configurable with sufficient privileges and others are architecturally enforced. For example, some
modules may be authorized to connect to Azure IoT Hub. However, there is no reason why a module in one IoT
Edge device should access the twin of a module in another IoT Edge device.
Other authorization schemes include certificate signing rights and role-based access control (RBAC ).

Attestation
Attestation ensures the integrity of software bits, which is important for detecting and preventing malware. The
Azure IoT Edge security framework classifies attestation under three main categories:
Static attestation
Runtime attestation
Software attestation
Static attestation
Static attestation verifies the integrity of all software on a device during power-up, including the operating system,
all runtimes, and configuration information. Because static attestation occurs during power-up, it's often referred to
as secure boot. The security framework for IoT Edge devices extends to manufacturers and incorporates secure
hardware capabilities that assure static attestation processes. These processes include secure boot and secure
firmware upgrade. Working in close collaboration with silicon vendors eliminates superfluous firmware layers, so
minimizes the threat surface.
Runtime attestation
Once a system has completed a secure boot process, well-designed systems should detect attempts to inject
malware and take proper countermeasures. Malware attacks may target the system's ports and interfaces. If
malicious actors have physical access to a device, they may tamper with the device itself or use side-channel attacks
to gain access. Such malcontent, whether malware or unauthorized configuration changes, can't be detected by
static attestation because it is injected after the boot process. Countermeasures offered or enforced by the device’s
hardware help to ward off such threats. The security framework for IoT Edge explicitly calls for extensions that
combat runtime threats.
Software attestation
All healthy systems, including intelligent edge systems, need patches and upgrades. Security is important for
update processes, otherwise they can be potential threat vectors. The security framework for IoT Edge calls for
updates through measured and signed packages to assure the integrity of and authenticate the source of the
packages. This standard applies to all operating systems and application software bits.

Hardware root of trust


For many intelligent edge devices, especially devices that can be physically accessed by potential malicious actors,
hardware security is the last defense for protection. Tamper resistant hardware is crucial for such
deployments. Azure IoT Edge encourages secure silicon hardware vendors to offer different flavors of hardware
root of trust to accommodate various risk profiles and deployment scenarios. Hardware trust may come from
common security protocol standards like Trusted Platform Module (ISO/IEC 11889) and Trusted Computing
Group’s Device Identifier Composition Engine (DICE ). Secure enclave technologies like TrustZones and Software
Guard Extensions (SGX) also provide hardware trust.

Certification
To help customers make informed decisions when procuring Azure IoT Edge devices for their deployment, the IoT
Edge framework includes certification requirements. Foundational to these requirements are certifications
pertaining to security claims and certifications pertaining to validation of the security implementation. For
example, a security claim certification means that the IoT Edge device uses secure hardware known to resist boot
attacks. A validation certification means that the secure hardware was properly implemented to offer this value in
the device. In keeping with the principle of simplicity, the framework tries to keep the burden of certification
minimal.

Extensibility
With IoT technology driving different types of business transformations, security should evolve in parallel to
address emerging scenarios. The Azure IoT Edge security framework starts with a solid foundation on which it
builds in extensibility into different dimensions to include:
First party security services like the Device Provisioning Service for Azure IoT Hub.
Third-party services like managed security services for different application verticals (like industrial or
healthcare) or technology focus (like security monitoring in mesh networks, or silicon hardware attestation
services) through a rich network of partners.
Legacy systems to include retrofitting with alternate security strategies, like using secure technology other than
certificates for authentication and identity management.
Secure hardware for adoption of emerging secure hardware technologies and silicon partner contributions.
In the end, securing the intelligent edge requires collaborative contributions from an open community driven by
the common interest in securing IoT. These contributions might be in the form of secure technologies or services.
The Azure IoT Edge security framework offers a solid foundation for security that is extensible for the maximum
coverage to offer the same level of trust and integrity in the intelligent edge as with Azure cloud.

Next steps
Read more about how Azure IoT Edge is Securing the intelligent edge.
Azure IoT Edge security manager
12/1/2019 • 7 minutes to read • Edit Online

The Azure IoT Edge security manager is a well-bounded security core for protecting the IoT Edge device and all its
components by abstracting the secure silicon hardware. It is the focal point for security hardening and provides
technology integration point to original equipment manufacturers (OEM ).

IoT Edge security manager aims to defend the integrity of the IoT Edge device and all inherent software
operations. The security manager transitions trust from underlying hardware root of trust hardware (if available)
to bootstrap the IoT Edge runtime and monitor ongoing operations. The IoT Edge security manager is software
working along with secure silicon hardware (where available) to help deliver the highest security assurances
possible.
The responsibilities of the IoT Edge security manager include, but aren't limited to:
Secured and measured bootstrapping of the Azure IoT Edge device.
Device identity provisioning and transition of trust where applicable.
Host and protect device components of cloud services like Device Provisioning Service.
Securely provision IoT Edge modules with unique identities.
Gatekeeper to device hardware root of trust through notary services.
Monitor the integrity of IoT Edge operations at runtime.
IoT Edge security manager includes three components:
IoT Edge security daemon.
Hardware security module platform abstraction Layer (HSM PAL ).
Optional but highly recommended hardware silicon root of trust or HSM.

The IoT Edge security daemon


The IoT Edge security daemon is responsible for the logical operations of IoT Edge security manager. It represents
a significant portion of the trusted computing base of the IoT Edge device.
Design principles
The IoT Edge security daemon follows two core principles: maximize operational integrity, and minimize bloat and
churn.
Maximize operational integrity
The IoT Edge security daemon operates with the highest integrity possible within the defense capability of any
given root of trust hardware. With proper integration, the root of trust hardware measures and monitors the
security daemon statically and at runtime to resist tampering.
Physical access is always a threat to IoT devices. Hardware root of trust plays an important role in defending the
integrity of the IoT Edge security daemon. Hardware root of trust come in two varieties:
secure elements for the protection of sensitive information like secrets and cryptographic keys.
secure enclaves for the protection of secrets like keys, and sensitive workloads like metering and billing.
Two kinds of execution environments exist to use hardware root of trust:
The standard or rich execution environment (REE ) that relies on the use of secure elements to protect sensitive
information.
The trusted execution environment (TEE ) that relies on the use of secure enclave technology to protect
sensitive information and offer protection to software execution.
For devices using secure enclaves as hardware root of trust, sensitive logic within IoT Edge security daemon
should be inside the enclave. Non-sensitive portions of the security daemon can be outside of the TEE. In any case,
original design manufacturers (ODM ) and original equipment manufacturers (OEM ) should extend trust from
their HSM to measure and defend the integrity of the IoT Edge security daemon at boot and runtime.
Minimize bloat and churn
Another core principle for the IoT Edge security daemon is to minimize churn. For the highest level of trust, the
IoT Edge security daemon can tightly couple with the device hardware root of trust and operate as native code. It's
common for these types of realizations to update the daemon software through the hardware root of trust's
secure update paths (as opposed to OS provided update mechanisms), which can be challenging in some
scenarios. While security renewal is recommended for IoT devices, excessive update requirements or large update
payloads can expand the threat surface in many ways. Examples include skipping of updates to maximize
operational availability or root of trust hardware too constrained to process large update payloads. As such, the
design of IoT Edge security daemon is concise to keep the footprint and trusted computing base small and to
minimize update requirements.
Architecture of IoT Edge security daemon
The IoT Edge security daemon takes advantage of any available hardware root of trust technology for security
hardening. It also allows for split-world operation between a standard/rich execution environment (REE ) and a
trusted execution environment (TEE ) when hardware technologies offer trusted execution environments. Role-
specific interfaces enable the major components of IoT Edge to assure the integrity of the IoT Edge device and its
operations.
Cloud interface
The cloud interface allows the IoT Edge security daemon to access cloud services such as cloud compliments to
device security like security renewal. For example, the IoT Edge security daemon currently uses this interface to
access the Azure IoT Hub Device Provisioning Service for device identity lifecycle management.
Management API
IoT Edge security daemon offers a management API, which is called by the IoT Edge agent when
creating/starting/stopping/removing an IoT Edge module. The security daemon stores “registrations” for all active
modules. These registrations map a module’s identity to some properties of the module. A few examples for these
properties are the process identifier (pid) of the process running in the container or the hash of the docker
container’s contents.
These properties are used by the workload API (described below ) to verify that the caller is authorized to perform
an action.
The management API is a privileged API, callable only from the IoT Edge agent. Since the IoT Edge security
daemon bootstraps and starts the IoT Edge agent, it can create an implicit registration for the IoT Edge agent, after
it has attested that the IoT Edge agent has not been tampered with. The same attestation process that the
workload API uses also restricts access to the management API to only the IoT Edge agent.
Container API
The container API interacts with the container system in use for module management, like Moby or Docker.
Workload API
The workload API is accessible to all modules. It provides proof of identity, either as an HSM rooted signed token
or an X509 certificate, and the corresponding trust bundle to a module. The trust bundle contains CA certificates
for all the other servers that the modules should trust.
The IoT Edge security daemon uses an attestation process to guard this API. When a module calls this API, the
security daemon attempts to find a registration for the identity. If successful, it uses the properties of the
registration to measure the module. If the result of the measurement process matches the registration, a new
proof of identity is generated. The corresponding CA certificates (trust bundle) are returned to the module. The
module uses this certificate to connect to IoT Hub, other modules, or start a server. When the signed token or
certificate nears expiration, it's the responsibility of the module to request a new certificate.
Integration and maintenance
Microsoft maintains the main code base for the IoT Edge security daemon on GitHub.
Installation and updates
Installation and updates of the IoT Edge security daemon are managed through the operating system's package
management system. IoT Edge devices with hardware root of trust should provide additional hardening to the
integrity of the daemon by managing its lifecycle through the secure boot and updates management systems.
Device makers should explore these avenues based on their respective device capabilities.
Versioning
The IoT Edge runtime tracks and reports the version of the IoT Edge security daemon. The version is reported as
the runtime.platform.version attribute of the IoT Edge agent module reported property.
Hardware security module platform abstraction layer (HSM PAL )
The HSM PAL abstracts all root of trust hardware to isolate the developer or user of IoT Edge from their
complexities. It includes a combination of application programming interface (API) and trans-domain
communication procedures, for example communication between a standard execution environment and a secure
enclave. The actual implementation of the HSM PAL depends on the specific secure hardware in use. Its existence
enables the use of virtually any secure silicon hardware.

Secure silicon root of trust hardware


Secure silicon is necessary to anchor trust inside the IoT Edge device hardware. Secure silicon come in variety to
include Trusted Platform Module (TPM ), embedded Secure Element (eSE ), ARM TrustZone, Intel SGX, and custom
secure silicon technologies. The use of secure silicon root of trust in devices is recommended given the threats
associated with physical accessibility of IoT devices.

IoT Edge security manager integration and maintenance


The IoT Edge security manager aims to identify and isolate the components that defend the security and integrity
of the Azure IoT Edge platform for custom hardening. Third parties, like device makers, should make use of
custom security features available with their device hardware. See next steps section for links that demonstrate
how to harden the Azure IoT security manager with the Trusted Platform Module (TPM ) on Linux and Windows
platforms. These examples use software or virtual TPMs but directly apply to using discrete TPM devices.

Next steps
Read the blog on Securing the intelligent edge.
Create and provision an IoT Edge device with a virtual TPM on a Linux virtual machine.
Create and provision an IoT Edge device with a simulated TPM on Windows.
Azure IoT Edge certificate usage detail
8/22/2019 • 8 minutes to read • Edit Online

IoT Edge certificates are used for the modules and downstream IoT devices to verify the identity and legitimacy of
the IoT Edge hub runtime module that they connect to. These verifications enable a TLS (transport layer security)
secure connection between the runtime, the modules, and the IoT devices. Like IoT Hub itself, IoT Edge requires a
secure and encrypted connection from IoT downstream (or leaf) devices and IoT Edge modules. To establish a
secure TLS connection, the IoT Edge hub module presents a server certificate chain to connecting clients in order
for them to verify its identity.
This article explains how IoT Edge certificates can work in production, development, and test scenarios. While the
scripts are different (Powershell vs. bash), the concepts are the same between Linux and Windows.

IoT Edge certificates


Usually, manufacturers are not the end users of an IoT Edge device. Sometimes the only relationship between the
two is when the end user, or operator, purchases a generic device made by the manufacturer. Other times, the
manufacturer works under contract to build a custom device on behalf of the operator. The IoT Edge certificate
design attempts to take both scenarios into account.
The following figure illustrates IoT Edge's usage of certificates. There may be zero, one, or many intermediate
signing certificates between the root CA certificate and the device CA certificate, depending on the number of
entities involved. Here we show one case.

Certificate authority
The certificate authority, or 'CA' for short, is an entity that issues digital certificates. A certificate authority acts as a
trusted third party between the owner, and the receiver of the certificate. A digital certificate certifies the
ownership of a public key by the receiver of the certificate. The certificate chain of trust works by initially issuing a
root certificate, which is the basis for trust in all certificates issued by the authority. Afterwards, the owner can use
the root certificate to issue additional intermediate certificates ('leaf' certificates).
Root CA certificate
A root CA certificate is the root of trust of the entire process. In production scenarios, this CA certificate is usually
purchased from a trusted commercial certificate authority like Baltimore, Verisign, or DigiCert. Should you have
complete control over the devices connecting to your IoT Edge devices, it's possible to use a corporate level
certificate authority. In either event, the entire certificate chain from the IoT Edge hub up rolls up to it, so the leaf
IoT devices must trust the root certificate. You can store the root CA certificate either in the trusted root certificate
authority store, or provide the certificate details in your application code.
Intermediate certificates
In a typical manufacturing process for creating secure devices, root CA certificates are rarely used directly,
primarily because of the risk of leakage or exposure. The root CA certificate creates and digitally signs one or
more intermediate CA certificates. There may only be one, or there may be a chain of these intermediate
certificates. Scenarios that would require a chain of intermediate certificates include:
A hierarchy of departments within a manufacturer.
Multiple companies involved serially in the production of a device.
A customer buying a root CA and deriving a signing certificate for the manufacturer to sign the devices
they make on that customer's behalf.
In any case, the manufacturer uses an intermediate CA certificate at the end of this chain to sign the device CA
certificate placed on the end device. Generally, these intermediate certificates are closely guarded at the
manufacturing plant. They undergo strict processes, both physical and electronic for their usage.
Device CA certificate
The device CA certificate is generated from and signed by the final intermediate CA certificate in the process. This
certificate is installed on the IoT Edge device itself, preferably in secure storage such as a hardware security
module (HSM ). In addition, a device CA certificate uniquely identifies an IoT Edge device. For IoT Edge, the device
CA certificate can issue other certificates. For example, the device CA certificate issues leaf device certificates that
are used to authenticate devices to the Azure IoT Device Provisioning Service.
IoT Edge Workload CA
The IoT Edge Security Manager generates the workload CA certificate, the first on the "operator" side of the
process, when IoT Edge first starts. This certificate is generated from and signed by the "device CA certificate".
This certificate, which is just another intermediate signing certificate, is used to generate and sign any other
certificates used by the IoT Edge runtime. Today, that is primarily the IoT Edge hub server certificate discussed in
the following section, but in the future may include other certificates for authenticating IoT Edge components.
IoT Edge hub server certificate
The IoT Edge hub server certificate is the actual certificate presented to leaf devices and modules for identity
verification during establishment of the TLS connection required by IoT Edge. This certificate presents the full
chain of signing certificates used to generate it up to the root CA certificate, which the leaf IoT device must trust.
When generated by the IoT Edge Security Manager, the common name (CN ), of this IoT Edge hub certificate is set
to the 'hostname' property in the config.yaml file after conversion to lower case. This is a common source of
confusion with IoT Edge.

Production implications
A reasonable question might be "why does IoT Edge need the 'workload CA' extra certificate? Couldn't it use the
device CA certificate to directly generate the IoT Edge hub server certificate?". Technically, it could. However, the
purpose of this "workload" intermediate certificate is to separate concerns between the device manufacturer and
the device operator. Imagine a scenario where an IoT Edge device is sold or transferred from one customer to
another. You would likely want the device CA certificate provided by the manufacturer to be immutable. However,
the "workload" certificates specific to operation of the device should be wiped and recreated for the new
deployment.
Because manufacturing and operation processes are separated, consider the following implications when
preparing production devices:
With any certificate-based process, the root CA certificate and all intermediate CA certificates should be
secured and monitored during the entire process of rolling out an IoT Edge device. The IoT Edge device
manufacturer should have strong processes in place for proper storage and usage of their intermediate
certificates. In addition, the device CA certificate should be kept in as secure storage as possible on the
device itself, preferably a hardware security module.
The IoT Edge hub server certificate is presented by IoT Edge hub to the connecting client devices and
modules. The common name (CN ) of the device CA certificate must not be the same as the "hostname"
that will be used in config.yaml on the IoT Edge device. The name used by clients to connect to IoT Edge
(for example, via the GatewayHostName parameter of the connection string or the CONNECT command in
MQTT) can't be the same as common name used in the device CA certificate. This restriction is because
the IoT Edge hub presents its entire certificate chain for verification by clients. If the IoT Edge hub server
certificate and the device CA certificate both have the same CN, you get in a verification loop and the
certificate invalidates.
Because the device CA certificate is used by the IoT Edge security daemon to generate the final IoT Edge
certificates, it must itself be a signing certificate, meaning it has certificate signing capabilities. Applying "V3
Basic constraints CA:True" to the device CA certificate automatically sets up the required key usage
properties.

TIP
If you've already gone through the setup of IoT Edge as a transparent gateway in a dev/test scenario using our "convenience
scripts" (see next section) and used the same host name when creating the device CA certificate as you did for the hostname
in config.yaml, you might be wondering why it worked. In an effort to simplify the developer experience, the convenience
scripts appends a ".ca" on the end of the name you pass into the script. So, for example, if you used "mygateway" for both
your device name in the scripts and hostname in config.yaml, the former will be turned into mygateway.ca before being used
as the CN for the device CA cert.

Dev/Test implications
To ease development and test scenarios, Microsoft provides a set of convenience scripts for generating non-
production certificates suitable for IoT Edge in the transparent gateway scenario. For examples of how the scripts
work, see Configure an IoT Edge device to act as a transparent gateway.
These scripts generate certificates that follow the certificate chain structure explained in this article. The following
commands generate the "root CA certificate" and a single "intermediate CA certificate".

./certGen.sh create_root_and_intermediate

New-CACertsCertChain rsa

Likewise, these commands generate the "Device CA Certificate".


./certGen.sh create_edge_device_ca_certificate "<gateway device name>"

New-CACertsEdgeDeviceCA "<gateway device name>"

The <gateway device name> passed into those scripts should not be the same as the "hostname" parameter
in config.yaml. The scripts help you avoid any issues by appending a ".ca" string to the <gateway device
name> to prevent the name collision in case a user sets up IoT Edge using the same name in both places.
However, it's good practice to avoid using the same name.

TIP
To connect your device IoT "leaf" devices and applications that use our IoT device SDK through IoT Edge, you must add the
optional GatewayHostName parameter on to the end of the device's connection string. When the Edge Hub Server
Certificate is generated, it is based on a lower-cased version of the hostname from config.yaml, therefore, for the names to
match and the TLS certificate verification to succeed, you should enter the GatewayHostName parameter in lower case.

Example of IoT Edge certificate hierarchy


To illustrate an example of this certificate path, the following screenshot is from a working IoT Edge device set up
as a transparent gateway. OpenSSL is used to connect to the IoT Edge hub, validate, and dump out the certificates.

You can see the hierarchy of certificate depth represented in the screenshot:

ROOT CA CERTIFICATE AZURE IOT HUB CA CERT TEST ONLY

Intermediate CA Certificate Azure IoT Hub Intermediate Cert Test Only

Device CA Certificate iotgateway.ca ("iotgateway" was passed in as the < gateway


host name > to the convenience scripts)

Workload CA Certificate iotedge workload ca

IoT Edge Hub Server Certificate iotedgegw.local (matches the 'hostname' from config.yaml)

Next steps
Understand Azure IoT Edge modules
Configure an IoT Edge device to act as a transparent gateway
Azure IoT Edge supported systems
12/1/2019 • 4 minutes to read • Edit Online

This article provides details about which systems and components are supported by IoT Edge, whether officially or
in preview.
If you experience problems while using the Azure IoT Edge service, there are several ways to seek support. Try one
of the following channels for support:
Reporting bugs – The majority of development that goes into the Azure IoT Edge product happens in the IoT
Edge open-source project. Bugs can be reported on the issues page of the project. Fixes rapidly make their way
from the project in to product updates.
Microsoft Customer Support team – Users who have a support plan can engage the Microsoft Customer
Support team by creating a support ticket directly from the Azure portal.
Feature requests – The Azure IoT Edge product tracks feature requests via the product’s User Voice page.

Container engines
Azure IoT Edge modules are implemented as containers, so IoT Edge needs a container engine to launch them.
Microsoft provides a container engine, moby-engine, to fulfill this requirement. This container engine is based on
the Moby open-source project. Docker CE and Docker EE are other popular container engines. They're also based
on the Moby open-source project and are compatible with Azure IoT Edge. Microsoft provides best effort support
for systems using those container engines; however, Microsoft can't ship fixes for issues in them. For this reason,
Microsoft recommends using moby-engine on production systems.

Operating systems
Azure IoT Edge runs on most operating systems that can run containers; however, all of these systems are not
equally supported. Operating systems are grouped into tiers that represent the level of support users can expect.
Tier 1 systems are supported. For tier 1 systems, Microsoft:
has this operating system in automated tests
provides installation packages for them
Tier 2 systems are compatible with Azure IoT Edge and can be used relatively easily. For tier 2 systems:
Microsoft has done ad hoc testing on the platforms or knows of a partner successfully running Azure
IoT Edge on the platform
Installation packages for other platforms may work on these platforms
The family of the host OS must always match the family of the guest OS used inside a module's container. In other
words, you can only use Linux containers on Linux and Windows containers on Windows. When using Windows,
only process isolated containers are supported, not Hyper-V isolated containers.

Tier 1
The systems listed in the following table are supported by Microsoft, either generally available or in public
preview, and are tested with each new release.

OPERATING SYSTEM AMD64 ARM32V7 ARM64

Raspbian Stretch

Ubuntu Server 16.04 Public preview

Ubuntu Server 18.04 Public preview

Windows 10 IoT Core, build


17763

Windows 10 IoT Enterprise,


build 17763

Windows Server 2019, build


17763

Windows Server IoT 2019,


build 17763

The Windows operating systems listed above are the requirements for devices that run Windows containers on
Windows, which is the only supported configuration for production. The Azure IoT Edge installation packages for
Windows allow the use of Linux containers on Windows; however, this configuration is for development and
testing only. For more information, see Use IoT Edge on Windows to run Linux containers.
Tier 2
The systems listed in the following table are considered compatible with Azure IoT Edge, but are not actively
tested or maintained by Microsoft.
OPERATING SYSTEM AMD64 ARM32V7 ARM64

CentOS 7.5

Debian 8

Debian 9

Debian 10 1

Mentor Embedded Linux


Flex OS

Mentor Embedded Linux


Omni OS

RHEL 7.5

Ubuntu 16.04

Ubuntu 18.04

Wind River 8

Yocto

Raspbian Buster 1

1 Debian 10 systems, including Raspian Buster, use a version of OpenSSL that IoT Edge doesn't support. Use the
following command to install an earlier version before installing IoT Edge:

sudo apt-get install libssl1.0.2

Virtual Machines
Azure IoT Edge can be run in virtual machines. Using a virtual machine as an IoT Edge device is common when
customers want to augment existing infrastructure with edge intelligence. The family of the host VM OS must
match the family of the guest OS used inside a module's container. This requirement is the same as when Azure
IoT Edge is run directly on a device. Azure IoT Edge is agnostic of the underlying virtualization technology and
works in VMs powered by platforms like Hyper-V and vSphere.
Minimum system requirements
Azure IoT Edge runs great on devices as small as a Raspberry Pi3 to server grade hardware. Choosing the right
hardware for your scenario depends on the workloads that you want to run. Making the final device decision can
be complicated; however, you can easily start prototyping a solution on traditional laptops or desktops.
Experience while prototyping will help guide your final device selection. Questions you should consider include:
How many modules are in your workload?
How many layers do your modules’ containers share?
In what language are your modules written?
How much data will your modules be processing?
Do your modules need any specialized hardware for accelerating their workloads?
What are the desired performance characteristics of your solution?
What is your hardware budget?
Prepare to deploy your IoT Edge solution in
production
12/1/2019 • 11 minutes to read • Edit Online

When you're ready to take your IoT Edge solution from development into production, make sure that it's
configured for ongoing performance.
The information provided in this article isn't all equal. To help you prioritize, each section starts with lists that divide
the work into two sections: important to complete before going to production, or helpful for you to know.

Device configuration
IoT Edge devices can be anything from a Raspberry Pi to a laptop to a virtual machine running on a server. You
may have access to the device either physically or through a virtual connection, or it may be isolated for extended
periods of time. Either way, you want to make sure that it's configured to work appropriately.
Important
Install production certificates
Have a device management plan
Use Moby as the container engine
Helpful
Choose upstream protocol
Install production certificates
Every IoT Edge device in production needs a device certificate authority (CA) certificate installed on it. That CA
certificate is then declared to the IoT Edge runtime in the config.yaml file. To make development and testing easier,
the IoT Edge runtime creates temporary certificates if no certificates are declared in the config.yaml file. However,
these temporary certificates expire after three months and aren't secure for production scenarios.
To understand the role of the device CA certificate, see How Azure IoT Edge uses certificates.
For more information about how to install certificates on an IoT Edge device and reference them from the
config.yaml file, see Configure an IoT Edge device to act as a transparent gateway. The steps for configuring the
certificates are the same whether the device is going to be used as a gateway or not. That article provides scripts to
generate sample certificates for testing only. Don't use those sample certificates in production.
Have a device management plan
Before you put any device in production you should know how you're going to manage future updates. For an IoT
Edge device, the list of components to update may include:
Device firmware
Operating system libraries
Container engine, like Moby
IoT Edge daemon
CA certificates
For more information, see Update the IoT Edge runtime. The current methods for updating the IoT Edge daemon
require physical or SSH access to the IoT Edge device. If you have many devices to update, consider adding the
update steps to a script or use an automation tool like Ansible.
Use Moby as the container engine
A container engine is a prerequisite for any IoT Edge device. Only moby-engine is supported in production. Other
container engines, like Docker, do work with IoT Edge and it's ok to use these engines for development. The moby-
engine can be redistributed when used with Azure IoT Edge, and Microsoft provides servicing for this engine.
Choose upstream protocol
The protocol (and therefore the port used) for upstream communication to IoT Hub can be configured for both the
IoT Edge agent and the IoT Edge hub. The default protocol is AMQP, but you may want to change that depending
on your network setup.
The two runtime modules both have an UpstreamProtocol environment variable. The valid values for the variable
are:
MQTT
AMQP
MQTTWS
AMQPWS
Configure the UpstreamProtocol variable for the IoT Edge agent in the config.yaml file on the device itself. For
example, if your IoT Edge device is behind a proxy server that blocks AMQP ports, you may need to configure the
IoT Edge agent to use AMQP over WebSocket (AMQPWS ) to establish the initial connection to IoT Hub.
Once your IoT Edge device connects, be sure to continue configuring the UpstreamProtocol variable for both
runtime modules in future deployments. An example of this process is provided in Configure an IoT Edge device to
communicate through a proxy server.

Deployment
Helpful
Be consistent with upstream protocol
Set up host storage for system modules
Reduce memory space used by the IoT Edge hub
Do not use debug versions of module images
Be consistent with upstream protocol
If you configured the IoT Edge agent on your IoT Edge device to use a different protocol than the default AMQP,
then you should declare the same protocol in all future deployments. For example, if your IoT Edge device is
behind a proxy server that blocks AMQP ports, you probably configured the device to connect over AMQP over
WebSocket (AMQPWS ). When you deploy modules to the device, configure the same AMQPWS protocol for the
IoT Edge agent and IoT Edge hub, or else the default AMQP will override the settings and prevent you from
connecting again.
You only have to configure the UpstreamProtocol environment variable for the IoT Edge agent and IoT Edge hub
modules. Any additional modules adopt whatever protocol is set in the runtime modules.
An example of this process is provided in Configure an IoT Edge device to communicate through a proxy server.
Set up host storage for system modules
The IoT Edge hub and agent modules use local storage to maintain state and enable messaging between modules,
devices, and the cloud. For better reliability and performance, configure the system modules to use storage on the
host filesystem.
For more information, see Host storage for system modules.
Reduce memory space used by IoT Edge hub
If you're deploying constrained devices with limited memory available, you can configure IoT Edge hub to run in a
more streamlined capacity and use less disk space. These configurations do limit the performance of the IoT Edge
hub, however, so find the right balance that works for your solution.
Don't optimize for performance on constrained devices
The IoT Edge hub is optimized for performance by default, so it attempts to allocate large chunks of memory. This
configuration can cause stability problems on smaller devices like the Raspberry Pi. If you're deploying devices with
constrained resources, you may want to set the OptimizeForPerformance environment variable to false on the
IoT Edge hub.
When OptimizeForPerformance is set to true, the MQTT protocol head uses the PooledByteBufferAllocator
which has better performance but allocates more memory. The allocator does not work well on 32 bit operating
systems or on devices with low memory. Additionally, when optimized for performance, RocksDb allocates more
memory for its role as the local storage provider.
For more information, see Stability issues on resource constrained devices.
Disable unused protocols
Another way to optimize the performance of the IoT Edge hub and reduce its memory usage is to turn off the
protocol heads for any protocols that you're not using in your solution.
Protocol heads are configured by setting boolean environment variables for the IoT Edge hub module in your
deployment manifests. The three variables are:
amqpSettings__enabled
mqttSettings__enabled
httpSettings__enabled
All three variables have two underscores and can be set to either true or false.
Reduce storage time for messages
The IoT Edge hub module stores messages temporarily if they cannot be delivered to IoT Hub for any reason. You
can configure how long the IoT Edge hub holds on to undelivered messages before letting them expire. If you have
memory concerns on your device, you can lower the timeToLiveSecs value in the IoT Edge hub module twin.
The default value of the timeToLiveSecs parameter is 7200 seconds, which is two hours.
Do not use debug versions of module images
When moving from test scenarios to production scenarios, remember to remove debug configurations from
deployment manifests. Check that none of the module images in the deployment manifests have the .debug suffix.
If you added create options to expose ports in the modules for debugging, remove those create options as well.

Container management
Important
Manage access to your container registry
Use tags to manage versions
Manage access to your container registry
Before you deploy modules to production IoT Edge devices, ensure that you control access to your container
registry so that outsiders can't access or make changes to your container images. Use a private, not public,
container registry to manage container images.
In the tutorials and other documentation, we instruct you to use the same container registry credentials on your
IoT Edge device as you use on your development machine. These instructions are only intended to help you set up
testing and development environments more easily, and should not be followed in a production scenario. Azure
Container Registry recommends authenticating with service principals when applications or services pull container
images in an automated or otherwise unattended manner, as IoT Edge devices do. Create a service principal with
read-only access to your container registry, and provide that username and password in the deployment manifest.
Use tags to manage versions
A tag is a docker concept that you can use to distinguish between versions of docker containers. Tags are suffixes
like 1.0 that go on the end of a container repository. For example, mcr.microsoft.com/azureiotedge-agent:1.0.
Tags are mutable and can be changed to point to another container at any time, so your team should agree on a
convention to follow as you update your module images moving forward.
Tags also help you to enforce updates on your IoT Edge devices. When you push an updated version of a module
to your container registry, increment the tag. Then, push a new deployment to your devices with the tag
incremented. The container engine will recognize the incremented tag as a new version and will pull the latest
module version down to your device.
For an example of a tag convention, see Update the IoT Edge runtime to learn how IoT Edge uses rolling tags and
specific tags to track versions.

Networking
Helpful
Review outbound/inbound configuration
Allow connections from IoT Edge devices
Configure communication through a proxy
Review outbound/inbound configuration
Communication channels between Azure IoT Hub and IoT Edge are always configured to be outbound. For most
IoT Edge scenarios, only three connections are necessary. The container engine needs to connect with the container
registry (or registries) that holds the module images. The IoT Edge runtime needs to connect with IoT Hub to
retrieve device configuration information, and to send messages and telemetry. And if you use automatic
provisioning, the IoT Edge daemon needs to connect to the Device Provisioning Service. For more information, see
Firewall and port configuration rules.
Allow connections from IoT Edge devices
If your networking setup requires that you explicitly permit connections made from IoT Edge devices, review the
following list of IoT Edge components:
IoT Edge agent opens a persistent AMQP/MQTT connection to IoT Hub, possibly over WebSockets.
IoT Edge hub opens a single persistent AMQP connection or multiple MQTT connections to IoT Hub, possibly
over WebSockets.
IoT Edge daemon makes intermittent HTTPS calls to IoT Hub.
In all three cases, the DNS name would match the pattern *.azure-devices.net.
Additionally, the Container engine makes calls to container registries over HTTPS. To retrieve the IoT Edge
runtime container images, the DNS name is mcr.microsoft.com. The container engine connects to other registries
as configured in the deployment.
This checklist is a starting point for firewall rules:

URL (* = WILDCARD) OUTBOUND TCP PORTS USAGE

mcr.microsoft.com 443 Microsoft container registry

global.azure-devices-provisioning.net 443 DPS access (optional)


URL (* = WILDCARD) OUTBOUND TCP PORTS USAGE

*.azurecr.io 443 Personal and third-party container


registries

*.blob.core.windows.net 443 Download Azure Container Registry


image deltas from blob storage

*.azure-devices.net 5671, 8883, 443 IoT Hub access

*.docker.io 443 Docker Hub access (optional)

Some of these firewall rules are inherited from Azure Container Registry. For more information, see Configure
rules to access an Azure container registry behind a firewall.
Configure communication through a proxy
If your devices are going to be deployed on a network that uses a proxy server, they need to be able to
communicate through the proxy to reach IoT Hub and container registries. For more information, see Configure an
IoT Edge device to communicate through a proxy server.

Solution management
Helpful
Set up logs and diagnostics
Consider tests and CI/CD pipelines
Set up logs and diagnostics
On Linux, the IoT Edge daemon uses journals as the default logging driver. You can use the command-line tool
journalctl to query the daemon logs. On Windows, the IoT Edge daemon uses PowerShell diagnostics. Use
Get-IoTEdgeLog to query logs from the daemon. IoT Edge modules use the JSON driver for logging, which is the
default.

. {Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; Get-IoTEdgeLog

When you're testing an IoT Edge deployment, you can usually access your devices to retrieve logs and
troubleshoot. In a deployment scenario, you may not have that option. Consider how you're going to gather
information about your devices in production. One option is to use a logging module that collects information from
the other modules and sends it to the cloud. One example of a logging module is logspout-loganalytics, or you can
design your own.
Place limits on log size
By default the Moby container engine does not set container log size limits. Over time this can lead to the device
filling up with logs and running out of disk space. Consider the following options to prevent this:
Option: Set global limits that apply to all container modules
You can limit the size of all container logfiles in the container engine log options. The following example sets the
log driver to json-file (recommended) with limits on size and number of files:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}

Add (or append) this information to a file named daemon.json and place it the right location for your device
platform.

PLATFORM LOCATION

Linux /etc/docker/

Windows C:\ProgramData\iotedge-moby\config\

The container engine must be restarted for the changes to take effect.
Option: Adjust log settings for each container module
You can do so in the createOptions of each module. For example:

"createOptions": {
"HostConfig": {
"LogConfig": {
"Type": "json-file",
"Config": {
"max-size": "10m",
"max-file": "3"
}
}
}
}

Additional options on Linux systems


Configure the container engine to send logs to systemd journal by setting journald as the default logging
driver.
Periodically remove old logs from your device by installing a logrotate tool. Use the following file
specification:

/var/lib/docker/containers/*/*-json.log{
copytruncate
daily
rotate7
delaycompress
compress
notifempty
missingok
}

Consider tests and CI/CD pipelines


For the most efficient IoT Edge deployment scenario, consider integrating your production deployment into your
testing and CI/CD pipelines. Azure IoT Edge supports multiple CI/CD platforms, including Azure DevOps. For
more information, see Continuous integration and continuous deployment to Azure IoT Edge.
Next steps
Learn more about IoT Edge automatic deployment.
See how IoT Edge supports Continuous integration and continuous deployment.
Glossary of terms for Azure IoT Edge
11/24/2019 • 3 minutes to read • Edit Online

This article lists some of the common terms used in the IoT Edge articles.

Automatic Device Management


Automatic Device Management in Azure IoT Hub automates many of the repetitive and complex tasks of
managing large device fleets over the entirety of their lifecycles. With Automatic Device Management, you can
target a set of devices based on their properties, define a desired configuration, and let IoT Hub update devices
whenever they come into scope. Consists of automatic device configurations and IoT Edge automatic deployments.

IoT Edge
Azure IoT Edge enables cloud-driven deployment of Azure services and solution-specific code to on-premises
devices. IoT Edge devices can aggregate data from other devices to perform computing and analytics before the
data is sent to the cloud. For more information, see Azure IoT Edge.

IoT Edge agent


The part of the IoT Edge runtime responsible for deploying and monitoring modules.

IoT Edge device


IoT Edge devices have the IoT Edge runtime installed and are flagged as IoT Edge device in the device details.
Learn how to deploy Azure IoT Edge on a simulated device in Linux - preview.

IoT Edge automatic deployment


An IoT Edge automatic deployment configures a target set of IoT Edge devices to run a set of IoT Edge modules.
Each deployment continuously ensures that all devices that match its target condition are running the specified set
of modules, even when new devices are created or are modified to match the target condition. Each IoT Edge
device only receives the highest priority deployment whose target condition it meets. Learn more about IoT Edge
automatic deployment.

IoT Edge deployment manifest


A Json document containing the information to be copied in one or more IoT Edge devices' module twin(s) to
deploy a set of modules, routes, and associated module desired properties.

IoT Edge gateway device


An IoT Edge device with downstream device. The downstream device can be either IoT Edge or not IoT Edge
device.

IoT Edge hub


The part of the IoT Edge runtime responsible for module to module communications, upstream (toward IoT Hub)
and downstream (away from IoT Hub) communications.
IoT Edge leaf device
An IoT Edge device with no downstream device.

IoT Edge module


An IoT Edge module is a Docker container that you can deploy to IoT Edge devices. It performs a specific task, such
as ingesting a message from a device, transforming a message, or sending a message to an IoT hub. It
communicates with other modules and sends data to the IoT Edge runtime. Understand the requirements and tools
for developing IoT Edge modules.

IoT Edge module identity


A record in the IoT Hub module identity registry detailing the existence and security credentials to be used by a
module to authenticate with an edge hub or IoT Hub.

IoT Edge module image


The docker image that is used by the IoT Edge runtime to instantiate module instances.

IoT Edge module twin


A Json document persisted in the IoT Hub that stores the state information for a module instance.

IoT Edge priority


When two IoT Edge deployments target the same device, the deployment with higher priority gets applied. If two
deployments have the same priority, the deployment with the later creation date gets applied. Learn more about
priority.

IoT Edge runtime


IoT Edge runtime includes everything that Microsoft distributes to be installed on an IoT Edge device. It includes
Edge agent, Edge hub, and the IoT Edge security daemon.

IoT Edge set modules to a single device


An operation that copies the content of an IoT Edge manifest on one device' module twin. The underlying API is a
generic 'apply configuration', which simply takes an IoT Edge manifest as an input.

IoT Edge target condition


In an IoT Edge deployment, Target condition is any Boolean condition on device twins’ tags to select the target
devices of the deployment, for example tag.environment = prod. The target condition is continuously evaluated
to include any new devices that meet the requirements or remove devices that no longer do. Learn more about
target condition

Next steps
IoT Hub glossary
Register an Azure IoT Edge device
11/24/2019 • 5 minutes to read • Edit Online

Before you can use your IoT devices with Azure IoT Edge, you must register them with your IoT hub. Once a
device is registered, you can retrieve a connection string to set up your device for IoT Edge workloads.
You have the choice of registering by using one of the following tools:
Azure portal provides a graphical user interface to create, view, and manage Azure resources.
Visual Studio Code is a source-code editor. Azure IoT extensions make it easy to manage IoT resources from
the same tool where you're developing IoT solutions.
Azure CLI is a command-line tool for managing Azure resources. Its reusable commands are helpful for
automating tasks.

Register in the Azure portal


You can perform all registration tasks in the Azure portal.
Prerequisites for the Azure portal
A free or standard IoT hub in your Azure subscription.
Create an IoT Edge device in the Azure portal
In your IoT Hub in the Azure portal, IoT Edge devices are created and managed separately from IOT devices that
are not edge enabled.
1. Sign in to the Azure portal and navigate to your IoT hub.
2. In the left pane, select IoT Edge from the menu.
3. Select Add an IoT Edge device.
4. Provide a descriptive device ID. Use the default settings to auto-generate authentication keys and connect the
new device to your hub.
5. Select Save.
View IoT Edge devices in the Azure portal
All the edge-enabled devices that connect to your IoT hub are listed on the IoT Edge page.
Retrieve the connection string in the Azure portal
When you're ready to set up your device, you need the connection string that links your physical device with its
identity in the IoT hub.
1. From the IoT Edge page in the portal, click on the device ID from the list of IoT Edge devices.
2. Copy the value of either Connection string (primary key) or Connection string (secondary key).

Register with Visual Studio Code


There are multiple ways to perform most operations in VS Code. This article uses the Explorer, but you can also
use the Command Palette to run the steps.
Prerequisites for Visual Studio Code
An IoT hub in your Azure subscription
Visual Studio Code
Azure IoT Tools for Visual Studio Code
Sign in to access your IoT hub
You can use the Azure IoT extensions for Visual Studio Code to perform operations with your IoT Hub. For these
operations to work, you need to sign in to your Azure account and select your IoT Hub.
1. In Visual Studio Code, open the Explorer view.
2. At the bottom of the Explorer, expand the Azure IoT Hub section.

3. Click on the ... in the Azure IoT Hub section header. If you don't see the ellipsis, click on or hover over the
header.
4. Choose Select IoT Hub.
5. If you aren't signed in to your Azure account, follow the prompts to do so.
6. Select your Azure subscription.
7. Select your IoT hub.
Create an IoT Edge device with Visual Studio Code
1. In the VS Code Explorer, expand the Azure IoT Hub Devices section.
2. Click on the ... in the Azure IoT Hub Devices section header. If you don't see the ellipsis, click on or hover over
the header.
3. Select Create IoT Edge Device.
4. In the text box that opens, give your device an ID.
In the output screen, you see the result of the command. The device info is printed, which includes the deviceId
that you provided and the connectionString that you can use to connect your physical device to your IoT hub.
In the output screen, you see the result of the command. The device info is printed, which includes the deviceId
that you provided and the connectionString that you can use to connect your physical device to your IoT hub.
View IoT Edge devices with Visual Studio Code
All the devices that connect to your IoT hub are listed in the Azure IoT Hub section of the Visual Studio Code
Explorer. IoT Edge devices are distinguishable from non-Edge devices with a different icon, and the fact that the
$edgeAgent and $edgeHub modules are deployed to each IoT Edge device.

Retrieve the connection string with Visual Studio Code


When you're ready to set up your device, you need the connection string that links your physical device with its
identity in the IoT hub.
1. Right-click on the ID of your device in the Azure IoT Hub section.
2. Select Copy Device Connection String.
The connection string is copied to your clipboard.
You can also select Get Device Info from the right-click menu to see all the device info, including the connection
string, in the output window.
Register with the Azure CLI
The Azure CLI is an open-source cross platform command-line tool for managing Azure resources such as IoT
Edge. It enables you to manage Azure IoT Hub resources, device provisioning service instances, and linked-hubs
out of the box. The new IoT extension enriches Azure CLI with features such as device management and full IoT
Edge capability.
Prerequisites for the Azure CLI
An IoT hub in your Azure subscription.
Azure CLI in your environment. At a minimum, your Azure CLI version must be 2.0.24 or above. Use
az --version to validate. This version supports az extension commands and introduces the Knack command
framework.
The IoT extension for Azure CLI.
Create an IoT Edge device with the Azure CLI
Use the az iot hub device-identity create command to create a new device identity in your IoT hub. For example:

az iot hub device-identity create --device-id [device id] --hub-name [hub name] --edge-enabled

This command includes three parameters:


device-id: Provide a descriptive name that's unique to your IoT hub.
hub-name: Provide the name of your IoT hub.
edge-enabled: This parameter declares that the device is for use with IoT Edge.

View IoT Edge devices with the Azure CLI


Use the az iot hub device-identity list command to view all devices in your IoT hub. For example:

az iot hub device-identity list --hub-name [hub name]

Any device that is registered as an IoT Edge device will have the property capabilities.iotEdge set to true.
Retrieve the connection string with the Azure CLI
When you're ready to set up your device, you need the connection string that links your physical device with its
identity in the IoT hub. Use the az iot hub device-identity show -connection-string command to return the
connection string for a single device:

az iot hub device-identity show-connection-string --device-id [device id] --hub-name [hub name]

The value for the device-id parameter is case-sensitive. Don't copy the quotation marks around the connection
string.

Next steps
Now that you have a device identity registered in your IoT hub, you're ready to install the IoT Edge runtime on
your devices. Install the runtime according to the device's operating system:
Install Azure IoT Edge on Windows
Install the Azure IoT Edge runtime on Linux
Install the Azure IoT Edge runtime on Debian-based
Linux systems
11/24/2019 • 9 minutes to read • Edit Online

The Azure IoT Edge runtime is what turns a device into an IoT Edge device. The runtime can be deployed on
devices as small as a Raspberry Pi or as large as an industrial server. Once a device is configured with the IoT
Edge runtime, you can start deploying business logic to it from the cloud. To learn more, see Understand the
Azure IoT Edge runtime and its architecture.
This article lists the steps to install the Azure IoT Edge runtime on an X64, ARM32, or ARM64 Linux device.
Installation packages are provided for Ubuntu Server 16.04, Ubuntu Server 18.04, and Raspbian Stretch. Refer to
Azure IoT Edge supported systems for a list of supported Linux operating systems and architectures.

NOTE
Support for ARM64 devices is in public preview.

NOTE
Packages in the Linux software repositories are subject to the license terms located in each package
(/usr/share/doc/package-name). Read the license terms prior to using the package. Your installation and use of the package
constitutes your acceptance of these terms. If you do not agree with the license terms, do not use the package.

Install the latest runtime version


Use the following sections to install the most recent version of the Azure IoT Edge runtime onto your device.
Register Microsoft key and software repository feed
Prepare your device for the IoT Edge runtime installation.
Install the repository configuration. Choose the 16.04 or 18.04 command that matches your device operating
system:
Ubuntu Server 16.04:

curl https://packages.microsoft.com/config/ubuntu/16.04/multiarch/prod.list > ./microsoft-prod.list

Ubuntu Server 18.04:

curl https://packages.microsoft.com/config/ubuntu/18.04/multiarch/prod.list > ./microsoft-prod.list

Raspbian Stretch:

curl https://packages.microsoft.com/config/debian/stretch/multiarch/prod.list > ./microsoft-prod.list

Copy the generated list.


sudo cp ./microsoft-prod.list /etc/apt/sources.list.d/

Install Microsoft GPG public key

curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg


sudo cp ./microsoft.gpg /etc/apt/trusted.gpg.d/

Install the container runtime


Azure IoT Edge relies on an OCI-compatible container runtime. For production scenarios, we recommended that
you use the Moby-based engine provided below. It is the only container engine officially supported with Azure
IoT Edge. Docker CE/EE container images are compatible with the Moby runtime.
Perform apt update.

sudo apt-get update

Install the Moby engine.

sudo apt-get install moby-engine

Install the Moby command-line interface (CLI). The CLI is useful for development but optional for production
deployments.

sudo apt-get install moby-cli

If you encounter errors when installing the Moby container runtime, follow the steps to Verify your Linux kernel
for Moby compatibility, provided later in this article.
Install the Azure IoT Edge Security Daemon
The IoT Edge security daemon provides and maintains security standards on the IoT Edge device. The daemon
starts on every boot and bootstraps the device by starting the rest of the IoT Edge runtime.
The installation command also installs the standard version of the libiothsm if not already present.
Perform apt update.

sudo apt-get update

Install the security daemon. The package is installed at /etc/iotedge/ .

sudo apt-get install iotedge

Once IoT Edge is successfully installed, the output will prompt you to update the configuration file. Follow the
steps in the Configure the Azure IoT Edge security daemon section to finish provisioning your device.

Install a specific runtime version


If you want to install a specific version of the Azure IoT Edge runtime, you can target the component files directly
from the IoT Edge GitHub repository. Use the following steps to get all of the IoT Edge components onto your
device: the Moby engine and CLI, the libiothsm, and finally the IoT Edge security daemon.
1. Navigate to the Azure IoT Edge releases, and find the release version that you want to target.
2. Expand the Assets section for that version.
3. There may or may not be updates to the Moby engine in any given release. If you see files that start with
moby-engine and moby-cli, use the following commands to update those components. If you don't see
any Moby files, go back through the older release assets until you find the most recent version.
a. Find the moby-engine file that matches your IoT Edge device's architecture. Right-click on the file
link and copy the link address.
b. Use the copied link in the following command to install that version of the Moby engine:

curl -L <moby-engine link> -o moby_engine.deb && sudo dpkg -i ./moby_engine.deb

c. Find the moby-cli file that matches your IoT Edge device's architecture. The Moby CLI is an
optional component, but can be helpful during development. Right-click on the file link and copy the
link address.
d. Use the copied link in the following command to install that version of the Moby CLI:

curl -L <moby-cli link> -o moby_cli.deb && sudo dpkg -i ./moby_cli.deb

4. Every release should have new files for the IoT Edge security daemon and the hsmlib. Use the following
commands to update those components.
a. Find the libiothsm -std file that matches your IoT Edge device's architecture. Right-click on the file
link and copy the link address.
b. Use the copied link in the following command to install that version of the hsmlib:

curl -L <libiothsm-std link> -o libiothsm-std.deb && sudo dpkg -i ./libiothsm-std.deb

c. Find the iotedge file that matches your IoT Edge device's architecture. Right-click on the file link
and copy the link address.
d. Use the copied link in the following command to install that version of the IoT Edge security
daemon.

curl -L <iotedge link> -o iotedge.deb && sudo dpkg -i ./iotedge.deb

Once IoT Edge is successfully installed, the output will prompt you to update the configuration file. Follow the
steps in the next section to finish provisioning your device.

Configure the security daemon


Configure the IoT Edge runtime to link your physical device with a device identity that exists in an Azure IoT hub.
The daemon can be configured using the configuration file at /etc/iotedge/config.yaml . The file is write-
protected by default, you might need elevated permissions to edit it.
A single IoT Edge device can be provisioned manually using a device connections string provided by IoT Hub. Or,
you can use the Device Provisioning Service to automatically provision devices, which is helpful when you have
many devices to provision. Depending on your provisioning choice, choose the appropriate installation script.
Option 1: Manual provisioning
To manually provision a device, you need to provide it with a device connection string that you can create by
registering a new device in your IoT hub.
Open the configuration file.

sudo nano /etc/iotedge/config.yaml

Find the provisioning configurations of the file and uncomment the Manual provisioning configuration
section. Update the value of device_connection_string with the connection string from your IoT Edge device.
Make sure any other provisioning sections are commented out.

# Manual provisioning configuration


provisioning:
source: "manual"
device_connection_string: "<ADD DEVICE CONNECTION STRING HERE>"

# DPS TPM provisioning configuration


# provisioning:
# source: "dps"
# global_endpoint: "https://global.azure-devices-provisioning.net"
# scope_id: "{scope_id}"
# attestation:
# method: "tpm"
# registration_id: "{registration_id}"

To paste clipboard contents into Nano Shift+Right Click or press Shift+Insert .


Save and close the file.
CTRL + X , Y , Enter

After entering the provisioning information in the configuration file, restart the daemon:

sudo systemctl restart iotedge

Option 2: Automatic provisioning


To automatically provision a device, set up Device Provisioning Service and retrieve your device registration ID.
There are a number of attestation mechanisms supported by IoT Edge when using automatic provisioning but
your hardware requirements also impact your choices. For example, Raspberry Pi devices do not come with a
Trusted Platform Module (TPM ) chip by default.
Open the configuration file.

sudo nano /etc/iotedge/config.yaml

Find the provisioning configurations of the file and uncomment the section appropriate for your attestation
mechanism. When using TPM attestation, for example, update the values of scope_id and registration_id with
the values from your IoT Hub Device Provisioning service and your IoT Edge device with TPM, respectively.
# Manual provisioning configuration
# provisioning:
# source: "manual"
# device_connection_string: "<ADD DEVICE CONNECTION STRING HERE>"

# DPS TPM provisioning configuration


provisioning:
source: "dps"
global_endpoint: "https://global.azure-devices-provisioning.net"
scope_id: "{scope_id}"
attestation:
method: "tpm"
registration_id: "{registration_id}"

To paste clipboard contents into Nano Shift+Right Click or press Shift+Insert .


Save and close the file.
CTRL + X , Y , Enter

After entering the provisioning information in the configuration file, restart the daemon:

sudo systemctl restart iotedge

Verify successful installation


If you used the manual configuration steps in the previous section, the IoT Edge runtime should be successfully
provisioned and running on your device. If you used the automatic configuration steps, then you need to
complete some additional steps so that the runtime can register your device with your IoT hub on your behalf. For
next steps, see Create and provision a simulated TPM IoT Edge device on a Linux virtual machine.
You can check the status of the IoT Edge Daemon:

systemctl status iotedge

Examine daemon logs:

journalctl -u iotedge --no-pager --no-full

Run an automated check for the most common configuration and networking errors:

sudo iotedge check

And, list running modules:

sudo iotedge list

After installing IoT Edge on your device, the only module you should see running is edgeAgent. Once you create
your first deployment, the other system module $edgeHub will start on the device as well. For more information,
see deploy IoT Edge modules.

Tips and troubleshooting


You need elevated privileges to run iotedge commands. After installing the runtime, sign out of your machine
and sign back in to update your permissions automatically. Until then, use sudo in front of any iotedge the
commands.
On resource constrained devices, it is highly recommended that you set the OptimizeForPerformance
environment variable to false as per instructions in the troubleshooting guide.
If your network that has a proxy server, follow the steps in Configure your IoT Edge device to communicate
through a proxy server.
Verify your Linux kernel for Moby compatibility
Many embedded device manufacturers ship device images that contain custom Linux kernels without the features
required for container runtime compatibility. If you encounter issues while installing the recommended Moby
container runtime, you may be able to troubleshoot your Linux kernel configuration using the check-config script
from the official Moby GitHub repository. Run the following commands on the device to check your kernel
configuration:

curl -sSL https://raw.githubusercontent.com/moby/moby/master/contrib/check-config.sh -o check-config.sh


chmod +x check-config.sh
./check-config.sh

This will provide a detailed output that contains the status of kernel features that are used by the Moby runtime.
You will want to ensure that all items under Generally Necessary and Network Drivers are enabled to ensure that
your kernel is fully compatible with the Moby runtime. If you have identified any missing features, enable them by
rebuilding your kernel from source and selecting the associated modules for inclusion in the appropriate kernel
.config. Similarly, if you are using a kernel configuration generator like defconfig or menuconfig, find and enable
the respective features and rebuild your kernel accordingly. Once you have deployed your newly modified kernel,
run the check-config script again to verify that all the required features were successfully enabled.

Uninstall IoT Edge


If you want to remove the IoT Edge installation from your Linux device, use the following commands from the
command line.
Remove the IoT Edge runtime.

sudo apt-get remove --purge iotedge

When the IoT Edge runtime is removed, the container that it created are stopped but still exist on your device.
View all containers to see which ones remain.

sudo docker ps -a

Delete the containers from your device, including the two runtime containers.

sudo docker rm -f <container name>

Finally, remove the container runtime from your device.

sudo apt-get remove --purge moby-cli


sudo apt-get remove --purge moby-engine
Next steps
Now that you have an IoT Edge device provisioned with the runtime installed, you can deploy IoT Edge modules.
If you are having problems with the IoT Edge runtime installing properly, check out the troubleshooting page.
To update an existing installation to the newest version of IoT Edge, see Update the IoT Edge security daemon and
runtime.
Install the Azure IoT Edge runtime on Windows
11/24/2019 • 14 minutes to read • Edit Online

The Azure IoT Edge runtime is what turns a device into an IoT Edge device. The runtime can be deployed on
devices as small as a Raspberry Pi or as large as an industrial server. Once a device is configured with the IoT
Edge runtime, you can start deploying business logic to it from the cloud.
To learn more about the IoT Edge runtime, see Understand the Azure IoT Edge runtime and its architecture.
This article lists the steps to install the Azure IoT Edge runtime on your Windows x64 (AMD/Intel) system using
Windows containers.

NOTE
A known Windows operating system issue prevents transition to sleep and hibernate power states when IoT Edge modules
(process-isolated Windows Nano Server containers) are running. This issue impacts battery life on the device.
As a workaround, use the command Stop-Service iotedge to stop any running IoT Edge modules before using these
power states.

Using Linux containers on Windows systems is not a recommended or supported production configuration for
Azure IoT Edge. However, it can be used for development and testing purposes. To learn more, see Use IoT Edge
on Windows to run Linux containers.
For information about what's included in the latest version of IoT Edge, see Azure IoT Edge releases.

Prerequisites
Use this section to review whether your Windows device can support IoT Edge, and to prepare it for a container
engine before installation.
Supported Windows versions
For development and test scenarios, Azure IoT Edge with Windows containers can be installed on any version of
Windows 10 or Windows Server 2019 (build 17763) that supports the containers feature. For information about
which operating systems are currently supported for production scenarios, see Azure IoT Edge supported
systems.
IoT Core devices must include the IoT Core- Windows Containers optional feature to support the IoT Edge
runtime. Use the following command in a remote PowerShell session to check that Windows containers are
supported on your device:

Get-Service vmcompute

If the service is present, you should get a successful response with the service status listed as running. If the
vmcompute service is not found, then your device does not meet the requirements for IoT Edge. Contact your
hardware provider to ask about support for this feature.
Prepare for a container engine
Azure IoT Edge relies on a OCI-compatible container engine. For production scenarios, use the Moby engine
included in the installation script to run Windows containers on your Windows device.
Install IoT Edge on a new device
NOTE
Azure IoT Edge software packages are subject to the license terms located in the packages (in the LICENSE directory). Please
read the license terms prior to using the package. Your installation and use of the package constitutes your acceptance of
these terms. If you do not agree with the license terms, do not use the package.

A PowerShell script downloads and installs the Azure IoT Edge security daemon. The security daemon then starts
the first of two runtime modules, the IoT Edge agent, which enables remote deployments of other modules.

TIP
For IoT Core devices, we recommend running the installation commands using a RemotePowerShell session. For more
information, see Using PowerShell for Windows IoT.

When you install the IoT Edge runtime for the first time on a device, you need to provision the device with an
identity from an IoT hub. A single IoT Edge device can be provisioned manually using a device connection string
provided by IoT Hub. Or, you can use the Device Provisioning Service (DPS ) to automatically provision devices,
which is helpful when you have many devices to set up. Depending on your provisioning choice, choose the
appropriate installation script.
The following sections describe the common use cases and parameters for the IoT Edge installation script on a
new device.
Option 1: Install and manually provision
In this first option, you provide a device connection string generated by IoT Hub to provision the device.
This example demonstrates a manual installation with Windows containers:
1. If you haven't already, register a new IoT Edge device and retrieve the device connection string. Copy
the connection string to use later in this section. You can complete this step using the following tools:
Azure portal
Azure CLI
Visual Studio Code
2. Run PowerShell as an administrator.

NOTE
Use an AMD64 session of PowerShell to install IoT Edge, not PowerShell (x86). If you're not sure which session type
you're using, run the following command:

(Get-Process -Id $PID).StartInfo.EnvironmentVariables["PROCESSOR_ARCHITECTURE"]

3. The Deploy-IoTEdge command checks that your Windows machine is on a supported version, turns on
the containers feature, and then downloads the moby runtime and the IoT Edge runtime. The command
defaults to using Windows containers.

. {Invoke-WebRequest -useb https://aka.ms/iotedge-win} | Invoke-Expression; `


Deploy-IoTEdge
4. At this point, IoT Core devices may restart automatically. Other Windows 10 or Windows Server devices
may prompt you to restart. If so, restart your device now. Once your device is ready, run PowerShell as an
administrator again.
5. The Initialize-IoTEdge command configures the IoT Edge runtime on your machine. The command
defaults to manual provisioning with Windows containers.

. {Invoke-WebRequest -useb https://aka.ms/iotedge-win} | Invoke-Expression; `


Initialize-IoTEdge

6. When prompted, provide the device connection string that you retrieved in step 1. The device connection
string associates the physical device with a device ID in IoT Hub.
The device connection string takes the following format, and should not include quotation marks:
HostName={IoT hub name}.azure-devices.net;DeviceId={device name};SharedAccessKey={key}

7. Use the steps in Verify successful installation to check the status of IoT Edge on your device.
When you install and provision a device manually, you can use additional parameters to modify the installation
including:
Direct traffic to go through a proxy server
Point the installer to an offline directory
Declare a specific agent container image, and provide credentials if it's in a private registry
For more information about these installation options, skip ahead to learn about all installation parameters.
Option 2: Install and automatically provision
In this second option, you provision the device using the IoT Hub Device Provisioning Service. Provide the Scope
ID from a Device Provisioning Service instance along with any other information specific to your preferred
attestation mechanism:
Create and provision a simulated IoT Edge device with a virtual TPM on Windows
Create and provision an IoT Edge device using symmetric key attestation
When you install and provision a device automatically, you can use additional parameters to modify the
installation including:
Direct traffic to go through a proxy server
Point the installer to an offline directory
Declare a specific agent container image, and provide credentials if it's in a private registry
For more information about these installation options, continue reading this article or skip to learn about All
installation parameters.

Offline installation
During installation two files are downloaded:
Microsoft Azure IoT Edge cab, which contains the IoT Edge security daemon (iotedged), Moby container
engine, and Moby CLI.
Visual C++ redistributable package (VC runtime) msi
You can download one or both of these files ahead of time to the device, then point the installation script at the
directory that contains the files. The installer checks the directory first, and then only downloads components that
aren't found. If all the files are available offline, you can install with no internet connection. You can also use this
feature to install a specific version of the components.
For the latest IoT Edge installation files along with previous versions, see Azure IoT Edge releases.
To install with offline components, use the -OfflineInstallationPath parameter as part of the Deploy-IoTEdge
command and provide the absolute path to the file directory. For example,

. {Invoke-WebRequest -useb https://aka.ms/iotedge-win} | Invoke-Expression; `


Deploy-IoTEdge -OfflineInstallationPath C:\Downloads\iotedgeoffline

You can also use the offline installation path parameter with the Update-IoTEdge command, introduced later in
this article.

Verify successful installation


Check the status of the IoT Edge service. It should be listed as running.

Get-Service iotedge

Examine service logs from the last 5 minutes. If you just finished installing the IoT Edge runtime, you may see a
list of errors from the time between running Deploy-IoTEdge and Initialize-IoTEdge. These errors are
expected, as the service is trying to start before being configured.

. {Invoke-WebRequest -useb https://aka.ms/iotedge-win} | Invoke-Expression; Get-IoTEdgeLog

Run an automated check for the most common configuration and networking errors.

iotedge check

List running modules. After a new installation, the only module you should see running is edgeAgent. After you
deploy IoT Edge modules for the first time, the other system module, edgeHub, will start on the device too.

iotedge list

Manage module containers


The IoT Edge service requires a container engine running on your device. When you deploy a module to a device,
the IoT Edge runtime uses the container engine to pull the container image from a registry in the cloud. The IoT
Edge service enables you to interact with your modules and retrieve logs, but sometimes you may want to use the
container engine to interact with the container itself.
For more information about module concepts, see Understand Azure IoT Edge modules.
If you're running Windows containers on your Windows IoT Edge device, then the IoT Edge installation included
the Moby container engine. The Moby engine was based on the same standards as Docker, and was designed to
run in parallel on the same machine as Docker Desktop. For that reason, if you want to target containers managed
by the Moby engine, you have to specifically target that engine instead of Docker.
For example, to list all Docker images, use the following command:

docker images
To list all Moby images, modify the same command with a pointer to the Moby engine:

docker -H npipe:////./pipe/iotedge_moby_engine images

The engine URI is listed in the output of the installation script, or you can find it in the container runtime settings
section for the config.yaml file.

For more information about commands you can use to interact with containers and images running on your
device, see Docker command-line interfaces.

Update an existing installation


If you've already installed the IoT Edge runtime on a device before and provisioned it with an identity from IoT
Hub, then you can update the runtime without having to reenter your device information.
For more information, see Update the IoT Edge security daemon and runtime.
This example shows an installation that points to an existing configuration file, and uses Windows containers:

. {Invoke-WebRequest -useb https://aka.ms/iotedge-win} | Invoke-Expression; `


Update-IoTEdge

When you update IoT Edge, you can use additional parameters to modify the update, including:
Direct traffic to go through a proxy server, or
Point the installer to an offline directory
Restarting without a prompt if necessary
You can't declare an IoT Edge agent container image with script parameters because that information is already
set in the configuration file from the previous installation. If you want to modify the agent container image, do so
in the config.yaml file.
For more information about these update options, use the command Get-Help Update-IoTEdge -full or refer to all
installation parameters.

Uninstall IoT Edge


If you want to remove the IoT Edge installation from your Windows device, use the following command from an
administrative PowerShell window. This command removes the IoT Edge runtime, along with your existing
configuration and the Moby engine data.
. {Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; `
Uninstall-IoTEdge

The Uninstall-IoTEdge command does not work on Windows IoT Core. To remove IoT Edge from Windows IoT
Core devices, you need to redeploy your Windows IoT Core image.
For more information about uninstallation options, use the command Get-Help Uninstall-IoTEdge -full .

All installation parameters


The previous sections introduced common installation scenarios with examples of how to use parameters to
modify the installation script. This section provides reference tables of the common parameters used to install,
update, or uninstall IoT Edge.
Deploy-IoTEdge
The Deploy-IoTEdge command downloads and deploys the IoT Edge Security Daemon and its dependencies. The
deployment command accepts these common parameters, among others. For the full list, use the command
Get-Help Deploy-IoTEdge -full .

PARAMETER ACCEPTED VALUES COMMENTS

ContainerOs Windows or Linux If no container operating system is


specified, Windows is the default value.

For Windows containers, IoT Edge uses


the moby container engine included in
the installation. For Linux containers,
you need to install a container engine
before starting the installation.

Proxy Proxy URL Include this parameter if your device


needs to go through a proxy server to
reach the internet. For more
information, see Configure an IoT Edge
device to communicate through a
proxy server.

OfflineInstallationPath Directory path If this parameter is included, the


installer will check the listed directory
for the IoT Edge cab and VC Runtime
MSI files required for installation. Any
files not found in the directory are
downloaded. If both files are in the
directory, you can install IoT Edge
without an internet connection. You
can also use this parameter to use a
specific version.

InvokeWebRequestParameters Hashtable of parameters and values During installation, several web


requests are made. Use this field to set
parameters for those web requests.
This parameter is useful to configure
credentials for proxy servers. For more
information, see Configure an IoT Edge
device to communicate through a
proxy server.
PARAMETER ACCEPTED VALUES COMMENTS

RestartIfNeeded none This flag allows the deployment script


to restart the machine without
prompting, if necessary.

Initialize -IoTEdge
The Initialize-IoTEdge command configures IoT Edge with your device connection string and operational details.
Much of the information generated by this command is then stored in the iotedge\config.yaml file. The
initialization command accepts these common parameters, among others. For the full list, use the command
Get-Help Initialize-IoTEdge -full .

PARAMETER ACCEPTED VALUES COMMENTS

Manual None Switch parameter. If no provisioning


type is specified, manual is the default
value.

Declares that you will provide a device


connection string to provision the
device manually

Dps None Switch parameter. If no provisioning


type is specified, manual is the default
value.

Declares that you will provide a Device


Provisioning Service (DPS) scope ID and
your device's Registration ID to
provision through DPS.

DeviceConnectionString A connection string from an IoT Edge Required for manual installation. If you
device registered in an IoT Hub, in don't provide a connection string in the
single quotes script parameters, you will be prompted
for one during installation.

ScopeId A scope ID from an instance of Device Required for DPS installation. If you
Provisioning Service associated with don't provide a scope ID in the script
your IoT Hub. parameters, you will be prompted for
one during installation.

RegistrationId A registration ID generated by your Required for DPS installation if using


device TPM or symmetric key attestation.

SymmetricKey The symmetric key used to provision Required for DPS installation if using
the IoT Edge device identity when using symmetric key attestation.
DPS

ContainerOs Windows or Linux If no container operating system is


specified, Windows is the default value.

For Windows containers, IoT Edge uses


the moby container engine included in
the installation. For Linux containers,
you need to install a container engine
before starting the installation.
PARAMETER ACCEPTED VALUES COMMENTS

InvokeWebRequestParameters Hashtable of parameters and values During installation, several web


requests are made. Use this field to set
parameters for those web requests.
This parameter is useful to configure
credentials for proxy servers. For more
information, see Configure an IoT Edge
device to communicate through a
proxy server.

AgentImage IoT Edge agent image URI By default, a new IoT Edge installation
uses the latest rolling tag for the IoT
Edge agent image. Use this parameter
to set a specific tag for the image
version, or to provide your own agent
image. For more information, see
Understand IoT Edge tags.

Username Container registry username Use this parameter only if you set the -
AgentImage parameter to a container
in a private registry. Provide a
username with access to the registry.

Password Secure password string Use this parameter only if you set the -
AgentImage parameter to a container
in a private registry. Provide the
password to access the registry.

Update -IoTEdge
PARAMETER ACCEPTED VALUES COMMENTS

ContainerOs Windows or Linux If no container OS is specified, Windows


is the default value. For Windows
containers, a container engine will be
included in the installation. For Linux
containers, you need to install a
container engine before starting the
installation.

Proxy Proxy URL Include this parameter if your device


needs to go through a proxy server to
reach the internet. For more
information, see Configure an IoT Edge
device to communicate through a
proxy server.

InvokeWebRequestParameters Hashtable of parameters and values During installation, several web


requests are made. Use this field to set
parameters for those web requests.
This parameter is useful to configure
credentials for proxy servers. For more
information, see Configure an IoT Edge
device to communicate through a
proxy server.
PARAMETER ACCEPTED VALUES COMMENTS

OfflineInstallationPath Directory path If this parameter is included, the


installer will check the listed directory
for the IoT Edge cab and VC Runtime
MSI files required for installation. Any
files not found in the directory are
downloaded. If both files are in the
directory, you can install IoT Edge
without an internet connection. You
can also use this parameter to use a
specific version.

RestartIfNeeded none This flag allows the deployment script


to restart the machine without
prompting, if necessary.

Uninstall-IoTEdge
PARAMETER ACCEPTED VALUES COMMENTS

Force none This flag forces the uninstallation in


case the previous attempt to uninstall
was unsuccessful.

RestartIfNeeded none This flag allows the uninstall script to


restart the machine without prompting,
if necessary.

Next steps
Now that you have an IoT Edge device provisioned with the runtime installed, you can deploy IoT Edge modules.
If you are having problems installing IoT Edge properly, check out the troubleshooting page.
To update an existing installation to the newest version of IoT Edge, see Update the IoT Edge security daemon and
runtime.
Use IoT Edge on Windows to run Linux containers
10/27/2019 • 4 minutes to read • Edit Online

Test IoT Edge modules for Linux devices using a Windows machine.
In a production scenario, Windows devices should only run Windows containers. However, a common
development scenario is to use a Windows computer to build IoT Edge modules for Linux devices. The IoT Edge
runtime for Windows allows you to run Linux containers for testing and development purposes.
This article lists the steps to install the Azure IoT Edge runtime using Linux containers on your Windows x64
(AMD/Intel) system. To learn more about the IoT Edge runtime installer, including details about all the installation
parameters, see Install the Azure IoT Edge runtime on Windows.

Prerequisites
Use this section to review whether your Windows device can support IoT Edge, and to prepare it for a container
engine before installation.
Supported Windows versions
Azure IoT Edge with Linux containers can run on any version of Windows that meets the requirements for Docker
Desktop
For more information about what's included in the latest version of IoT Edge, see Azure IoT Edge releases.
If you want to install IoT Edge on a virtual machine, enable nested virtualization and allocate at least 2-GB
memory. How you enable nested virtualization is different depending on the hypervisor your use. For Hyper-V,
generation 2 virtual machines have nested virtualization enabled by default. For VMWare, there's a toggle to
enable the feature on your virtual machine.
Prepare the container engine
Azure IoT Edge relies on a OCI-compatible container engine. The biggest configuration difference between
running Windows and Linux containers on a Windows machine is that the IoT Edge installation includes a
Windows container runtime, but you need to provide your own runtime for Linux containers before installing IoT
Edge.
To set up a Windows machine to develop and test containers for Linux devices, you can use Docker Desktop as
your container engine. You need to install Docker and configure it to use Linux containers before installing IoT
Edge.
If your IoT Edge device is a Windows computer, check that it meets the system requirements for Hyper-V.

Install IoT Edge on a new device


NOTE
Azure IoT Edge software packages are subject to the license terms located in the packages (in the LICENSE directory). Please
read the license terms prior to using the package. Your installation and use of the package constitutes your acceptance of
these terms. If you do not agree with the license terms, do not use the package.

A PowerShell script downloads and installs the Azure IoT Edge security daemon. The security daemon then starts
the first of two runtime modules, the IoT Edge agent, which enables remote deployments of other modules.
When you install the IoT Edge runtime for the first time on a device, you need to provision the device with an
identity from an IoT hub. A single IoT Edge device can be provisioned manually using a device connections string
provided by your IoT hub. Or, you can use the Device Provisioning Service to automatically provision devices,
which is helpful when you have many devices to set up.
You can read more about the different installation options and parameters in the article Install the Azure IoT Edge
runtime on Windows. Once you have Docker Desktop installed and configured for Linux containers, the main
installation difference is declaring Linux with the -ContainerOs parameter. For example:
1. If you haven't already, register a new IoT Edge device and retrieve the device connection string. Copy the
connection string to use later in this section. You can complete this step using the following tools:
Azure portal
Azure CLI
Visual Studio Code
2. Run PowerShell as an administrator.

NOTE
Use an AMD64 session of PowerShell to install IoT Edge, not PowerShell (x86). If you're not sure which session type
you're using, run the following command:

(Get-Process -Id $PID).StartInfo.EnvironmentVariables["PROCESSOR_ARCHITECTURE"]

3. The Deploy-IoTEdge command checks that your Windows machine is on a supported version, turns on
the containers feature, and then downloads the moby runtime (which is not used for Linux containers) and
the IoT Edge runtime. The command defaults to Windows containers, so declare Linux as the desired
container operating system.

. {Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; `


Deploy-IoTEdge -ContainerOs Linux

4. At this point, IoT Core devices may restart automatically. Other Windows 10 or Windows Server devices
may prompt you to restart. If so, restart your device now. Once your device is ready, run PowerShell as an
administrator again.
5. The Initialize-IoTEdge command configures the IoT Edge runtime on your machine. The command
defaults to manual provisioning with a device connection string. Declare Linux as the desired container
operating system again.

. {Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; `


Initialize-IoTEdge -ContainerOs Linux

6. When prompted, provide the device connection string that you retrieved in step 1. The device connection
string associates the physical device with a device ID in IoT Hub.
The device connection string takes the following format, and should not include quotation marks:
HostName={IoT hub name}.azure-devices.net;DeviceId={device name};SharedAccessKey={key}

Verify successful installation


Check the status of the IoT Edge service:
Get-Service iotedge

Examine service logs from the last 5 minutes:

. {Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; Get-IoTEdgeLog

Run an automated check for the most common configuration and networking errors:

iotedge check

List running modules. After a new installation, the only module you should see running is edgeAgent. After you
deploy IoT Edge modules for the first time, the other system module, edgeHub, will start on the device too.

iotedge list

Next steps
Now that you have an IoT Edge device provisioned with the runtime installed, you can deploy IoT Edge modules.
If you are having problems installing IoT Edge properly, check out the troubleshooting page.
To update an existing installation to the newest version of IoT Edge, see Update the IoT Edge security daemon and
runtime.
Run Azure IoT Edge on Windows Server Virtual
Machines
10/27/2019 • 3 minutes to read • Edit Online

The Azure IoT Edge runtime is what turns a device into an IoT Edge device. The runtime can be deployed on
devices as small as a Raspberry Pi or as large as an industrial server. Once a device is configured with the IoT Edge
runtime, you can start deploying business logic to it from the cloud.
To learn more about how the IoT Edge runtime works and what components are included, see Understand the
Azure IoT Edge runtime and its architecture.
This article lists the steps to run the Azure IoT Edge runtime on a Windows Server 2019 virtual machine using the
Windows Server Azure Marketplace offer. Follow the instructions at Install the Azure IoT Edge runtime on
Windows for use with other versions.

Deploy from the Azure Marketplace


1. Navigate to the Windows Server Azure Marketplace offer or by searching “Windows Server” on Azure
Marketplace
2. Select GET IT NOW
3. In Software plan, find "Windows Server 2019 Datacenter Server Core with Containers" and then select
Continue on the next dialog.
You can also use these instructions for other versions of Windows Server with Containers
4. Once in the Azure portal, select Create and follow the wizard to deploy the VM.
If it’s your first time trying out a VM, it’s easiest to use a password and to enable RDP and SSH in the
public inbound port menu.
If you have a resource intensive workload, you should upgrade the virtual machine size by adding more
CPUs and/or memory.
5. Once the virtual machine is deployed, configure it to connect to your IoT Hub:
a. Copy your device connection string from your IoT Edge device created in your IoT Hub. See the
procedure Retrieve the connection string in the Azure portal.
b. Select your newly created virtual machine resource from the Azure portal and open the run command
option
c. Select the RunPowerShellScript option
d. Copy this script into the command window with your device connection string:

. {Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; `


Install-IoTEdge -Manual -DeviceConnectionString '<connection-string>'

e. Execute the script to install the IoT Edge runtime and set your connection string by selecting Run
f. After a minute or two, you should see a message that the Edge runtime was installed and provisioned
successfully.

Deploy from the Azure portal


1. From the Azure portal, search for “Windows Server” and select Windows Server 2019 Datacenter to begin
the VM creation workflow.
2. From Select a software plan choose "Windows Server 2019 Datacenter Server Core with Containers", then
select Create
3. Complete step 5 in the "Deploy from the Azure Marketplace" instructions above.

Deploy from Azure CLI


1. If you’re using Azure CLI on your desktop, start by logging in:

az login

2. If you have multiple subscriptions, select the subscription you’d like to use:
a. List your subscriptions:

az account list --output table

b. Copy the SubscriptionID field for the subscription you’d like to use
c. Run this command with the ID you copied:

az account set -s {SubscriptionId}

3. Create a new resource group (or specify an existing one in the next steps):

az group create --name IoTEdgeResources --location westus2

4. Create a new virtual machine:

az vm create -g IoTEdgeResources -n EdgeVM --image MicrosoftWindowsServer:WindowsServer:2019-Datacenter-


Core-with-Containers:latest --admin-username azureuser --generate-ssh-keys --size Standard_DS1_v2

This command will prompt you for a password, but you can add the option --admin-password to set it
more easily in a script
The Windows Server Core image has command line support only with remote desktop, so if you'd like
the full desktop experience, specify
MicrosoftWindowsServer:WindowsServer:2019-Datacenter-with-Containers:latest as the image

5. Set the device connection string (You can follow the Retrieve the connection string with Azure CLI
procedure if you’re not familiar with this process):

az vm run-command invoke -g IoTEdgeResources -n EdgeVM --command-id RunPowerShellScript --script ".


{Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; `Install-IoTEdge -Manual -
DeviceConnectionString '<connection-string>'"

Next steps
Now that you have an IoT Edge device provisioned with the runtime installed, you can deploy IoT Edge modules.
If you're having problems with the Edge runtime installing properly, check out the troubleshooting page.
To update an existing installation to the newest version of IoT Edge, see Update the IoT Edge security daemon and
runtime.
Learn more about using Windows virtual machines at the Windows Virtual Machines documentation.
If you want to SSH into this VM after setup, follow the Installation of OpenSSH for Windows Server guide using
remote desktop or remote powershell.
Run Azure IoT Edge on Ubuntu Virtual Machines
10/30/2019 • 3 minutes to read • Edit Online

The Azure IoT Edge runtime is what turns a device into an IoT Edge device. The runtime can be deployed on
devices as small as a Raspberry Pi or as large as an industrial server. Once a device is configured with the IoT Edge
runtime, you can start deploying business logic to it from the cloud.
To learn more about how the IoT Edge runtime works and what components are included, see Understand the
Azure IoT Edge runtime and its architecture.
This article lists the steps to run the Azure IoT Edge runtime on an Ubuntu 16.04 Virtual Machine using the
preconfigured Azure IoT Edge on Ubuntu Azure Marketplace offer.
On first boot, the Azure IoT Edge on Ubuntu VM preinstalls the latest version of the Azure IoT Edge runtime. It
also includes a script to set the connection string and then restart the runtime, which can be triggered remotely
through the Azure VM portal or Azure command line, allowing you to easily configure and connect the IoT Edge
device without starting an SSH or remote desktop session. This script will wait to set the connection string until the
IoT Edge client is fully installed so that you don’t have to build that into your automation.

Deploy from the Azure Marketplace


1. Navigate to the Azure IoT Edge on Ubuntu Marketplace offer or by searching “Azure IoT Edge on Ubuntu” on
the Azure Marketplace
2. Select GET IT NOW and then Continue on the next dialog.
3. Once in the Azure portal, select Create and follow the wizard to deploy the VM.
If it’s your first time trying out a VM, it’s easiest to use a password and to enable the SSH in the public
inbound port menu.
If you have a resource intensive workload, you should upgrade the virtual machine size by adding more
CPUs and/or memory.
4. Once the virtual machine is deployed, configure it to connect to your IoT Hub:
a. Copy your device connection string from your IoT Edge device created in your IoT Hub (You can follow
the Retrieve the connection string in the Azure portal procedure if you aren’t familiar with this process)
b. Select your newly created virtual machine resource from the Azure portal and open the run command
option
c. Select the RunShellScript option
d. Execute the script below via the command window with your device connection string:
/etc/iotedge/configedge.sh "{device_connection_string}"
e. Select Run
f. Wait a few moments, and the screen should then provide a success message indicating the connection
string was set successfully.

Deploy from the Azure portal


From the Azure portal, search for “Azure IoT Edge” and select Ubuntu Server 16.04 LTS + Azure IoT Edge
runtime to begin the VM creation workflow. From there, complete steps 3 and 4 in the "Deploy from the Azure
Marketplace" instructions above.

Deploy from Azure CLI


1. If you’re using Azure CLI on your desktop, start by logging in:

az login

2. If you have multiple subscriptions, select the subscription you’d like to use:
a. List your subscriptions:

az account list --output table

b. Copy the SubscriptionID field for the subscription you’d like to use.
c. Set your working subscription with the ID that you just copied:

az account set -s {SubscriptionId}

3. Create a new resource group (or specify an existing one in the next steps):

az group create --name IoTEdgeResources --location westus2

4. Accept the terms of use for the virtual machine. If you want to review the terms first, follow the steps in
Deploy from the Azure Marketplace.

az vm image accept-terms --urn microsoft_iot_edge:iot_edge_vm_ubuntu:ubuntu_1604_edgeruntimeonly:latest

5. Create a new virtual machine:

az vm create --resource-group IoTEdgeResources --name EdgeVM --image


microsoft_iot_edge:iot_edge_vm_ubuntu:ubuntu_1604_edgeruntimeonly:latest --admin-username azureuser --
generate-ssh-keys

6. Set the device connection string (You can follow the Retrieve the connection string with the Azure CLI
procedure if you’re not familiar with this process):

az vm run-command invoke -g IoTEdgeResources -n EdgeVM --command-id RunShellScript --script


"/etc/iotedge/configedge.sh '{device_connection_string}'"

If you want to SSH into this VM after setup, use the publicIpAddress with the command:
ssh azureuser@{publicIpAddress}

Next steps
Now that you have an IoT Edge device provisioned with the runtime installed, you can deploy IoT Edge modules.
If you are having problems with the IoT Edge runtime installing properly, check out the troubleshooting page.
To update an existing installation to the newest version of IoT Edge, see Update the IoT Edge security daemon and
runtime.
If you'd like to open up ports to access the VM through SSH or other inbound connections, refer to the Azure
Virtual Machine documentation on opening up ports and endpoints to a Linux VM
How to install IoT Edge on Kubernetes (Preview)
11/24/2019 • 2 minutes to read • Edit Online

IoT Edge can integrate with Kubernetes using it as a resilient, highly available infrastructure layer. It registers an IoT
Edge Custom Resource Definition (CRD ) with the Kubernetes API Server. Additionally, it provides an Operator (IoT
Edge agent) that reconciles cloud-managed desired state with the local cluster state.
Module lifetime is managed by the Kubernetes scheduler, which maintains module availability and chooses their
placement. IoT Edge manages the edge application platform running on top, continuously reconciling the desired
state specified in IoT Hub with the state on the edge cluster. The edge application model is still the familiar model
based on IoT Edge modules and routes. The IoT Edge agent operator performs automatic translation to the
Kubernetes natives constructs like pods, deployments, services etc.
Here is a high-level architecture diagram:

Every component of the edge deployment is scoped to a Kubernetes namespace specific to the device, making it
possible to share the same cluster resources among multiple edge devices and their deployments.

NOTE
IoT Edge on Kubernetes is in public preview.

Install locally for a quick test environment


Prerequisites
Kubernetes 1.10 or newer. If you don't have an existing cluster setup, you can use Minikube for a local
cluster environment.
Helm, the Kubernetes package manager.
kubectl for viewing and interacting with the cluster.
Setup steps
1. Start Minikube

minikube start

2. Initialize the Helm server component ( tiller) in your cluster

helm init

3. Add IoT Edge repo and update the helm installation

helm repo add edgek8s https://edgek8s.blob.core.windows.net/helm/


helm repo update

4. Create an IoT Hub, register an IoT Edge device, and note its connection string.
5. Install iotedged and IoT Edge agent into your cluster

helm install \
--name k8s-edge1 \
--set "deviceConnectionString=replace-with-device-connection-string" \
edgek8s/edge-kubernetes

6. Open the Kubernetes dashboard in the browser

minikube dashboard

Under the cluster namespaces, you will see one for the IoT Edge device following the convention msiot-
<iothub -name>-<edgedevice-name>. The IoT Edge agent and iotedged pods should be up and running in
this namespace.
7. Add a simulated temperature sensor module using the steps in the Deploy a module section of the
quickstart. IoT Edge module management is done from the IoT Hub portal just like any other IoT Edge
device. Making local changes to module configuration via Kubernetes tools is not recommended as they
might get overwritten.
8. In a few seconds, refreshing the Pods page under the edge device namespace in the dashboard will list the
IoT Edge hub and simulated sensor pods as running with the IoT Edge hub pod ingesting data into IoT Hub.

Clean up resources
To remove all resources created by the edge deployment, use the following command with the name used in step 5
of the previous section.

helm delete --purge k8s-edge1

Next steps
Deploy as a highly available edge gateway
The edge device in a Kubernetes cluster can be used as an IoT gateway for downstream devices. It can be
configured to be resilient to node failure thus providing high availability to edge deployments. See this detailed
walkthrough to use IoT Edge in this scenario.
Update the IoT Edge security daemon and runtime
11/24/2019 • 5 minutes to read • Edit Online

As the IoT Edge service releases new versions, you'll want to update your IoT Edge devices for the latest features
and security improvements. This article provides information about how to update your IoT Edge devices when a
new version is available.
Two components of an IoT Edge device need to be updated if you want to move to a newer version. The first is
the security daemon, which runs on the device and starts the runtime modules when the device starts. Currently,
the security daemon can only be updated from the device itself. The second component is the runtime, made up
of the IoT Edge hub and IoT Edge agent modules. Depending on how you structure your deployment, the
runtime can be updated from the device or remotely.
To find the latest version of Azure IoT Edge, see Azure IoT Edge releases.

Update the security daemon


The IoT Edge security daemon is a native component that needs to be updated using the package manager on
the IoT Edge device.
Check the version of the security daemon running on your device by using the command iotedge version .
Linux devices
On Linux x64 devices, use apt-get or your appropriate package manager to update the security daemon.

apt-get update
apt-get install libiothsm iotedge

On Linux ARM32 devices, use the steps in Install Azure IoT Edge runtime on Linux (ARM32v7/armhf) to install
the latest version of the security daemon.
Windows devices
On Windows devices, use the PowerShell script to update the security daemon. The script automatically pulls the
latest version of the security daemon.

. {Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; Update-IoTEdge -ContainerOs <Windows or


Linux>

Running the Update-IoTEdge command removes the security daemon from your device, along with the two
runtime container images. The config.yaml file is kept on the device, as well as data from the Moby container
engine (if you're using Windows containers). Keeping the configuration information means that you don't have to
provide the connection string or Device Provisioning Service information for your device again during the update
process.
If you want to install a specific version of the security daemon, download the appropriate Microsoft-Azure-
IoTEdge.cab file from IoT Edge releases. Then, use the -OfflineInstallationPath parameter to point to the file
location. For more information, see Offline installation.

Update the runtime containers


The way that you update the IoT Edge agent and IoT Edge hub containers depends on whether you use rolling
tags (like 1.0) or specific tags (like 1.0.7) in your deployment.
Check the version of the IoT Edge agent and IoT Edge hub modules currently on your device using the
commands iotedge logs edgeAgent or iotedge logs edgeHub .

Understand IoT Edge tags


The IoT Edge agent and IoT Edge hub images are tagged with the IoT Edge version that they are associated with.
There are two different ways to use tags with the runtime images:
Rolling tags - Use only the first two values of the version number to get the latest image that matches those
digits. For example, 1.0 is updated whenever there's a new release to point to the latest 1.0.x version. If the
container runtime on your IoT Edge device pulls the image again, the runtime modules are updated to the
latest version. This approach is suggested for development purposes. Deployments from the Azure portal
default to rolling tags.
Specific tags - Use all three values of the version number to explicitly set the image version. For example,
1.0.7 won't change after its initial release. You can declare a new version number in the deployment manifest
when you're ready to update. This approach is suggested for production purposes.
Update a rolling tag image
If you use rolling tags in your deployment (for example, mcr.microsoft.com/azureiotedge-hub:1.0) then you need
to force the container runtime on your device to pull the latest version of the image.
Delete the local version of the image from your IoT Edge device. On Windows machines, uninstalling the security
daemon also removes the runtime images, so you don't need to take this step again.

docker rmi mcr.microsoft.com/azureiotedge-hub:1.0


docker rmi mcr.microsoft.com/azureiotedge-agent:1.0

You may need to use the force -f flag to remove the images.
The IoT Edge service will pull the latest versions of the runtime images and automatically start them on your
device again.
Update a specific tag image
If you use specific tags in your deployment (for example, mcr.microsoft.com/azureiotedge-hub:1.0.7) then all you
need to do is update the tag in your deployment manifest and apply the changes to your device.
In the Azure portal, the runtime deployment images are declared in the Configure advanced Edge Runtime
settings section.
In a JSON deployment manifest, update the module images in the systemModules section.

"systemModules": {
"edgeAgent": {
"type": "docker",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-agent:1.0.7",
"createOptions": ""
}
},
"edgeHub": {
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-hub:1.0.7",
"createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],
\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}"
}
}
},

Update to a release candidate version


Azure IoT Edge regularly releases new versions of the IoT Edge service. Before each stable release, there is one
or more release candidate (RC ) versions. RC versions include all the planned features for the release, but are still
going through the testing and validation processes required for a stable release. If you want to test a new feature
early, you can install the RC version and provide feedback through GitHub.
Release candidate versions follow the same numbering convention of releases, but have -rc plus an incremental
number appended to the end. You can see the release candidates in the same list of Azure IoT Edge releases as
the stable versions. For example, find 1.0.7-rc1 and 1.0.7-rc2, the two release candidates that came before 1.0.7.
You can also see that RC versions are marked with pre-release labels.
As previews, release candidate versions aren't included as the latest version that the regular installers target.
Instead, you need to manually target the assets for the RC version that you want to test. Depending on your IoT
Edge device operating system, use the following sections to update IoT Edge to a specific version:
Linux
Windows

Next steps
View the latest Azure IoT Edge releases.
Stay up-to-date with recent updates and announcement in the Internet of Things blog
Create and provision an IoT Edge device with a
virtual TPM on a Linux virtual machine
12/1/2019 • 9 minutes to read • Edit Online

Azure IoT Edge devices can be automatically provisioned using the Device Provisioning Service. If you're
unfamiliar with the process of auto-provisioning, review the auto-provisioning concepts before continuing.
This article shows you how to test auto-provisioning on a simulated IoT Edge device with the following steps:
Create a Linux virtual machine (VM ) in Hyper-V with a simulated Trusted Platform Module (TPM ) for hardware
security.
Create an instance of IoT Hub Device Provisioning Service (DPS ).
Create an individual enrollment for the device
Install the IoT Edge runtime and connect the device to IoT Hub

NOTE
TPM 2.0 is required when using TPM attestation with DPS and can only be used to create individual, not group, enrollments.

TIP
This article describes how to test DPS provisioning using a TPM simulator, but much of it applies to physical TPM hardware
such as the Infineon OPTIGA™ TPM, an Azure Certified for IoT device.
If you're using a physical device, you can skip ahead to the Retrieve provisioning information from a physical device section in
this article.

Prerequisites
A Windows development machine with Hyper-V enabled. This article uses Windows 10 running an Ubuntu
Server VM.
An active IoT Hub.
If using a simulated TPM, Visual Studio 2015 or later with the 'Desktop development with C++' workload
enabled.

Create a Linux virtual machine with a virtual TPM


In this section, you create a new Linux virtual machine on Hyper-V. You configured this virtual machine with a
simulated TPM so that you can use it for testing how automatic provisioning works with IoT Edge.
Create a virtual switch
A virtual switch enables your virtual machine to connect to a physical network.
1. Open Hyper-V Manager on your Windows machine.
2. In the Actions menu, select Virtual Switch Manager.
3. Choose an External virtual switch, then select Create Virtual Switch.
4. Give your new virtual switch a name, for example EdgeSwitch. Make sure that the connection type is set to
External network, then select Ok.
5. A pop-up warns you that network connectivity may be disrupted. Select Yes to continue.
If you see errors while creating the new virtual switch, ensure that no other switches are using the ethernet
adaptor, and that no other switches use the same name.
Create virtual machine
1. Download a disk image file to use for your virtual machine and save it locally. For example, Ubuntu server.
2. In Hyper-V Manager again, select New > Virtual Machine in the Actions menu.
3. Complete the New Virtual Machine Wizard with the following specific configurations:
a. Specify Generation: Select Generation 2. Generation 2 virtual machines have nested virtualization
enabled, which is required to run IoT Edge on a virtual machine.
b. Configure Networking: Set the value of Connection to the virtual switch that you created in the
previous section.
c. Installation Options: Select Install an operating system from a bootable image file and browse to
the disk image file that you saved locally.
4. Select Finish in the wizard to create the virtual machine.
It may take a few minutes to create the new VM.
Enable virtual TPM
Once your VM is created, open its settings to enable the virtual trusted platform module (TPM ) that lets you auto-
provision the device.
1. Select the virtual machine, then open its Settings.
2. Navigate to Security.
3. Uncheck Enable Secure Boot.
4. Check Enable Trusted Platform Module.
5. Click OK.
Start the virtual machine and collect TPM data
In the virtual machine, build a tool that you can use to retrieve the device's Registration ID and Endorsement
key.
1. Start your virtual machine and connect to it.
2. Follow the prompts within the virtual machine to finish the installation process and reboot the machine.
3. Sign in to your VM, then follow the steps in Set up a Linux development environment to install and build
the Azure IoT device SDK for C.

TIP
In the course of this article, you'll copy to and paste from the virtual machine, which is not easy through the Hyper-V
Manager connection application. You may want to connect to the virtual machine through Hyper-V Manager once
to retrieve its IP address: ifconfig . Then, you can use the IP address to connect through SSH:
ssh <username>@<ipaddress> .

4. Run the following commands to build the SDK tool that retrieves your device provisioning information
from the TPM simulator.
cd azure-iot-sdk-c/cmake
cmake -Duse_prov_client:BOOL=ON -Duse_tpm_simulator:BOOL=ON ..
cd provisioning_client/tools/tpm_device_provision
make
sudo ./tpm_device_provision

5. From a command window, navigate to the azure-iot-sdk-c directory and run the TPM simulator. It listens
over a socket on ports 2321 and 2322. Do not close this command window; you will need to keep this
simulator running.
From the azure-iot-sdk-c directory, run the following command to start the simulator:

./provisioning_client/deps/utpm/tools/tpm_simulator/Simulator.exe

6. Using Visual Studio, open the solution generated in the cmake directory named azure_iot_sdks.sln , and
build it using the Build solution command on the Build menu.
7. In the Solution Explorer pane in Visual Studio, navigate to the folder Provision_Tools. Right-click the
tpm_device_provision project and select Set as Startup Project.
8. Run the solution using either of the Start commands on the Debug menu. The output window displays the
TPM simulator's Registration ID and the Endorsement key, which you should copy for use later when
you create an individual enrollment for your device in You can close this window (with Registration ID and
Endorsement key), but leave the TPM simulator window running.

Retrieve provisioning information from a physical device


On your device, build a tool that you can use to retrieve the device's provisioning information.
1. Follow the steps in Set up a Linux development environment to install and build the Azure IoT device SDK
for C.
2. Run the following commands to build the SDK tool that retrieves your device provisioning information
from the TPM device.

cd azure-iot-sdk-c/cmake
cmake -Duse_prov_client:BOOL=ON ..
cd provisioning_client/tools/tpm_device_provision
make
sudo ./tpm_device_provision

3. Copy the values for Registration ID and Endorsement key. You use these values to create an individual
enrollment for your device in DPS.

Set up the IoT Hub Device Provisioning Service


Create a new instance of the IoT Hub Device Provisioning Service in Azure, and link it to your IoT hub. You can
follow the instructions in Set up the IoT Hub DPS.
After you have the Device Provisioning Service running, copy the value of ID Scope from the overview page. You
use this value when you configure the IoT Edge runtime.

Create a DPS enrollment


Retrieve the provisioning information from your virtual machine, and use that to create an individual enrollment in
Device Provisioning Service.
When you create an enrollment in DPS, you have the opportunity to declare an Initial Device Twin State. In the
device twin, you can set tags to group devices by any metric you need in your solution, like region, environment,
location, or device type. These tags are used to create automatic deployments.
1. In the Azure portal, navigate to your instance of IoT Hub Device Provisioning Service.
2. Under Settings, select Manage enrollments.
3. Select Add individual enrollment then complete the following steps to configure the enrollment:
a. For Mechanism, select TPM.
b. Provide the Endorsement key and Registration ID that you copied from your virtual machine.

TIP
If you're using a physical TPM device, you need to determine the Endorsement key, which is unique to each
TPM chip and is obtained from the TPM chip manufacturer associated with it. You can derive a unique
Registration ID for your TPM device by, for example, creating an SHA-256 hash of the endorsement key.

c. Select True to declare that this virtual machine is an IoT Edge device.
d. Choose the linked IoT Hub that you want to connect your device to. You can choose multiple hubs,
and the device will be assigned to one of them according to the selected allocation policy.
e. Provide an ID for your device if you'd like. You can use device IDs to target an individual device for
module deployment. If you don't provide a device ID, the registration ID is used.
f. Add a tag value to the Initial Device Twin State if you'd like. You can use tags to target groups of
devices for module deployment. For example:

{
"tags": {
"environment": "test"
},
"properties": {
"desired": {}
}
}

g. Select Save.
Now that an enrollment exists for this device, the IoT Edge runtime can automatically provision the device during
installation.

Install the IoT Edge runtime


The IoT Edge runtime is deployed on all IoT Edge devices. Its components run in containers, and allow you to
deploy additional containers to the device so that you can run code at the edge. Install the IoT Edge runtime on
your virtual machine.
Know your DPS ID Scope and device Registration ID before beginning the article that matches your device
type. If you installed the example Ubuntu server, use the x64 instructions. Make sure to configure the IoT Edge
runtime for automatic, not manual, provisioning.
Install the Azure IoT Edge runtime on Linux
Give IoT Edge access to the TPM
In order for the IoT Edge runtime to automatically provision your device, it needs access to the TPM.
You can give TPM access to the IoT Edge runtime by overriding the systemd settings so that the iotedge service
has root privileges. If you don't want to elevate the service privileges, you can also use the following steps to
manually provide TPM access.
1. Find the file path to the TPM hardware module on your device and save it as a local variable.

tpm=$(sudo find /sys -name dev -print | fgrep tpm | sed 's/.\{4\}$//')

2. Create a new rule that will give the IoT Edge runtime access to tpm0.

sudo touch /etc/udev/rules.d/tpmaccess.rules

3. Open the rules file.

sudo nano /etc/udev/rules.d/tpmaccess.rules

4. Copy the following access information into the rules file.

# allow iotedge access to tpm0


KERNEL=="tpm0", SUBSYSTEM=="tpm", GROUP="iotedge", MODE="0660"

5. Save and exit the file.


6. Trigger the udev system to evaluate the new rule.

/bin/udevadm trigger $tpm

7. Verify that the rule was successfully applied.

ls -l /dev/tpm0

Successful output looks like the following:

crw-rw---- 1 root iotedge 10, 224 Jul 20 16:27 /dev/tpm0

If you don't see that the correct permissions have been applied, try rebooting your machine to refresh udev.

Restart the IoT Edge runtime


Restart the IoT Edge runtime so that it picks up all the configuration changes that you made on the device.

sudo systemctl restart iotedge

Check to see that the IoT Edge runtime is running.

sudo systemctl status iotedge


If you see provisioning errors, it may be that the configuration changes haven't taken effect yet. Try restarting the
IoT Edge daemon again.

sudo systemctl daemon-reload

Or, try restarting your virtual machine to see if the changes take effect on a fresh start.

Verify successful installation


If the runtime started successfully, you can go into your IoT Hub and see that your new device was automatically
provisioned. Now your device is ready to run IoT Edge modules.
Check the status of the IoT Edge Daemon.

systemctl status iotedge

Examine daemon logs.

journalctl -u iotedge --no-pager --no-full

List running modules.

iotedge list

You can verify that the individual enrollment that you created in Device Provisioning Service was used. Navigate to
your Device Provisioning Service instance in the Azure portal. Open the enrollment details for the individual
enrollment that you created. Notice that the status of the enrollment is assigned and the device ID is listed.

Next steps
The Device Provisioning Service enrollment process lets you set the device ID and device twin tags at the same
time as you provision the new device. You can use those values to target individual devices or groups of devices
using automatic device management. Learn how to Deploy and monitor IoT Edge modules at scale using the
Azure portal or using Azure CLI.
Create and provision a simulated IoT Edge device
with a virtual TPM on Windows
11/24/2019 • 4 minutes to read • Edit Online

Azure IoT Edge devices can be auto-provisioned using the Device Provisioning Service just like devices that are
not edge-enabled. If you're unfamiliar with the process of auto-provisioning, review the auto-provisioning
concepts before continuing.
DPS supports symmetric key attestation for IoT Edge devices in both individual enrollment and group enrollment.
For group enrollment, if you check “is IoT Edge device” option to be true in symmetric key attestation, all the
devices that are registered under that enrollment group will be marked as IoT Edge devices.
This article shows you how to test auto-provisioning on a simulated IoT Edge device with the following steps:
Create an instance of IoT Hub Device Provisioning Service (DPS ).
Create a simulated device on your Windows machine with a simulated Trusted Platform Module (TPM ) for
hardware security.
Create an individual enrollment for the device.
Install the IoT Edge runtime and connect the device to IoT Hub.

NOTE
TPM 2.0 is required when using TPM attestation with DPS and can only be used to create individual, not group, enrollments.

TIP
This article describes testing auto-provisioning by using TPM attestation on virtual devices, but much of it applies when
using physical TPM hardware as well.

Prerequisites
A Windows development machine. This article uses Windows 10.
An active IoT Hub.

Set up the IoT Hub Device Provisioning Service


Create a new instance of the IoT Hub Device Provisioning Service in Azure, and link it to your IoT hub. You can
follow the instructions in Set up the IoT Hub DPS.
After you have the Device Provisioning Service running, copy the value of ID Scope from the overview page. You
use this value when you configure the IoT Edge runtime.
TIP
If you're using a physical TPM device, you need to determine the Endorsement key, which is unique to each TPM chip and
is obtained from the TPM chip manufacturer associated with it. You can derive a unique Registration ID for your TPM device
by, for example, creating an SHA-256 hash of the endorsement key.
Follow the instructions in the article How to manage device enrollments with Azure Portal to create your enrollment in DPS
and then proceed with the Install the IoT Edge runtime section in this article to continue.

Simulate a TPM device


Create a simulated TPM device on your Windows development machine. Retrieve the Registration ID and
Endorsement key for your device, and use them to create an individual enrollment entry in DPS.
When you create an enrollment in DPS, you have the opportunity to declare an Initial Device Twin State. In the
device twin you can set tags to group devices by any metric you need in your solution, like region, environment,
location, or device type. These tags are used to create automatic deployments.
Choose the SDK language that you want to use to create the simulated device, and follow the steps until you
create the individual enrollment.
When you create the individual enrollment, select True to declare that the simulated TPM device on your
Windows development machine is an IoT Edge device.
Simulated device and individual enrollment guides:
C
Java
C#
Node.js
Python
After creating the individual enrollment, save the value of the Registration ID. You use this value when you
configure the IoT Edge runtime.

Install the IoT Edge runtime


The IoT Edge runtime is deployed on all IoT Edge devices. Its components run in containers, and allow you to
deploy additional containers to the device so that you can run code at the edge.
You'll need the following information when provisioning your device:
The DPS ID Scope value
The device Registration ID you created
Install the IoT Edge runtime on the device that is running the simulated TPM. You'll configure the IoT Edge
runtime for automatic, not manual, provisioning.

TIP
Keep the window that's running the TPM simulator open during your installation and testing.

For more detailed information about installing IoT Edge on Windows, including prerequisites and instructions for
tasks like managing containers and updating IoT Edge, see Install the Azure IoT Edge runtime on Windows.
1. Open a PowerShell window in administrator mode. Be sure to use an AMD64 session of PowerShell when
installing IoT Edge, not PowerShell (x86).
2. The Deploy-IoTEdge command checks that your Windows machine is on a supported version, turns on
the containers feature, and then downloads the moby runtime and the IoT Edge runtime. The command
defaults to using Windows containers.

. {Invoke-WebRequest -useb https://aka.ms/iotedge-win} | Invoke-Expression; `


Deploy-IoTEdge

3. At this point, IoT Core devices may restart automatically. Other Windows 10 or Windows Server devices
may prompt you to restart. If so, restart your device now. Once your device is ready, run PowerShell as an
administrator again.
4. The Initialize-IoTEdge command configures the IoT Edge runtime on your machine. The command
defaults to manual provisioning with Windows containers. Use the -Dps flag to use the Device
Provisioning Service instead of manual provisioning.
Replace the placeholder values for {scope_id} and {registration_id} with the data you collected earlier.

. {Invoke-WebRequest -useb https://aka.ms/iotedge-win} | Invoke-Expression; `


Initialize-IoTEdge -Dps -ScopeId {scope ID} -RegistrationId {registration ID}

Verify successful installation


If the runtime started successfully, you can go into your IoT Hub and start deploying IoT Edge modules to your
device. Use the following commands on your device to verify that the runtime installed and started successfully.
Check the status of the IoT Edge service.

Get-Service iotedge

Examine service logs from the last 5 minutes.

. {Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; Get-IoTEdgeLog

List running modules.

iotedge list

Next steps
The Device Provisioning Service enrollment process lets you set the device ID and device twin tags at the same
time as you provision the new device. You can use those values to target individual devices or groups of devices
using automatic device management. Learn how to Deploy and monitor IoT Edge modules at scale using the
Azure portal or using Azure CLI
Create and provision an IoT Edge device using
symmetric key attestation
12/1/2019 • 7 minutes to read • Edit Online

Azure IoT Edge devices can be auto-provisioned using the Device Provisioning Service just like devices that are
not edge-enabled. If you're unfamiliar with the process of auto-provisioning, review the auto-provisioning concepts
before continuing.
This article shows you how to create a Device Provisioning Service individual enrollment using symmetric key
attestation on an IoT Edge device with the following steps:
Create an instance of IoT Hub Device Provisioning Service (DPS ).
Create an individual enrollment for the device.
Install the IoT Edge runtime and connect to the IoT Hub.
Symmetric key attestation is a simple approach to authenticating a device with a Device Provisioning Service
instance. This attestation method represents a "Hello world" experience for developers who are new to device
provisioning, or do not have strict security requirements. Device attestation using a TPM or X.509 certificates is
more secure, and should be used for more stringent security requirements.

Prerequisites
An active IoT Hub
A physical or virtual device

Set up the IoT Hub Device Provisioning Service


Create a new instance of the IoT Hub Device Provisioning Service in Azure, and link it to your IoT hub. You can
follow the instructions in Set up the IoT Hub DPS.
After you have the Device Provisioning Service running, copy the value of ID Scope from the overview page. You
use this value when you configure the IoT Edge runtime.

Choose a unique registration ID for the device


A unique registration ID must be defined to identify each device. You can use the MAC address, serial number, or
any unique information from the device.
In this example, we use a combination of a MAC address and serial number forming the following string for a
registration ID.

sn-007-888-abc-mac-a1-b2-c3-d4-e5-f6

Create a unique registration ID for your device. Valid characters are lowercase alphanumeric and dash ('-').

Create a DPS enrollment


Use your device's registration ID to create an individual enrollment in DPS.
When you create an enrollment in DPS, you have the opportunity to declare an Initial Device Twin State. In the
device twin, you can set tags to group devices by any metric you need in your solution, like region, environment,
location, or device type. These tags are used to create automatic deployments.

TIP
Group enrollments are also possible when using symmetric key attestation and involve the same decisions as individual
enrollments.

1. In the Azure portal, navigate to your instance of IoT Hub Device Provisioning Service.
2. Under Settings, select Manage enrollments.
3. Select Add individual enrollment then complete the following steps to configure the enrollment:
a. For Mechanism, select Symmetric Key.
b. Select the Auto-generate keys check box.
c. Provide the Registration ID that you created for your device.
d. Provide an IoT Hub Device ID for your device if you'd like. You can use device IDs to target an
individual device for module deployment. If you don't provide a device ID, the registration ID is used.
e. Select True to declare that the enrollment is for an IoT Edge device. For a group enrollment, all
devices must be IoT Edge devices or none of them can be.
f. Accept the default value from the Device Provisioning Service's allocation policy for how you want
to assign devices to hubs or choose a different value that is specific to this enrollment.
g. Choose the linked IoT Hub that you want to connect your device to. You can choose multiple hubs,
and the device will be assigned to one of them according to the selected allocation policy.
h. Choose how you want device data to be handled on re-provisioning when devices request
provisioning after the first time.
i. Add a tag value to the Initial Device Twin State if you'd like. You can use tags to target groups of
devices for module deployment. For example:

{
"tags": {
"environment": "test"
},
"properties": {
"desired": {}
}
}

j. Ensure Enable entry is set to Enable.


k. Select Save.
Now that an enrollment exists for this device, the IoT Edge runtime can automatically provision the device during
installation. Be sure to copy your enrollment's Primary Key value to use when installing the IoT Edge runtime, or
if you're going to be creating device keys for use with a group enrollment.

Derive a device key


NOTE
This section is required only if using a group enrollment.

Each device uses its derived device key with your unique registration ID to perform symmetric key attestation with
the enrollment during provisioning. To generate the device key, use the key you copied from your DPS enrollment
to compute an HMAC -SHA256 of the unique registration ID for the device and convert the result into Base64
format.
Do not include your enrollment's primary or secondary key in your device code.
Linux workstations
If you are using a Linux workstation, you can use openssl to generate your derived device key as shown in the
following example.
Replace the value of KEY with the Primary Key you noted earlier.
Replace the value of REG_ID with your device's registration ID.

KEY=8isrFI1sGsIlvvFSSFRiMfCNzv21fjbE/+ah/lSh3lF8e2YG1Te7w1KpZhJFFXJrqYKi9yegxkqIChbqOS9Egw==
REG_ID=sn-007-888-abc-mac-a1-b2-c3-d4-e5-f6

keybytes=$(echo $KEY | base64 --decode | xxd -p -u -c 1000)


echo -n $REG_ID | openssl sha256 -mac HMAC -macopt hexkey:$keybytes -binary | base64

Jsm0lyGpjaVYVP2g3FnmnmG9dI/9qU24wNoykUmermc=

Windows-based workstations
If you are using a Windows-based workstation, you can use PowerShell to generate your derived device key as
shown in the following example.
Replace the value of KEY with the Primary Key you noted earlier.
Replace the value of REG_ID with your device's registration ID.

$KEY='8isrFI1sGsIlvvFSSFRiMfCNzv21fjbE/+ah/lSh3lF8e2YG1Te7w1KpZhJFFXJrqYKi9yegxkqIChbqOS9Egw=='
$REG_ID='sn-007-888-abc-mac-a1-b2-c3-d4-e5-f6'

$hmacsha256 = New-Object System.Security.Cryptography.HMACSHA256


$hmacsha256.key = [Convert]::FromBase64String($KEY)
$sig = $hmacsha256.ComputeHash([Text.Encoding]::ASCII.GetBytes($REG_ID))
$derivedkey = [Convert]::ToBase64String($sig)
echo "`n$derivedkey`n"

Jsm0lyGpjaVYVP2g3FnmnmG9dI/9qU24wNoykUmermc=

Install the IoT Edge runtime


The IoT Edge runtime is deployed on all IoT Edge devices. Its components run in containers, and allow you to
deploy additional containers to the device so that you can run code at the edge.
You'll need the following information when provisioning your device:
The DPS ID Scope value
The device Registration ID you created
The Primary Key you copied from the DPS enrollment

TIP
For group enrollments, you need each device's derived key rather than the DPS enrollment key.

Linux device
Follow the instructions for your device's architecture. Make sure to configure the IoT Edge runtime for automatic,
not manual, provisioning.
Install the Azure IoT Edge runtime on Linux
The section in the configuration file for symmetric key provisioning looks like this:

# DPS symmetric key provisioning configuration


provisioning:
source: "dps"
global_endpoint: "https://global.azure-devices-provisioning.net"
scope_id: "{scope_id}"
attestation:
method: "symmetric_key"
registration_id: "{registration_id}"
symmetric_key: "{symmetric_key}"

Replace the placeholder values for {scope_id} , {registration_id} , and {symmetric_key} with the data you
collected earlier.
Windows device
Install the IoT Edge runtime on the device for which you generated a derived device key. You'll configure the IoT
Edge runtime for automatic, not manual, provisioning.
For more detailed information about installing IoT Edge on Windows, including prerequisites and instructions for
tasks like managing containers and updating IoT Edge, see Install the Azure IoT Edge runtime on Windows.
1. Open a PowerShell window in administrator mode. Be sure to use an AMD64 session of PowerShell when
installing IoT Edge, not PowerShell (x86).
2. The Deploy-IoTEdge command checks that your Windows machine is on a supported version, turns on
the containers feature, and then downloads the moby runtime and the IoT Edge runtime. The command
defaults to using Windows containers.

. {Invoke-WebRequest -useb https://aka.ms/iotedge-win} | Invoke-Expression; `


Deploy-IoTEdge

3. At this point, IoT Core devices may restart automatically. Other Windows 10 or Windows Server devices
may prompt you to restart. If so, restart your device now. Once your device is ready, run PowerShell as an
administrator again.
4. The Initialize-IoTEdge command configures the IoT Edge runtime on your machine. The command
defaults to manual provisioning with Windows containers unless you use the -Dps flag to use automatic
provisioning.
Replace the placeholder values for {scope_id} , {registration_id} , and {symmetric_key} with the data you
collected earlier.
. {Invoke-WebRequest -useb https://aka.ms/iotedge-win} | Invoke-Expression; `
Initialize-IoTEdge -Dps -ScopeId {scope ID} -RegistrationId {registration ID} -SymmetricKey {symmetric
key}

Verify successful installation


If the runtime started successfully, you can go into your IoT Hub and start deploying IoT Edge modules to your
device. Use the following commands on your device to verify that the runtime installed and started successfully.
Linux device
Check the status of the IoT Edge service.

systemctl status iotedge

Examine service logs.

journalctl -u iotedge --no-pager --no-full

List running modules.

iotedge list

Windows device
Check the status of the IoT Edge service.

Get-Service iotedge

Examine service logs.

. {Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; Get-IoTEdgeLog

List running modules.

iotedge list

You can verify that the individual enrollment that you created in Device Provisioning Service was used. Navigate to
your Device Provisioning Service instance in the Azure portal. Open the enrollment details for the individual
enrollment that you created. Notice that the status of the enrollment is assigned and the device ID is listed.

Next steps
The Device Provisioning Service enrollment process lets you set the device ID and device twin tags at the same
time as you provision the new device. You can use those values to target individual devices or groups of devices
using automatic device management. Learn how to Deploy and monitor IoT Edge modules at scale using the
Azure portal or using Azure CLI.
Use Visual Studio 2019 to develop and debug
modules for Azure IoT Edge
11/27/2019 • 10 minutes to read • Edit Online

You can turn your business logic into modules for Azure IoT Edge. This article shows you how to use Visual
Studio 2019 as the main tool to develop and debug modules.
The Azure IoT Edge Tools for Visual Studio provides the following benefits:
Create, edit, build, run, and debug Azure IoT Edge solutions and modules on your local development computer.
Deploy your Azure IoT Edge solution to Azure IoT Edge device via Azure IoT Hub.
Code your Azure IoT modules in C or C# while having all of the benefits of Visual Studio development.
Manage Azure IoT Edge devices and modules with UI.
This article shows you how to use the Azure IoT Edge Tools for Visual Studio 2019 to develop your IoT Edge
modules. You also learn how to deploy your project to your Azure IoT Edge device. Currently, Visual Studio 2019
provides support for modules written in C and C#. The supported device architectures are Windows X64 and
Linux X64 or ARM32. For more information about supported operating systems, languages, and architectures,
see Language and architecture support.

Prerequisites
This article assumes that you use a computer or virtual machine running Windows as your development machine.
On Windows computers you can develop either Windows or Linux modules. To develop Windows modules, use a
Windows computer running version 1809/build 17763 or newer. To develop Linux modules, use a Windows
computer that meets the requirements for Docker Desktop.
Because this article uses Visual Studio 2019 as the main development tool, install Visual Studio. Make sure you
include the Azure development and Desktop development with C++ workloads in your Visual Studio 2019
installation. You can Modify Visual Studio 2019 to add the required workloads.
After your Visual Studio 2019 is ready, you also need the following tools and components:
Download and install Azure IoT Edge Tools from the Visual Studio marketplace to create an IoT Edge project in
Visual Studio 2019.

TIP
If you are using Visual Studio 2017, please download and install Azure IoT Edge Tools for VS 2017 from the Visual Studio
marketplace

Download and install Docker Community Edition on your development machine to build and run your
module images. You'll need to set Docker CE to run in either Linux container mode or Windows container
mode.
Set up your local development environment to debug, run, and test your IoT Edge solution by installing the
Azure IoT EdgeHub Dev Tool. Install Python (2.7/3.6+) and Pip and then install the iotedgehubdev
package by running the following command in your terminal. Make sure your Azure IoT EdgeHub Dev Tool
version is greater than 0.3.0.
pip install --upgrade iotedgehubdev

Clone the repository and install the Vcpkg library manager, and then install the azure-iot-sdk-c package
for Windows.

git clone https://github.com/Microsoft/vcpkg


cd vcpkg
bootstrap-vcpkg.bat

vcpkg.exe install azure-iot-sdk-c:x64-windows


vcpkg.exe --triplet x64-windows integrate install

Azure Container Registry or Docker Hub.

TIP
You can use a local Docker registry for prototype and testing purposes instead of a cloud registry.

To test your module on a device, you'll need an active IoT hub with at least one IoT Edge device. To use your
computer as an IoT Edge device, follow the steps in the quickstart for Linux or Windows. If you are running
IoT Edge daemon on your development machine, you might need to stop EdgeHub and EdgeAgent before
you start development in Visual Studio.
Check your tools version
1. From the Tools menu, select Extensions and Updates. Expand Installed > Tools and you can find Azure
IoT Edge Tools and Cloud Explorer for Visual Studio.
2. Note the installed version. You can compare this version with the latest version on Visual Studio
Marketplace (Cloud Explorer, Azure IoT Edge)
3. If your version is older than what's available on Visual Studio Marketplace, update your tools in Visual
Studio as shown in the following section.
Update your tools
1. In the Extensions and Updates dialog, expand Updates > Visual Studio Marketplace, select Azure
IoT Edge Tools or Cloud Explorer for Visual Studio and select Update.
2. After the tools update is downloaded, close Visual Studio to trigger the tools update using the VSIX
installer.
3. In the installer, select OK to start and then Modify to update the tools.
4. After the update is complete, select Close and restart Visual Studio.
Create an Azure IoT Edge project
The Azure IoT Edge project template in Visual Studio creates a project that can be deployed to Azure IoT Edge
devices in Azure IoT Hub. First you create an Azure IoT Edge solution, and then you generate the first module in
that solution. Each IoT Edge solution can contain more than one module.

TIP
The IoT Edge project structure created by Visual Studio is not the same as in Visual Studio Code.
1. In Visual Studio new project dialog, search and select Azure IoT Edge project and click Next. In project
configuration window, enter a name for your project and specify the location, and then select Create. The
default project name is AzureIoTEdgeApp1.

2. In the Add IoT Edge Application and Module window, select either C# Module or C Module and then
specify your module name and module image repository. Visual Studio autopopulates the module name
with localhost:5000/<your module name>. Replace it with your own registry information. If you use a
local Docker registry for testing, then localhost is fine. If you use Azure Container Registry, then use the
login server from your registry's settings. The login server looks like <registry name>.azurecr.io. Only
replace the localhost:5000 part of the string so that the final result looks like <registry
name>.azurecr.io/<your module name>. The default module name is IotEdgeModule1
3. Select OK to create the Azure IoT Edge solution with a module that uses either C# or C.
Now you have an AzureIoTEdgeApp1.Linux.Amd64 project or an AzureIoTEdgeApp1.Windows.Amd64
project, and also an IotEdgeModule1 project in your solution. Each AzureIoTEdgeApp1 project has a
deployment.template.json file, which defines the modules you want to build and deploy for your IoT Edge
solution, and also defines the routes between modules. The default solution has a
SimulatedTemperatureSensor module and a IotEdgeModule1 module. The SimulatedTemperatureSensor
module generates simulated data to the IotEdgeModule1 module, while the default code in the
IotEdgeModule1 module directly pipes received messages to Azure IoT Hub.
To see how the simulated temperature sensor works, view the SimulatedTemperatureSensor.csproj source code.
The IotEdgeModule1 project is a .NET Core 2.1 console application if it's a C# module. It contains required
Docker files you need for your IoT Edge device running with either a Windows container or Linux container. The
module.json file describes the metadata of a module. The actual module code, which takes Azure IoT Device SDK
as a dependency, is found in the Program.cs or main.c file.

Develop your module


The default module code that comes with the solution is located at IotEdgeModule1 > Program.cs (for C#) or
main.c (C ). The module and the deployment.template.json file are set up so that you can build the solution, push
it to your container registry, and deploy it to a device to start testing without touching any code. The module is
built to take input from a source (in this case, the SimulatedTemperatureSensor module that simulates data)
and pipe it to Azure IoT Hub.
When you're ready to customize the module template with your own code, use the Azure IoT Hub SDKs to build
modules that address the key needs for IoT solutions such as security, device management, and reliability.

Initialize iotedgehubdev with IoT Edge device connection string


1. Copy the connection string of any IoT Edge device from Primary Connection String in the Visual Studio
Cloud Explorer. Be sure not to copy the connection string of a non-Edge device, as the icon of an IoT Edge
device is different from the icon of a non-Edge device.

2. Go to Tools > Azure IoT Edge Tools > Setup IoT Edge Simulator, paste the connection string and click
OK.

3. Enter the connection string from the first step and then select OK.

NOTE
You need to follow these steps only once on your development computer as the results are automatically applied to all
subsequent Azure IoT Edge solutions. This procedure can be followed again if you need to change to a different connection
string.

Build and debug single module


Typically, you'll want to test and debug each module before running it within an entire solution with multiple
modules.
1. Right-click IotEdgeModule1 and select Set as StartUp Project from the context menu.
2. Press F5 or click the button below to run the module; it may take 10–20 seconds the first time you do so.

3. You should see a .NET Core console app start if the module has been initialized successfully.

4. If developing in C#, set a breakpoint in the PipeMessage() function in Program.cs; if using C, set a
breakpoint in the InputQueue1Callback() function in main.c. You can then test it by sending a message by
running the following command in a Git Bash or WSL Bash shell. (You cannot run the curl command
from a PowerShell or command prompt.)

curl --header "Content-Type: application/json" --request POST --data '{"inputName":


"input1","data":"hello world"}' http://localhost:53000/api/v1/messages
The breakpoint should be triggered. You can watch variables in the Visual Studio Locals window.

TIP
You can also use PostMan or other API tools to send messages instead of curl .

5. Press Ctrl + F5 or click the stop button to stop debugging.

Build and debug IoT Edge solution with multiple modules


After you're done developing a single module, you might want to run and debug an entire solution with multiple
modules.
1. Add a second module to the solution by right-clicking AzureIoTEdgeApp1 and selecting Add > New IoT
Edge Module. The default name of the second module is IotEdgeModule2 and will act as another pipe
module.
2. Open the file deployment.template.json and you'll see IotEdgeModule2 has been added in the modules
section. Replace the routes section with the following. If you have customized your module names, make
sure you update these names to match.
"routes": {
"IotEdgeModule1ToIoTHub": "FROM /messages/modules/IotEdgeModule1/outputs/* INTO $upstream",
"sensorToIotEdgeModule1": "FROM
/messages/modules/SimulatedTemperatureSensor/outputs/temperatureOutput INTO
BrokeredEndpoint(\"/modules/IotEdgeModule1/inputs/input1\")",
"IotEdgeModule2ToIoTHub": "FROM /messages/modules/IotEdgeModule2/outputs/* INTO $upstream",
"sensorToIotEdgeModule2": "FROM
/messages/modules/SimulatedTemperatureSensor/outputs/temperatureOutput INTO
BrokeredEndpoint(\"/modules/IotEdgeModule2/inputs/input1\")"
},

3. Right-click AzureIoTEdgeApp1 and select Set as StartUp Project from the context menu.
4. Create your breakpoints and then press F5 to run and debug multiple modules simultaneously. You should
see multiple .NET Core console app windows, which each window representing a different module.

5. Press Ctrl + F5 or select the stop button to stop debugging.

Build and push images


1. Make sure AzureIoTEdgeApp1 is the start-up project. Select either Debug or Release as the
configuration to build for your module images.

NOTE
When choosing Debug, Visual Studio uses Dockerfile.(amd64|windows-amd64).debug to build Docker images.
This includes the .NET Core command-line debugger VSDBG in your container image while building it. For
production-ready IoT Edge modules, we recommend that you use the Release configuration, which uses
Dockerfile.(amd64|windows-amd64) without VSDBG.

2. If you're using a private registry like Azure Container Registry, use the following Docker command to sign
in to it. If you're using local registry, you can run a local registry.
docker login -u <ACR username> -p <ACR password> <ACR login server>

3. If you're using a private registry like Azure Container Registry, you need to add your registry login
information to the runtime settings found in the file deployment.template.json . Replace the placeholders
with your actual ACR admin username, password, and registry name.

"settings": {
"minDockerVersion": "v1.25",
"loggingOptions": "",
"registryCredentials": {
"registry1": {
"username": "<username>",
"password": "<password>",
"address": "<registry name>.azurecr.io"
}
}
}

4. Right-click AzureIoTEdgeApp1 and select Build and Push Edge Solution to build and push the Docker
image for each module.

Deploy the solution


In the quickstart article that you used to set up your IoT Edge device, you deployed a module by using the Azure
portal. You can also deploy modules using the Cloud Explorer for Visual Studio. You already have a deployment
manifest prepared for your scenario, the deployment.json file and all you need to do is select a device to receive
the deployment.
1. Open Cloud Explorer by clicking View > Cloud Explorer. Make sure you've logged in to Visual Studio
2019.
2. In Cloud Explorer, expand your subscription, find your Azure IoT Hub and the Azure IoT Edge device you
want to deploy.
3. Right-click on the IoT Edge device to create a deployment for it, you need to select the deployment
manifest file under the
$AzureIoTEdgeAppSolutionDir\config\deployment.(amd64|amd64.debug|windows-amd64).json .

NOTE
You must not select $AzureIoTEdgeAppSolutionDir\config\deployment_for_local_debug.json
4. Click the refresh button to see the new modules running along with the SimulatedTemperatureSensor
module and $edgeAgent and $edgeHub.

View generated data


1. To monitor the D2C message for a specific device, select the device in the list and then click Start
Monitoring Built-in Event Endpoint in the Action window.
2. To stop monitoring data, select the device in the list and then select Stop Monitoring Built-in Event
Endpoint in the Action window.

Next steps
To develop custom modules for your IoT Edge devices, Understand and use Azure IoT Hub SDKs.
Use Visual Studio Code to develop and debug
modules for Azure IoT Edge
11/27/2019 • 17 minutes to read • Edit Online

You can turn your business logic into modules for Azure IoT Edge. This article shows you how to use Visual
Studio Code as the main tool to develop and debug modules.
There are two ways to debug modules written in C#, Node.js, or Java in Visual Studio Code: You can either
attach a process in a module container or launch the module code in debug mode. To debug modules written in
Python or C, you can only attach to a process in Linux amd64 containers.
If you aren't familiar with the debugging capabilities of Visual Studio Code, read about Debugging.
This article provides instructions for developing and debugging modules in multiple languages for multiple
architectures. Currently, Visual Studio Code provides support for modules written in C#, C, Python, Node.js, and
Java. The supported device architectures are X64 and ARM32. For more information about supported operating
systems, languages, and architectures, see Language and architecture support.

NOTE
Develop and debugging support for Linux ARM64 devices is in public preview. For more information, see Develop and
debug ARM64 IoT Edge modules in Visual Studio Code (preview).

Prerequisites
You can use a computer or a virtual machine running Windows, macOS, or Linux as your development machine.
On Windows computers you can develop either Windows or Linux modules. To develop Windows modules, use
a Windows computer running version 1809/build 17763 or newer. To develop Linux modules, use a Windows
computer that meets the requirements for Docker Desktop.
Install Visual Studio Code first and then add the following extensions:
Azure IoT Tools
Docker extension
Visual Studio extension(s) specific to the language you're developing in:
C#, including Azure Functions: C# extension
Python: Python extension
Java: Java Extension Pack for Visual Studio Code
C: C/C++ extension
You'll also need to install some additional, language-specific tools to develop your module:
C#, including Azure Functions: .NET Core 2.1 SDK
Python: Python and Pip for installing Python packages (typically included with your Python installation).
Node.js: Node.js. You'll also want to install Yeoman and the Azure IoT Edge Node.js Module Generator.
Java: Java SE Development Kit 10 and Maven. You'll need to set the JAVA_HOME environment variable to
point to your JDK installation.
To build and deploy your module image, you need Docker to build the module image and a container registry to
hold the module image:
Docker Community Edition on your development machine.
Azure Container Registry or Docker Hub

TIP
You can use a local Docker registry for prototype and testing purposes instead of a cloud registry.

Unless you're developing your module in C, you also need the Python-based Azure IoT EdgeHub Dev Tool in
order to set up your local development environment to debug, run, and test your IoT Edge solution. If you
haven't already done so, install Python (2.7/3.6/3.7) and Pip and then install iotedgehubdev by running this
command in your terminal.

pip install --upgrade iotedgehubdev

NOTE
Currently, iotedgehubdev uses a docker-py library that is not compatible with Python 3.8.
If you have multiple Python including pre-installed python 2.7 (for example, on Ubuntu or macOS), make sure you are
using the correct pip or pip3 to install iotedgehubdev

To test your module on a device, you'll need an active IoT hub with at least one IoT Edge device. To use your
computer as an IoT Edge device, follow the steps in the quickstart for Linux or Windows. If you are running IoT
Edge daemon on your development machine, you might need to stop EdgeHub and EdgeAgent before you
move to next step.

Create a new solution template


The following steps show you how to create an IoT Edge module in your preferred development language
(including Azure Functions, written in C#) using Visual Studio Code and the Azure IoT Tools. You start by
creating a solution, and then generating the first module in that solution. Each solution can contain multiple
modules.
1. Select View > Command Palette.
2. In the command palette, enter and run the command Azure IoT Edge: New IoT Edge Solution.

3. Browse to the folder where you want to create the new solution and then select Select folder.
4. Enter a name for your solution.
5. Select a module template for your preferred development language to be the first module in the solution.
6. Enter a name for your module. Choose a name that's unique within your container registry.
7. Provide the name of the module's image repository. Visual Studio Code autopopulates the module name
with localhost:5000/<your module name>. Replace it with your own registry information. If you use a
local Docker registry for testing, then localhost is fine. If you use Azure Container Registry, then use the
login server from your registry's settings. The login server looks like <registry name>.azurecr.io. Only
replace the localhost:5000 part of the string so that the final result looks like <registry
name>.azurecr.io/<your module name>.

Visual Studio Code takes the information you provided, creates an IoT Edge solution, and then loads it in a new
window.
There are four items within the solution:
A .vscode folder contains debug configurations.
A modules folder has subfolders for each module. Within the folder for each module there is a file,
module.json, that controls how modules are built and deployed. This file would need to be modified to
change the module deployment container registry from localhost to a remote registry. At this point, you
only have one module. But you can add more in the command palette with the command Azure IoT
Edge: Add IoT Edge Module.
An .env file lists your environment variables. If Azure Container Registry is your registry, you'll have an
Azure Container Registry username and password in it.

NOTE
The environment file is only created if you provide an image repository for the module. If you accepted the
localhost defaults to test and debug locally, then you don't need to declare environment variables.

A deployment.template.json file lists your new module along with a sample


SimulatedTemperatureSensor module that simulates data you can use for testing. For more
information about how deployment manifests work, see Learn how to use deployment manifests to
deploy modules and establish routes.
To see how the simulated temperature module works, view the SimulatedTemperatureSensor.csproj source code.

Add additional modules


To add additional modules to your solution, run the command Azure IoT Edge: Add IoT Edge Module from
the command palette. You can also right-click the modules folder or the deployment.template.json file in the
Visual Studio Code Explorer view and then select Add IoT Edge Module.

Develop your module


The default module code that comes with the solution is located at the following location:
Azure Function (C#): modules > <your module name> > <your module name>.cs
C#: modules > <your module name> > Program.cs
Python: modules > <your module name> > main.py
Node.js: modules > <your module name> > app.js
Java: modules > <your module name> > src > main > java > com > edgemodulemodules > App.java
C: modules > <your module name> > main.c
The module and the deployment.template.json file are set up so that you can build the solution, push it to your
container registry, and deploy it to a device to start testing without touching any code. The module is built to
simply take input from a source (in this case, the SimulatedTemperatureSensor module that simulates data) and
pipe it to IoT Hub.
When you're ready to customize the template with your own code, use the Azure IoT Hub SDKs to build
modules that address the key needs for IoT solutions such as security, device management, and reliability.

Debug a module without a container (C#, Node.js, Java)


If you're developing in C#, Node.js, or Java, your module requires use of a ModuleClient object in the default
module code so that it can start, run, and route messages. You'll also use the default input channel input1 to
take action when the module receives messages.
Set up IoT Edge simulator for IoT Edge solution
On your development machine, you can start an IoT Edge simulator instead of installing the IoT Edge security
daemon so that you can run your IoT Edge solution.
1. In device explorer on the left side, right-click on your IoT Edge device ID, and then select Setup IoT Edge
Simulator to start the simulator with the device connection string.
2. You can see the IoT Edge Simulator has been successfully set up by reading the progress detail in the
integrated terminal.
Set up IoT Edge simulator for single module app
To set up and start the simulator, run the command Azure IoT Edge: Start IoT Edge Hub Simulator for
Single Module from the Visual Studio Code command palette. When prompted, use the value input1 from the
default module code (or the equivalent value from your code) as the input name for your application. The
command triggers the iotedgehubdev CLI and then starts the IoT Edge simulator and a testing utility module
container. You can see the outputs below in the integrated terminal if the simulator has been started in single
module mode successfully. You can also see a curl command to help send message through. You will use it
later.

You can use the Docker Explorer view in Visual Studio Code to see the module's running status.
The edgeHubDev container is the core of the local IoT Edge simulator. It can run on your development machine
without the IoT Edge security daemon and provides environment settings for your native module app or module
containers. The input container exposes REST APIs to help bridge messages to the target input channel on your
module.
Debug module in launch mode
1. Prepare your environment for debugging according to the requirements of your development language,
set a breakpoint in your module, and select the debug configuration to use:
C#
In the Visual Studio Code integrated terminal, change the directory to the <your module
name> folder, and then run the following command to build .NET Core application.

dotnet build

Open the file Program.cs and add a breakpoint.


Navigate to the Visual Studio Code Debug view by selecting View > Debug. Select the
debug configuration <your module name> Local Debug (.NET Core) from the
dropdown.

NOTE
If your .NET Core TargetFramework is not consistent with your program path in launch.json ,
you'll need to manually update the program path in launch.json to match the
TargetFramework in your .csproj file so that Visual Studio Code can successfully launch this
program.

Node.js
In the Visual Studio Code integrated terminal, change the directory to the <your module
name> folder, and then run the following command to install Node packages

npm install

Open the file app.js and add a breakpoint.


Navigate to the Visual Studio Code Debug view by selecting View > Debug. Select the
debug configuration <your module name> Local Debug (Node.js) from the dropdown.
Java
Open the file App.java and add a breakpoint.
Navigate to the Visual Studio Code Debug view by selecting View > Debug. Select the
debug configuration <your module name> Local Debug (Java) from the dropdown.
2. Click Start Debugging or press F5 to start the debug session.
3. In the Visual Studio Code integrated terminal, run the following command to send a Hello World
message to your module. This is the command shown in previous steps when you set up IoT Edge
simulator.
curl --header "Content-Type: application/json" --request POST --data '{"inputName":
"input1","data":"hello world"}' http://localhost:53000/api/v1/messages

NOTE
If you are using Windows, making sure the shell of your Visual Studio Code integrated terminal is Git Bash or WSL
Bash. You cannot run the curl command from a PowerShell or command prompt.

TIP
You can also use PostMan or other API tools to send messages through instead of curl .

4. In the Visual Studio Code Debug view, you'll see the variables in the left panel.
5. To stop your debugging session, select the Stop button or press Shift + F5, and then run Azure IoT
Edge: Stop IoT Edge Simulator in the command palette to stop the simulator and clean up.

Debug in attach mode with IoT Edge Simulator (C#, Node.js, Java,
Azure Functions)
Your default solution contains two modules, one is a simulated temperature sensor module and the other is the
pipe module. The simulated temperature sensor sends messages to the pipe module and then the messages are
piped to the IoT Hub. In the module folder you created, there are several Docker files for different container
types. Use any of the files that end with the extension .debug to build your module for testing.
Currently, debugging in attach mode is supported only as follows:
C# modules, including those for Azure Functions, support debugging in Linux amd64 containers
Node.js modules support debugging in Linux amd64 and arm32v7 containers, and Windows amd64
containers
Java modules support debugging in Linux amd64 and arm32v7 containers

TIP
You can switch among options for the default platform for your IoT Edge solution by clicking the item in the Visual Studio
Code status bar.

Set up IoT Edge simulator for IoT Edge solution


In your development machine, you can start an IoT Edge simulator instead of installing the IoT Edge security
daemon so that you can run your IoT Edge solution.
1. In device explorer on the left side, right-click on your IoT Edge device ID, and then select Setup IoT Edge
Simulator to start the simulator with the device connection string.
2. You can see the IoT Edge Simulator has been successfully set up by reading the progress detail in the
integrated terminal.
Build and run container for debugging and debug in attach mode
1. Open your module file ( Program.cs , app.js , App.java , or <your module name>.cs ) and add a breakpoint.
2. In the Visual Studio Code Explorer view, right-click the deployment.debug.template.json file for your
solution and then select Build and Run IoT Edge solution in Simulator. You can watch all the module
container logs in the same window. You can also navigate to the Docker view to watch container status.

3. Navigate to the Visual Studio Code Debug view and select the debug configuration file for your module.
The debug option name should be similar to <your module name> Remote Debug
4. Select Start Debugging or press F5. Select the process to attach to.
5. In Visual Studio Code Debug view, you'll see the variables in the left panel.
6. To stop the debugging session, first select the Stop button or press Shift + F5, and then select Azure IoT
Edge: Stop IoT Edge Simulator from the command palette.

NOTE
The preceding example shows how to debug IoT Edge modules on containers. It added exposed ports to your module's
container createOptions settings. After you finish debugging your modules, we recommend you remove these exposed
ports for production-ready IoT Edge modules.
For modules written in C#, including Azure Functions, this example is based on the debug version of
Dockerfile.amd64.debug , which includes the .NET Core command-line debugger (VSDBG) in your container image while
building it. After you debug your C# modules, we recommend that you directly use the Dockerfile without VSDBG for
production-ready IoT Edge modules.

Debug a module with the IoT Edge runtime


In each module folder, there are several Docker files for different container types. Use any of the files that end
with the extension .debug to build your module for testing.
When debugging modules using this method, your modules are running on top of the IoT Edge runtime. The IoT
Edge device and your Visual Studio Code can be on the same machine, or more typically, Visual Studio Code is
on the development machine and the IoT Edge runtime and modules are running on another physical machine.
In order to debug from Visual Studio Code, you must:
Set up your IoT Edge device, build your IoT Edge module(s) with the .debug Dockerfile, and then deploy to
the IoT Edge device.
Expose the IP and port of the module so that the debugger can be attached.
Update the launch.json so that Visual Studio Code can attach to the process in the container on the remote
machine. This file is located in the .vscode folder in your workspace and updates each time you add a new
module that supports debugging.
Build and deploy your module to the IoT Edge device
1. In Visual Studio Code, open the deployment.debug.template.json file, which contains the debug version of
your module images with the proper createOptions values set.
2. If you're developing your module in Python, follow these steps before proceeding:
Open the file main.py and add this code after the import section:

import ptvsd
ptvsd.enable_attach(('0.0.0.0', 5678))

Add the following single line of code to the callback you want to debug:

ptvsd.break_into_debugger()

For example, if you want to debug the receive_message_listener function, you would insert that
line of code as shown below:

def receive_message_listener(client):
ptvsd.break_into_debugger()
global RECEIVED_MESSAGES
while True:
message = client.receive_message_on_input("input1") # blocking call
RECEIVED_MESSAGES += 1
print("Message received on input1")
print( " Data: <<{}>>".format(message.data) )
print( " Properties: {}".format(message.custom_properties))
print( " Total calls received: {}".format(RECEIVED_MESSAGES))
print("Forwarding message to output1")
client.send_message_to_output(message, "output1")
print("Message successfully forwarded")

3. In the Visual Studio Code command palette:


a. Run the command Azure IoT Edge: Build and Push IoT Edge solution.
b. Select the deployment.debug.template.json file for your solution.
4. In the Azure IoT Hub Devices section of the Visual Studio Code Explorer view:
a. Right-click an IoT Edge device ID and then select Create Deployment for Single Device.

TIP
To confirm that the device you've chosen is an IoT Edge device, select it to expand the list of modules and
verify the presence of $edgeHub and $edgeAgent. Every IoT Edge device includes these two modules.

b. Navigate to your solution's config folder, select the deployment.debug.amd64.json file, and then
select Select Edge Deployment Manifest.
You'll see the deployment successfully created with a deployment ID in the integrated terminal.
You can check your container status by running the docker ps command in the terminal. If your Visual Studio
Code and IoT Edge runtime are running on the same machine, you can also check the status in the Visual Studio
Code Docker view.
Expose the IP and port of the module for the debugger
You can skip this section if your modules are running on the same machine as Visual Studio Code, as you are
using localhost to attach to the container and already have the correct port settings in the .debug Dockerfile,
module's container createOptions settings, and launch.json file. If your modules and Visual Studio Code are
running on separate machines, follow the steps for your development language.
C#, including Azure Functions
Configure the SSH channel on your development machine and IoT Edge device and then edit
launch.json file to attach.

Node.js
Make sure the module on the machine to be debugged is running and ready for debuggers to
attach, and that port 9229 is accessible externally. You can verify this by opening
http://<target-machine-IP>:9229/json on the debugger machine. This URL should show
information about the Node.js module to be debugged.
On your development machine, open Visual Studio Code and then edit launch.json so that the
address value of the <your module name> Remote Debug (Node.js) profile (or <your module
name> Remote Debug (Node.js in Windows Container) profile if the module is running as a
Windows container) is the IP of the machine being debugged.
Java
Build an SSH tunnel to the machine to be debugged by running
ssh -f <username>@<target-machine> -L 5005:127.0.0.1:5005 -N .

On your development machine, open Visual Studio Code and edit the <your module name>
Remote Debug (Java) profile in launch.json so that you can attach to the target machine. To
learn more about editing launch.json and debugging Java with Visual Studio Code, see the
section on configuring the debugger.
Python
Make sure that port 5678 on the machine to be debugged is open and accessible.
In the code ptvsd.enable_attach(('0.0.0.0', 5678)) that you earlier inserted into main.py , change
0.0.0.0 to the IP address of the machine to be debugged. Build, push, and deploy your IoT Edge
module again.
On your development machine, open Visual Studio Code and then edit launch.json so that the
host value of the <your module name> Remote Debug ( Python ) profile uses the IP address
of the target machine instead of localhost .
Debug your module
1. In the Visual Studio Code Debug view, select the debug configuration file for your module. The debug
option name should be similar to <your module name> Remote Debug
2. Open the module file for your development language and add a breakpoint:
Azure Function (C#): Add your breakpoint to the file <your module name>.cs .
C#: Add your breakpoint to the file Program.cs .
Node.js: Add your breakpoint to the file app.js .
Java: Add your breakpoint to the file App.java .
Python: Add your breakpoint to the file main.py in the callback method where you added the
ptvsd.break_into_debugger() line.
C: Add your breakpoint to the file main.c .
3. Select Start Debugging or select F5. Select the process to attach to.
4. In the Visual Studio Code Debug view, you'll see the variables in the left panel.

NOTE
The preceding example shows how to debug IoT Edge modules on containers. It added exposed ports to your module's
container createOptions settings. After you finish debugging your modules, we recommend you remove these exposed
ports for production-ready IoT Edge modules.

Build and debug a module remotely


With recent changes in both the Docker and Moby engines to support SSH connections, and a new setting in
Azure IoT Tools that enables injection of environment settings into the Visual Studio Code command palette and
Azure IoT Edge terminals, you can now build and debug modules on remote devices.
See this IoT Developer blog entry for more information and step-by-step instructions.

Next steps
After you've built your module, learn how to deploy Azure IoT Edge modules from Visual Studio Code.
To develop modules for your IoT Edge devices, Understand and use Azure IoT Hub SDKs.
Deploy Azure IoT Edge modules from the Azure
portal
11/24/2019 • 3 minutes to read • Edit Online

Once you create IoT Edge modules with your business logic, you want to deploy them to your devices to operate
at the edge. If you have multiple modules that work together to collect and process data, you can deploy them all
at once and declare the routing rules that connect them.
This article shows how the Azure portal guides you through creating a deployment manifest and pushing the
deployment to an IoT Edge device. For information about creating a deployment that targets multiple devices
based on their shared tags, see Deploy and monitor IoT Edge modules at scale

Prerequisites
An IoT hub in your Azure subscription.
An IoT Edge device with the IoT Edge runtime installed.

Select your device


1. Sign in to the Azure portal and navigate to your IoT hub.
2. Select IoT Edge from the menu.
3. Click on the ID of the target device from the list of devices.
4. Select Set Modules.

Configure a deployment manifest


A deployment manifest is a JSON document that describes which modules to deploy, how data flows between
the modules, and desired properties of the module twins. For more information about how deployment
manifests work and how to create them, see Understand how IoT Edge modules can be used, configured, and
reused.
The Azure portal has a wizard that walks you through creating the deployment manifest, instead of building the
JSON document manually. It has three steps: Add modules, Specify routes, and Review deployment.
Add modules
1. In the Container Registry Settings section of the page, provide the credentials to access any private
container registries that contain your module images.
2. In the Deployment Modules section of the page, select Add.
3. Look at the types of modules from the drop-down list:
IoT Edge Module - the default option.
Azure Stream Analytics Module - only modules generated from an Azure Stream Analytics
workload.
Azure Machine Learning Module - only model images generated from an Azure Machine Learning
workspace.
4. Select the IoT Edge Module.
5. Provide a name for the module, then specify the container image. For example:
Name - SimulatedTemperatureSensor
Image URI - mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0
6. Fill out the optional fields if necessary. For more information about container create options, restart policy,
and desired status see EdgeAgent desired properties. For more information about the module twin see
Define or update desired properties.
7. Select Save.
8. Repeat steps 2-6 to add additional modules to your deployment.
9. Select Next to continue to the routes section.
Specify routes
By default the wizard gives you a route called route and defined as FROM / INTO $upstream*, which means that
any messages output by any modules are sent to your IoT hub.
Add or update the routes with information from Declare routes, then select Next to continue to the review
section.
Review deployment
The review section shows you the JSON deployment manifest that was created based on your selections in the
previous two sections. Note that there are two modules declared that you didn't add: $edgeAgent and
$edgeHub. These two modules make up the IoT Edge runtime and are required defaults in every deployment.
Review your deployment information, then select Submit.

View modules on your device


Once you've deployed modules to your device, you can view all of them in the Device details page of the portal.
This page displays the name of each deployed module, as well as useful information like the deployment status
and exit code.

Deploy modules from Azure Marketplace


Azure Marketplace is an online applications and services marketplace where you can browse through a wide
range of enterprise applications and solutions that are certified and optimized to run on Azure, including IoT
Edge modules. Azure Marketplace can also be accessed through the Azure portal under Create a Resource.
You can install an IoT Edge module from either Azure Marketplace or the Azure portal:
1. Find a module and begin the deployment process.
Azure portal: Find a module and select Create.
Azure Marketplace:
a. Find a module and select Get it now.
b. Acknowledge the provider's terms of use and privacy policy by selecting Continue.
2. Choose your subscription and the IoT Hub to which the target device is attached.
3. Choose Deploy to a device.
4. Enter the name of the device or select Find Device to browse among the devices registered with the hub.
5. Select Create to continue the standard process of configuring a deployment manifest, including adding
other modules if desired. Details for the new module such as image URI, create options, and desired
properties are predefined but can be changed.
Next steps
Learn how to Deploy and monitor IoT Edge modules at scale
Deploy Azure IoT Edge modules with Azure CLI
11/24/2019 • 2 minutes to read • Edit Online

Once you create IoT Edge modules with your business logic, you want to deploy them to your devices to operate at
the edge. If you have multiple modules that work together to collect and process data, you can deploy them all at
once and declare the routing rules that connect them.
Azure CLI is an open-source cross platform command-line tool for managing Azure resources such as IoT Edge. It
enables you to manage Azure IoT Hub resources, device provisioning service instances, and linked-hubs out of the
box. The new IoT extension enriches Azure CLI with features such as device management and full IoT Edge
capability.
This article shows how to create a JSON deployment manifest, then use that file to push the deployment to an IoT
Edge device. For information about creating a deployment that targets multiple devices based on their shared tags,
see Deploy and monitor IoT Edge modules at scale

Prerequisites
An IoT hub in your Azure subscription.
An IoT Edge device with the IoT Edge runtime installed.
Azure CLI in your environment. At a minimum, your Azure CLI version must be 2.0.24 or above. Use
az --version to validate. This version supports az extension commands and introduces the Knack command
framework.
The IoT extension for Azure CLI.

Configure a deployment manifest


A deployment manifest is a JSON document that describes which modules to deploy, how data flows between the
modules, and desired properties of the module twins. For more information about how deployment manifests
work and how to create them, see Understand how IoT Edge modules can be used, configured, and reused.
To deploy modules using the Azure CLI, save the deployment manifest locally as a .json file. You will use the file
path in the next section when you run the command to apply the configuration to your device.
Here's a basic deployment manifest with one module as an example:
{
"modulesContent": {
"$edgeAgent": {
"properties.desired": {
"schemaVersion": "1.0",
"runtime": {
"type": "docker",
"settings": {
"minDockerVersion": "v1.25",
"loggingOptions": "",
"registryCredentials": {}
}
},
"systemModules": {
"edgeAgent": {
"type": "docker",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-agent:1.0",
"createOptions": "{}"
}
},
"edgeHub": {
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-hub:1.0",
"createOptions": "{}"
}
}
},
"modules": {
"SimulatedTemperatureSensor": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0",
"createOptions": "{}"
}
}
}
}
},
"$edgeHub": {
"properties.desired": {
"schemaVersion": "1.0",
"routes": {
"route": "FROM /* INTO $upstream"
},
"storeAndForwardConfiguration": {
"timeToLiveSecs": 7200
}
}
},
"SimulatedTemperatureSensor": {
"properties.desired": {}
}
}
}

Deploy to your device


You deploy modules to your device by applying the deployment manifest that you configured with the module
information.
Change directories into the folder where your deployment manifest is saved. If you used one of the VS Code IoT
Edge templates, use the deployment.json file in the config folder of your solution directory and not the
deployment.template.json file.

Use the following command to apply the configuration to an IoT Edge device:

az iot edge set-modules --device-id [device id] --hub-name [hub name] --content [file path]

The device ID parameter is case-sensitive. The content parameter points to the deployment manifest file that you
saved.

View modules on your device


Once you've deployed modules to your device, you can view all of them with the following command:
View the modules on your IoT Edge device:

az iot hub module-identity list --device-id [device id] --hub-name [hub name]

The device ID parameter is case-sensitive.


Next steps
Learn how to Deploy and monitor IoT Edge modules at scale
Deploy Azure IoT Edge modules from Visual Studio
Code
11/24/2019 • 3 minutes to read • Edit Online

Once you create IoT Edge modules with your business logic, you want to deploy them to your devices to operate
at the edge. If you have multiple modules that work together to collect and process data, you can deploy them all
at once and declare the routing rules that connect them.
This article shows how to create a JSON deployment manifest, then use that file to push the deployment to an IoT
Edge device. For information about creating a deployment that targets multiple devices based on their shared tags,
see Deploy and monitor IoT Edge modules at scale

Prerequisites
An IoT hub in your Azure subscription.
An IoT Edge device with the IoT Edge runtime installed.
Visual Studio Code.
Azure IoT Tools for Visual Studio Code.

Configure a deployment manifest


A deployment manifest is a JSON document that describes which modules to deploy, how data flows between the
modules, and desired properties of the module twins. For more information about how deployment manifests
work and how to create them, see Understand how IoT Edge modules can be used, configured, and reused.
To deploy modules using Visual Studio Code, save the deployment manifest locally as a .JSON file. You will use the
file path in the next section when you run the command to apply the configuration to your device.
Here's a basic deployment manifest with one module as an example:
{
"modulesContent": {
"$edgeAgent": {
"properties.desired": {
"schemaVersion": "1.0",
"runtime": {
"type": "docker",
"settings": {
"minDockerVersion": "v1.25",
"loggingOptions": "",
"registryCredentials": {}
}
},
"systemModules": {
"edgeAgent": {
"type": "docker",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-agent:1.0",
"createOptions": "{}"
}
},
"edgeHub": {
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-hub:1.0",
"createOptions": "{}"
}
}
},
"modules": {
"SimulatedTemperatureSensor": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0",
"createOptions": "{}"
}
}
}
}
},
"$edgeHub": {
"properties.desired": {
"schemaVersion": "1.0",
"routes": {
"route": "FROM /* INTO $upstream"
},
"storeAndForwardConfiguration": {
"timeToLiveSecs": 7200
}
}
},
"SimulatedTemperatureSensor": {
"properties.desired": {}
}
}
}

Sign in to access your IoT hub


You can use the Azure IoT extensions for Visual Studio Code to perform operations with your IoT hub. For these
operations to work, you need to sign in to your Azure account and select the IoT hub that you are working on.
1. In Visual Studio Code, open the Explorer view.
2. At the bottom of the Explorer, expand the Azure IoT Hub Devices section.

3. Click on the ... in the Azure IoT Hub Devices section header. If you don't see the ellipsis, hover over the
header.
4. Choose Select IoT Hub.
5. If you are not signed in to your Azure account, follow the prompts to do so.
6. Select your Azure subscription.
7. Select your IoT hub.

Deploy to your device


You deploy modules to your device by applying the deployment manifest that you configured with the module
information.
1. In the Visual Studio Code explorer view, expand the Azure IoT Hub Devices section.
2. Right-click on the IoT Edge device that you want to configure with the deployment manifest.

TIP
To confirm that the device you've chosen is an IoT Edge device, select it to expand the list of modules and verify the
presence of $edgeHub and $edgeAgent. Every IoT Edge device includes these two modules.

3. Select Create Deployment for Single Device.


4. Navigate to the deployment manifest JSON file that you want to use, and click Select Edge Deployment
Manifest.
The results of your deployment are printed in the VS Code output. Successful deployments are applied within a
few minutes if the target device is running and connected to the internet.

View modules on your device


Once you've deployed modules to your device, you can view all of them in the Azure IoT Hub Devices section.
Select the arrow next to your IoT Edge device to expand it. All the currently running modules are displayed.
If you recently deployed new modules to a device, hover over the Azure IoT Hub Devices section header and
select the refresh icon to update the view.
Right-click the name of a module to view and edit the module twin.

Next steps
Learn how to Deploy and monitor IoT Edge modules at scale
Deploy and monitor IoT Edge modules at scale
using the Azure portal
12/1/2019 • 8 minutes to read • Edit Online

Create an IoT Edge automatic deployment in the Azure portal to manage ongoing deployments for many
devices at once. Automatic deployments for IoT Edge are part of the automatic device management feature of
IoT Hub. Deployments are dynamic processes that enable you to deploy multiple modules to multiple devices,
track the status and health of the modules, and make changes when necessary.
For more information, see Understand IoT Edge automatic deployments for single devices or at scale.

Identify devices using tags


Before you can create a deployment, you have to be able to specify which devices you want to affect. Azure IoT
Edge identifies devices using tags in the device twin. Each device can have multiple tags that you define in any
way that makes sense for your solution. For example, if you manage a campus of smart buildings, you might
add the following tags to a device:

"tags":{
"location":{
"building": "20",
"floor": "2"
},
"roomtype": "conference",
"environment": "prod"
}

For more information about device twins and tags, see Understand and use device twins in IoT Hub.

Create a deployment
1. In the Azure portal, go to your IoT hub.
2. Select IoT Edge.
3. Select Add IoT Edge Deployment.
There are five steps to create a deployment. The following sections walk through each one.
Step 1: Name and Label
1. Give your deployment a unique name that is up to 128 lowercase letters. Avoid spaces and the following
invalid characters: & ^ [ ] { } \ | " < > / .
2. You can add labels as key-value pairs to help track your deployments. For example, HostPlatform and
Linux, or Version and 3.0.1.
3. Select Next to move to step two.
Step 2: Add Modules (optional)
You can add up to 20 modules to a deployment.
If you create a deployment with no modules, it removes any current modules from the target devices.
To add a module from Azure Stream Analytics, follow these steps:
1. In the Deployment Modules section of the page, click Add.
2. Select Azure Stream Analytics module.
3. Choose your Subscription from the drop-down menu.
4. Choose your IoT Edge job from the drop-down menu.
5. Select Save to add your module to the deployment.
To add custom code as a module, or to manually add an Azure service module, follow these steps:
1. In the Container Registry Settings section of the page, provide the names and credentials for any private
container registries that contain the module images for this deployment. The IoT Edge Agent will report
error 500 if it can't find the container registry credential for a Docker image.
2. In the Deployment Modules section of the page, click Add.
3. Select IoT Edge Module.
4. Give your module a Name.
5. For the Image URI field, enter the container image for your module.
6. Specify any Container Create Options that should be passed to the container. For more information, see
docker create.
7. Use the drop-down menu to select a Restart policy. Choose from the following options:
Always - The module always restarts if it shuts down for any reason.
never - The module never restarts if it shuts down for any reason.
on-failure - The module restarts if it crashes, but not if it shuts down cleanly.
on-unhealthy - The module restarts if it crashes or returns an unhealthy status. It's up to each
module to implement the health status function.
8. Use the drop-down menu to select the Desired Status for the module. Choose from the following options:
running - Running is the default option. The module will start running immediately after being
deployed.
stopped - After being deployed, the module will remain idle until called upon to start by you or
another module.
9. Select Set module twin's desired properties if you want to add tags or other properties to the module
twin.
10. Enter Environment Variables for this module. Environment variables provide configuration information to
a module.
11. Select Save to add your module to the deployment.
Once you have all the modules for a deployment configured, select Next to move to step three.
Step 3: Specify Routes (optional)
Routes define how modules communicate with each other within a deployment. By default the wizard gives you
a route called route and defined as FROM / INTO $upstream*, which means that any messages output by any
modules are sent to your IoT hub.
Add or update the routes with information from Declare routes, then select Next to continue to the review
section.
Step 4: Specify Metrics (optional)
Metrics provide summary counts of the various states that a device may report back as a result of applying
configuration content.
1. Enter a name for Metric Name.
2. Enter a query for Metric Criteria. The query is based on IoT Edge hub module twin reported properties.
The metric represents the number of rows returned by the query.
For example:

SELECT deviceId FROM devices


WHERE properties.reported.lastDesiredStatus.code = 200

Step 5: Target Devices


Use the tags property from your devices to target the specific devices that should receive this deployment.
Since multiple deployments may target the same device, you should give each deployment a priority number. If
there's ever a conflict, the deployment with the highest priority (larger values indicate higher priority) wins. If
two deployments have the same priority number, the one that was created most recently wins.
1. Enter a positive integer for the deployment Priority.
2. Enter a Target condition to determine which devices will be targeted with this deployment. The condition is
based on device twin tags or device twin reported properties and should match the expression format. For
example, tags.environment='test' or properties.reported.devicemodel='4000x' .
3. Select Next to move on to the final step.
Step 6: Review Deployment
Review your deployment information, then select Submit.

Deploy modules from Azure Marketplace


Azure Marketplace is an online applications and services marketplace where you can browse through a wide
range of enterprise applications and solutions that are certified and optimized to run on Azure, including IoT
Edge modules. Azure Marketplace can also be accessed through the Azure portal under Create a Resource.
You can deploy an IoT Edge module from either Azure Marketplace or the Azure portal:
1. Find a module and begin the deployment process.
Azure portal: Find a module and select Create.
Azure Marketplace:
a. Find a module and select Get it now.
b. Acknowledge the provider's terms of use and privacy policy by selecting Continue.
2. Choose your subscription and the IoT Hub to which the target device is attached.
3. Choose Deploy at Scale.
4. Choose whether to add the module to a new deployment or to a clone of an existing deployment; if
cloning, select the existing deployment from the list.
5. Select Create to continue the process of creating a deployment at scale. You'll be able to specify the same
details as you would for any deployment.

Monitor a deployment
To view the details of a deployment and monitor the devices running it, use the following steps:
1. Sign in to the Azure portal and navigate to your IoT hub.
2. Select IoT Edge.
3. Select IoT Edge deployments.
4. Inspect the deployment list. For each deployment, you can view the following details:
ID - the name of the deployment.
Target condition - the tag used to define targeted devices.
Priority - the priority number assigned to the deployment.
System metrics - Targeted specifies the number of device twins in IoT Hub that match the targeting
condition, and Applied specifies the number of devices that have had the deployment content applied
to their module twins in IoT Hub.
Device metrics - the number of IoT Edge devices in the deployment reporting success or errors from
the IoT Edge client runtime.
Custom metrics - the number of IoT Edge devices in the deployment reporting data for any metrics
that you defined for the deployment.
Creation time - the timestamp from when the deployment was created. This timestamp is used to
break ties when two deployments have the same priority.
5. Select the deployment that you want to monitor.
6. Inspect the deployment details. You can use tabs to review the details of the deployment.

Modify a deployment
When you modify a deployment, the changes immediately replicate to all targeted devices.
If you update the target condition, the following updates occur:
If a device didn't meet the old target condition, but meets the new target condition and this deployment is the
highest priority for that device, then this deployment is applied to the device.
If a device currently running this deployment no longer meets the target condition, it uninstalls this
deployment and takes on the next highest priority deployment.
If a device currently running this deployment no longer meets the target condition and doesn't meet the
target condition of any other deployments, then no change occurs on the device. The device continues
running its current modules in their current state, but is not managed as part of this deployment anymore.
Once it meets the target condition of any other deployment, it uninstalls this deployment and takes on the
new one.
To modify a deployment, use the following steps:
1. Sign in to the Azure portal and navigate to your IoT hub.
2. Select IoT Edge.
3. Select IoT Edge deployments.

4. Select the deployment that you want to modify.


5. Make updates to the following fields:
Target condition
Metrics - you can modify or delete metrics you've defined, or add new ones.
Labels
Priority
6. Select Save.
7. Follow the steps in Monitor a deployment to watch the changes roll out.

Delete a deployment
When you delete a deployment, any devices take on their next highest priority deployment. If your devices don't
meet the target condition of any other deployment, then the modules are not removed when the deployment is
deleted.
1. Sign in to the Azure portal and navigate to your IoT hub.
2. Select IoT Edge.
3. Select IoT Edge deployments.
4. Use the checkbox to select the deployment that you want to delete.
5. Select Delete.
6. A prompt will inform you that this action will delete this deployment and revert to the previous state for
all devices. This means that a deployment with a lower priority will apply. If no other deployment is
targeted, no modules will be removed. If you want to remove all modules from your device, create a
deployment with zero modules and deploy it to the same devices. Select Yes to continue.

Next steps
Learn more about Deploying modules to IoT Edge devices.
Deploy and monitor IoT Edge modules at scale using
the Azure CLI
12/1/2019 • 7 minutes to read • Edit Online

Create an IoT Edge automatic deployment using the Azure command-line interface to manage ongoing
deployments for many devices at once. Automatic deployments for IoT Edge are part of the automatic device
management feature of IoT Hub. Deployments are dynamic processes that enable you to deploy multiple modules
to multiple devices, track the status and health of the modules, and make changes when necessary.
For more information, see Understand IoT Edge automatic deployments for single devices or at scale.
In this article, you set up Azure CLI and the IoT extension. You then learn how to deploy modules to a set of IoT
Edge devices and monitor the progress using the available CLI commands.

CLI Prerequisites
An IoT hub in your Azure subscription.
IoT Edge devices with the IoT Edge runtime installed.
Azure CLI in your environment. At a minimum, your Azure CLI version must be 2.0.24 or above. Use
az --version to validate. This version supports az extension commands and introduces the Knack command
framework.
The IoT extension for Azure CLI.

Configure a deployment manifest


A deployment manifest is a JSON document that describes which modules to deploy, how data flows between the
modules, and desired properties of the module twins. For more information, see Learn how to deploy modules
and establish routes in IoT Edge.
To deploy modules using Azure CLI, save the deployment manifest locally as a .txt file. You use the file path in the
next section when you run the command to apply the configuration to your device.
Here's a basic deployment manifest with one module as an example:

{
"content": {
"modulesContent": {
"$edgeAgent": {
"properties.desired": {
"schemaVersion": "1.0",
"runtime": {
"type": "docker",
"settings": {
"minDockerVersion": "v1.25",
"loggingOptions": "",
"registryCredentials": {
"registryName": {
"username": "",
"password": "",
"address": ""
}
}
}
},
"systemModules": {
"systemModules": {
"edgeAgent": {
"type": "docker",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-agent:1.0",
"createOptions": "{}"
}
},
"edgeHub": {
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-hub:1.0",
"createOptions": "{}"
}
}
},
"modules": {
"SimulatedTemperatureSensor": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0",
"createOptions": "{}"
}
}
}
}
},
"$edgeHub": {
"properties.desired": {
"schemaVersion": "1.0",
"routes": {
"route": "FROM /* INTO $upstream"
},
"storeAndForwardConfiguration": {
"timeToLiveSecs": 7200
}
}
},
"SimulatedTemperatureSensor": {
"properties.desired": {}
}
}
}
}

Identify devices using tags


Before you can create a deployment, you have to be able to specify which devices you want to affect. Azure IoT
Edge identifies devices using tags in the device twin. Each device can have multiple tags that you define in any way
that makes sense for your solution. For example, if you manage a campus of smart buildings, you might add the
following tags to a device:
"tags":{
"location":{
"building": "20",
"floor": "2"
},
"roomtype": "conference",
"environment": "prod"
}

For more information about device twins and tags, see Understand and use device twins in IoT Hub.

Create a deployment
You deploy modules to your target devices by creating a deployment that consists of the deployment manifest as
well as other parameters.
Use the az iot edge deployment create command to create a deployment:

az iot edge deployment create --deployment-id [deployment id] --hub-name [hub name] --content [file path] --
labels "[labels]" --target-condition "[target query]" --priority [int]

The deployment create command takes the following parameters:


--deployment-id - The name of the deployment that will be created in the IoT hub. Give your deployment a
unique name that is up to 128 lowercase letters. Avoid spaces and the following invalid characters:
& ^ [ ] { } \ | " < > / .
--hub-name - Name of the IoT hub in which the deployment will be created. The hub must be in the current
subscription. Change your current subscription with the az account set -s [subscription name] command.
--content - Filepath to the deployment manifest JSON.
--labels - Add labels to help track your deployments. Labels are Name, Value pairs that describe your
deployment. Labels take JSON formatting for the names and values. For example,
{"HostPlatform":"Linux", "Version:"3.0.1"}
--target-condition - Enter a target condition to determine which devices will be targeted with this
deployment. The condition is based on device twin tags or device twin reported properties and should match
the expression format. For example, tags.environment='test' and properties.reported.devicemodel='4000x' .
--priority - A positive integer. In the event that two or more deployments are targeted at the same device, the
deployment with the highest numerical value for Priority will apply.

Monitor a deployment
Use the az iot edge deployment show command to display the details of a single deployment:

az iot edge deployment show --deployment-id [deployment id] --hub-name [hub name]

The deployment show command takes the following parameters:


--deployment-id - The name of the deployment that exists in the IoT hub.
--hub-name - Name of the IoT hub in which the deployment exists. The hub must be in the current
subscription. Switch to the desired subscription with the command az account set -s [subscription name]

Inspect the deployment in the command window. The metrics property lists a count for each metric that is
evaluated by each hub:
targetedCount - A system metric that specifies the number of device twins in IoT Hub that match the
targeting condition.
appliedCount - A system metric specifies the number of devices that have had the deployment content
applied to their module twins in IoT Hub.
reportedSuccessfulCount - A device metric that specifies the number of IoT Edge devices in the deployment
reporting success from the IoT Edge client runtime.
reportedFailedCount - A device metric that specifies the number of IoT Edge devices in the deployment
reporting failure from the IoT Edge client runtime.
You can show a list of device IDs or objects for each of the metrics by using the az iot edge deployment show -
metric command:

az iot edge deployment show-metric --deployment-id [deployment id] --metric-id [metric id] --hub-name [hub
name]

The deployment show -metric command takes the following parameters:


--deployment-id - The name of the deployment that exists in the IoT hub.
--metric-id - The name of the metric for which you want to see the list of device IDs, for example
reportedFailedCount
--hub-name - Name of the IoT hub in which the deployment exists. The hub must be in the current
subscription. Switch to the desired subscription with the command az account set -s [subscription name]

Modify a deployment
When you modify a deployment, the changes immediately replicate to all targeted devices.
If you update the target condition, the following updates occur:
If a device didn't meet the old target condition, but meets the new target condition and this deployment is the
highest priority for that device, then this deployment is applied to the device.
If a device currently running this deployment no longer meets the target condition, it uninstalls this deployment
and takes on the next highest priority deployment.
If a device currently running this deployment no longer meets the target condition and doesn't meet the target
condition of any other deployments, then no change occurs on the device. The device continues running its
current modules in their current state, but is not managed as part of this deployment anymore. Once it meets
the target condition of any other deployment, it uninstalls this deployment and takes on the new one.
Use the az iot edge deployment update command to update a deployment:

az iot edge deployment update --deployment-id [deployment id] --hub-name [hub name] --set
[property1.property2='value']

The deployment update command takes the following parameters:


--deployment-id - The name of the deployment that exists in the IoT hub.
--hub-name - Name of the IoT hub in which the deployment exists. The hub must be in the current
subscription. Switch to the desired subscription with the command az account set -s [subscription name]
--set - Update a property in the deployment. You can update the following properties:
targetCondition - for example targetCondition=tags.location.state='Oregon'
labels
priority
Delete a deployment
When you delete a deployment, any devices take on their next highest priority deployment. If your devices don't
meet the target condition of any other deployment, then the modules are not removed when the deployment is
deleted.
Use the az iot edge deployment delete command to delete a deployment:

az iot edge deployment delete --deployment-id [deployment id] --hub-name [hub name]

The deployment delete command takes the following parameters:


--deployment-id - The name of the deployment that exists in the IoT hub.
--hub-name - Name of the IoT hub in which the deployment exists. The hub must be in the current
subscription. Switch to the desired subscription with the command az account set -s [subscription name]

Next steps
Learn more about Deploying modules to IoT Edge devices.
Configure an IoT Edge device to act as a
transparent gateway
12/3/2019 • 12 minutes to read • Edit Online

This article provides detailed instructions for configuring an IoT Edge device to function as a transparent
gateway for other devices to communicate with IoT Hub. In this article, the term IoT Edge gateway refers to an
IoT Edge device used as a transparent gateway. For more information, see How an IoT Edge device can be used
as a gateway.

NOTE
Currently:
Edge-enabled devices can't connect to IoT Edge gateways.
Downstream devices can't use file upload.

There are three general steps to set up a successful transparent gateway connection. This article covers the first
step:
1. The gateway device needs to be able to securely connect to downstream devices, receive
communications from downstream devices, and route messages to the proper destination.
2. The downstream device needs to have a device identity to be able to authenticate with IoT Hub, and know to
communicate through its gateway device. For more information, see Authenticate a downstream device to
Azure IoT Hub.
3. The downstream device needs to be able to securely connect to its gateway device. For more information,
see Connect a downstream device to an Azure IoT Edge gateway.
For a device to function as a gateway, it needs to be able to securely connect to its downstream devices. Azure
IoT Edge allows you to use a public key infrastructure (PKI) to set up secure connections between devices. In
this case, we’re allowing a downstream device to connect to an IoT Edge device acting as a transparent gateway.
To maintain reasonable security, the downstream device should confirm the identity of the gateway device. This
identity check prevents your devices from connecting to potentially malicious gateways.
A downstream device in a transparent gateway scenario can be any application or platform that has an identity
created with the Azure IoT Hub cloud service. In many cases, these applications use the Azure IoT device SDK.
For all practical purposes, a downstream device could even be an application running on the IoT Edge gateway
device itself. However, an IoT Edge device cannot be downstream of an IoT Edge gateway.
You can create any certificate infrastructure that enables the trust required for your device-gateway topology. In
this article, we assume the same certificate setup that you would use to enable X.509 CA security in IoT Hub,
which involves an X.509 CA certificate associated to a specific IoT hub (the IoT hub root CA), a series of
certificates signed with this CA, and a CA for the IoT Edge device.
NOTE
The term "root CA" used throughout this article refers to the topmost authority public certificate of the PKI certificate
chain, and not necessarily the certificate root of a syndicated certificate authority. In many cases, it is actually an
intermediate CA public certificate.

The gateway presents its IoT Edge device CA certificate to the downstream device during the initiation of the
connection. The downstream device checks to make sure the IoT Edge device CA certificate is signed by the root
CA certificate. This process allows the downstream device to confirm that the gateway comes from a trusted
source.
The following steps walk you through the process of creating the certificates and installing them in the right
places on the gateway. You can use any machine to generate the certificates, and then copy them over to your
IoT Edge device.

Prerequisites
A development machine to create certificates.
An Azure IoT Edge device to configure as a gateway. Use the IoT Edge installation steps for one of the
following operating systems:
Windows
Linux

Generate certificates with Windows


Use the steps in this section to generate test certificates on Windows. You can use a Windows machine to
generate the certificates, and then copy them over to any IoT Edge device running on any supported operating
system.
The certificates generated in this section are intended for testing purposes only.
Install OpenSSL
Install OpenSSL for Windows on the machine that you're using to generate the certificates. If you already have
OpenSSL installed on your Windows device, you may skip this step, but ensure that openssl.exe is available in
your PATH environment variable.
There are several ways to install OpenSSL, including:
Easier: Download and install any third-party OpenSSL binaries, for example, from OpenSSL on
SourceForge. Add the full path to openssl.exe to your PATH environment variable.
Recommended: Download the OpenSSL source code and build the binaries on your machine by
yourself or via vcpkg. The instructions listed below use vcpkg to download source code, compile, and
install OpenSSL on your Windows machine with easy steps.
1. Navigate to a directory where you want to install vcpkg. We'll refer to this directory as
<VCPKGDIR>. Follow the instructions to download and install vcpkg.
2. Once vcpkg is installed, run the following command from a powershell prompt to install the
OpenSSL package for Windows x64. The installation typically takes about 5 mins to complete.

.\vcpkg install openssl:x64-windows

3. Add <VCPKGDIR>\installed\x64-windows\tools\openssl to your PATH environment variable so that


the openssl.exe file is available for invocation.
Prepare creation scripts
The Azure IoT Edge git repository contains scripts that you can use to generate test certificates. In this section,
you clone the IoT Edge repo and execute the scripts.
1. Open a PowerShell window in administrator mode.
2. Clone the git repo that contains scripts to generate non-production certificates. These scripts help you
create the necessary certificates to set up a transparent gateway. Use the git clone command or
download the ZIP.

git clone https://github.com/Azure/iotedge.git

3. Navigate to the directory in which you want to work. Throughout this article, we'll call this directory
<WRKDIR>. All certificates and keys will be created in this working directory.
4. Copy the configuration and script files from the cloned repo into your working directory.

copy <path>\iotedge\tools\CACertificates\*.cnf .
copy <path>\iotedge\tools\CACertificates\ca-certs.ps1 .

If you downloaded the repo as a ZIP, then the folder name is iotedge-master and the rest of the path is
the same.
5. Enable PowerShell to run the scripts.

Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser

6. Bring the functions used by the scripts into PowerShell's global namespace.

. .\ca-certs.ps1

The PowerShell window will display a warning that the certificates generated by this script are only for
testing purposes, and should not be used in production scenarios.
7. Verify that OpenSSL has been installed correctly and make sure that there won't be name collisions with
existing certificates. If there are problems, the script should describe how to fix them on your system.

Test-CACertsPrerequisites
Create certificates
In this section, you create three certificates and then connect them in a chain. Placing the certificates in a chain
file allows you to install them easily on your IoT Edge gateway device and any downstream devices.
1. Create the root CA certificate and have it sign one intermediate certificate. The certificates are all placed
in your working directory.

New-CACertsCertChain rsa

This script command creates several certificate and key files, but we're going to refer to one in particular
later in this article:
<WRKDIR>\certs\azure-iot-test-only.root.ca.cert.pem
2. Create the IoT Edge device CA certificate and private key with the following command. Provide a name
for the CA certificate, for example MyEdgeDeviceCA. The name is used to name the files and during
certificate generation.

New-CACertsEdgeDeviceCA "MyEdgeDeviceCA"

This script command creates several certificate and key files, including two that we're going to refer to
later in this article:
<WRKDIR>\certs\iot-edge-device-ca-MyEdgeDeviceCA-full-chain.cert.pem
<WRKDIR>\private\iot-edge-device-ca-MyEdgeDeviceCA.key.pem

TIP
If you provide a name other than MyEdgeDeviceCA, then the certificates and keys created by this command will
reflect that name.

Now that you have the certificates, skip ahead to Install certificates on the gateway

Generate certificates with Linux


Use the steps in this section to generate test certificates on Linux. You can use a Linux machine to generate the
certificates, and then copy them over to any IoT Edge device running on any supported operating system.
The certificates generated in this section are intended for testing purposes only.
Prepare creation scripts
The Azure IoT Edge git repository contains scripts that you can use to generate test certificates. In this section,
you clone the IoT Edge repo and execute the scripts.
1. Clone the git repo that contains scripts to generate non-production certificates. These scripts help you
create the necessary certificates to set up a transparent gateway.

git clone https://github.com/Azure/iotedge.git

2. Navigate to the directory in which you want to work. We'll refer to this directory throughout the article
as <WRKDIR>. All certificate and key files will be created in this directory.
3. Copy the config and script files from the cloned IoT Edge repo into your working directory.
cp <path>/iotedge/tools/CACertificates/*.cnf .
cp <path>/iotedge/tools/CACertificates/certGen.sh .

Create certificates
In this section, you create three certificates and then connect them in a chain. Placing the certificates in a chain
file allows to easily install them on your IoT Edge gateway device and any downstream devices.
1. Create the root CA certificate and one intermediate certificate. These certificates are placed in
<WRKDIR>.
If you've already created root and intermediate certificates in this working directory, don't run this script
again. Rerunning this script will overwrite the existing certificates. Instead, proceed to the next step.

./certGen.sh create_root_and_intermediate

The script creates several certificates and keys. Make note of one, which we'll refer to in the next section:
<WRKDIR>/certs/azure-iot-test-only.root.ca.cert.pem
2. Create the IoT Edge device CA certificate and private key with the following command. Provide a name
for the CA certificate, for example MyEdgeDeviceCA. The name is used to name the files and during
certificate generation.

./certGen.sh create_edge_device_ca_certificate "MyEdgeDeviceCA"

The script creates several certificates and keys. Make note of two, which we'll refer to in the next section:
<WRKDIR>/certs/iot-edge-device-ca-MyEdgeDeviceCA-full-chain.cert.pem
<WRKDIR>/private/iot-edge-device-ca-MyEdgeDeviceCA.key.pem

TIP
If you provide a name other than MyEdgeDeviceCA, then the certificates and keys created by this command will
reflect that name.

Install certificates on the gateway


Now that you've made a certificate chain, you need to install it on the IoT Edge gateway device and configure
the IoT Edge runtime to reference the new certificates.
1. Copy the following files from <WRKDIR>. Save them anywhere on your IoT Edge device. We'll refer to
the destination directory on your IoT Edge device as <CERTDIR>.
Device CA certificate - <WRKDIR>\certs\iot-edge-device-ca-MyEdgeDeviceCA-full-chain.cert.pem
Device CA private key - <WRKDIR>\private\iot-edge-device-ca-MyEdgeDeviceCA.key.pem
Root CA - <WRKDIR>\certs\azure-iot-test-only.root.ca.cert.pem
You can use a service like Azure Key Vault or a function like Secure copy protocol to move the certificate
files. If you generated the certificates on the IoT Edge device itself, you can skip this step and use the path
to the working directory.
2. Open the IoT Edge security daemon config file.
Windows: C:\ProgramData\iotedge\config.yaml
Linux: /etc/iotedge/config.yaml
3. Set the certificate properties in the config.yaml file to the full path to the certificate and key files on the
IoT Edge device. Remove the # character before the certificate properties to uncomment the four lines.
Remember that indents in yaml are two spaces.
Windows:

certificates:
device_ca_cert: "<CERTDIR>\\certs\\iot-edge-device-ca-MyEdgeDeviceCA-full-chain.cert.pem"
device_ca_pk: "<CERTDIR>\\private\\iot-edge-device-ca-MyEdgeDeviceCA.key.pem"
trusted_ca_certs: "<CERTDIR>\\certs\\azure-iot-test-only.root.ca.cert.pem"

Linux:

certificates:
device_ca_cert: "<CERTDIR>/certs/iot-edge-device-ca-MyEdgeDeviceCA-full-chain.cert.pem"
device_ca_pk: "<CERTDIR>/private/iot-edge-device-ca-MyEdgeDeviceCA.key.pem"
trusted_ca_certs: "<CERTDIR>/certs/azure-iot-test-only.root.ca.cert.pem"

4. On Linux devices, make sure that the user iotedge has read permissions for the directory holding the
certificates.

Deploy EdgeHub to the gateway


When you first install IoT Edge on a device, only one system module starts automatically: the IoT Edge agent.
For your device to work as a gateway, you need both system modules. If you haven't deployed any modules to
your gateway device before, create an initial deployment for your device to start the second system module, the
IoT Edge hub. The deployment will look empty because you don't add any modules in the wizard, but it will
make sure that both system modules are running.
You can check which modules are running on a device with the command iotedge list . If the list only returns
the module edgeAgent without edgeHub, use the following steps:
1. In the Azure portal, navigate to your IoT hub.
2. Go to IoT Edge and select your IoT Edge device that you want to use as a gateway.
3. Select Set Modules.
4. Select Next.
5. In the Specify routes page, you should have a default route that sends all messages from all modules to
IoT Hub. If not, add the following code then select Next.

{
"routes": {
"route": "FROM /* INTO $upstream"
}
}

6. In the Review template page, select Submit.

Open ports on gateway device


Standard IoT Edge devices don't need any inbound connectivity to function, because all communication with IoT
Hub is done through outbound connections. Gateway devices are different because they need to receive
messages from their downstream devices. If a firewall is between the downstream devices and the gateway
device, then communication needs to be possible through the firewall as well.
For a gateway scenario to work, at least one of the IoT Edge hub's supported protocols must be open for
inbound traffic from downstream devices. The supported protocols are MQTT, AMQP, HTTPS, MQTT over
WebSockets, and AMQP over WebSockets.

PORT PROTOCOL

8883 MQTT

5671 AMQP

443 HTTPS
MQTT+WS
AMQP+WS

Route messages from downstream devices


The IoT Edge runtime can route messages sent from downstream devices just like messages sent by modules.
This feature allows you to perform analytics in a module running on the gateway before sending any data to the
cloud.
Currently, the way that you route messages sent by downstream devices is by differentiating them from
messages sent by modules. Messages sent by modules all contain a system property called
connectionModuleId but messages sent by downstream devices do not. You can use the WHERE clause of
the route to exclude any messages that contain that system property.
The below route is an example that would send messages from any downstream device to a module named
ai_insights , and then from ai_insights to IoT Hub.

{
"routes":{
"sensorToAIInsightsInput1":"FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO
BrokeredEndpoint(\"/modules/ai_insights/inputs/input1\")",
"AIInsightsToIoTHub":"FROM /messages/modules/ai_insights/outputs/output1 INTO $upstream"
}
}

For more information about message routing, see Deploy modules and establish routes.

Enable extended offline operation


Starting with the v1.0.4 release of the IoT Edge runtime, the gateway device and downstream devices
connecting to it can be configured for extended offline operation.
With this capability, local modules or downstream devices can re-authenticate with the IoT Edge device as
needed and communicate with each other using messages and methods even when disconnected from the IoT
hub. For more information, see Understand extended offline capabilities for IoT Edge devices, modules, and
child devices.
To enable extended offline capabilities, you establish a parent-child relationship between an IoT Edge gateway
device and downstream devices that will connect to it. Those steps are explained in more detail in Authenticate a
downstream device to Azure IoT Hub.

Next steps
Now that you have an IoT Edge device working as a transparent gateway, you need to configure your
downstream devices to trust the gateway and send messages to it. Continue on to Authenticate a downstream
device to Azure IoT Hub for the next steps in setting up your transparent gateway scenario.
Authenticate a downstream device to Azure IoT Hub
11/24/2019 • 15 minutes to read • Edit Online

In a transparent gateway scenario, downstream devices (sometimes called leaf devices or child devices) need
identities in IoT Hub like any other device. This article walks through the options for authenticating a
downstream device to IoT Hub, and then demonstrates how to declare the gateway connection.
There are three general steps to set up a successful transparent gateway connection. This article covers the
second step:
1. The gateway device needs to be able to securely connect to downstream devices, receive communications
from downstream devices, and route messages to the proper destination. For more information, see
Configure an IoT Edge device to act as a transparent gateway.
2. The downstream device needs to have a device identity to be able to authenticate with IoT Hub,
and know to communicate through its gateway device.
3. The downstream device needs to be able to securely connect to its gateway device. For more information, see
Connect a downstream device to an Azure IoT Edge gateway.
Downstream devices can authenticate with IoT Hub using one of three methods: symmetric keys (sometimes
referred to as shared access keys), X.509 self-signed certificates, or X.509 certificate authority (CA) signed
certificates. The authentication steps are similar to the steps used to set up any non-IoT-Edge device with IoT
Hub, with small differences to declare the gateway relationship.
The steps in this article show manual device provisioning, not automatic provisioning with the Azure IoT Hub
Device Provisioning Service.

Prerequisites
Complete the steps in Configure an IoT Edge device to act as a transparent gateway. If you're using X.509
authentication for your downstream device, you need to use the same certificate generating script that you set up
in the transparent gateway article.
This article refers to the gateway hostname at several points. The gateway hostname is declared in the
hostname parameter of the config.yaml file on the IoT Edge gateway device. It's used to create the certificates in
this article, and is referred to in the connection string of the downstream devices. The gateway hostname needs
to be resolvable to an IP Address, either using DNS or a host file entry.

Symmetric key authentication


Symmetric key authentication, or shared access key authentication, is the simplest way to authenticate with IoT
Hub. With symmetric key authentication, a base64 key is associated with your IoT device ID in IoT Hub. You
include that key in your IoT applications so that your device can present it when it connects to IoT Hub.
Create the device identity
Add a new IoT device in your IoT hub, using either the Azure portal, Azure CLI, or the IoT extension for Visual
Studio Code. Remember that downstream devices need to be identified in IoT Hub as regular IoT device, not IoT
Edge devices.
When you create the new device identity, provide the following information:
Create an ID for your device.
Select Symmetric key as the authentication type.
Optionally, choose to Set a parent device and select the IoT Edge gateway device that this downstream
device will connect through. This step is optional for symmetric key authentication, but it's recommended
because setting a parent device enables offline capabilities for your downstream device. You can always
update the device details to add or change the parent later.

You can use the IoT extension for Azure CLI to complete the same operation. The following example creates a
new IoT device with symmetric key authentication and assigns a parent device:

az iot hub device-identity create -n {iothub name} -d {device ID} --pd {gateway device ID}

For more information about Azure CLI commands for device creation and parent/child management, see the
reference content for az iot hub device-identity commands.
Connect to IoT Hub through a gateway
The same process is used to authenticate regular IoT devices to IoT Hub with symmetric keys also applies to
downstream devices. The only difference is that you need to add a pointer to the gateway device to route the
connection or, in offline scenarios, to handle the authentication on behalf of IoT Hub.
For symmetric key authentication, there's no additional steps that you need to take on your device for it to
authenticate with IoT Hub. You still need the certificates in place so that your downstream device can connect to
its gateway device, as described in Connect a downstream device to an Azure IoT Edge gateway.
After creating an IoT device identity in the portal, you can retrieve its primary or secondary keys. One of these
keys needs to be included in the connection string that you include in any application that communicates with IoT
Hub. For symmetric key authentication, IoT Hub provides the fully formed connection string in the device details
for your convenience. You need to add extra information about the gateway device to the connection string.
Symmetric key connection strings for downstream devices need the following components:
The IoT hub that the device connects to: Hostname={iothub name}.azure-devices.net
The device ID registered with the hub: DeviceID={device ID}
Either the primary or secondary key: SharedAccessKey={key}
The gateway device that the device connects through. Provide the hostname value from the IoT Edge
gateway device's config.yaml file: GatewayHostName={gateway hostname}

All together, a complete connection string looks like:

HostName=myiothub.azure-
devices.net;DeviceId=myDownstreamDevice;SharedAccessKey=xxxyyyzzz;GatewayHostName=myGatewayDevice

If you established a parent/child relationship for this downstream device, then you can simplify the connection
string by calling the gateway directly as the connection host. For example:

HostName=myGatewayDevice;DeviceId=myDownstreamDevice;SharedAccessKey=xxxyyyzzz

X.509 authentication
There are two ways to authenticate an IoT device using X.509 certificates. Whichever way you choose to
authenticate, the steps to connect your device to IoT Hub are the same. Choose either self-signed or CA-signed
certs for authentication, then continue to learn how to connect to IoT Hub.
For more information about how IoT Hub uses X.509 authentication, see the following articles:
Device authentication using X.509 CA certificates
Conceptual understanding of X.509 CA certificates in the IoT industry
Create the device identity with X.509 self-signed certificates
For X.509 self-signed authentication, sometimes referred to as thumbprint authentication, you need to create
new certificates to place on your IoT device. These certificates have a thumbprint in them that you share with IoT
Hub for authentication.
The easiest way to test this scenario is to use the same machine that you used to create certificates in Configure
an IoT Edge device to act as a transparent gateway. That machine should already be set up with the right tool,
root CA certificate, and intermediate CA certificate to create the IoT device certificates. You can copy the final
certificates and their private keys over to your downstream device afterwards. Following the steps in the gateway
article, you set up openssl on your machine, then cloned the IoT Edge repo to access certificate creation scripts.
Then, you made a working directory that we call <WRKDIR> to hold the certificates. The default certificates are
meant for developing and testing, so only last 30 days. You should have created a root CA certificate and an
intermediate certificate.
1. Navigate to your working directory in either a bash or PowerShell window.
2. Create two certificates (primary and secondary) for the downstream device. Provide your device name and
then the primary or secondary label. This information is used to name the files so that you can keep track
of certificates for multiple devices.

New-CACertsDevice "<device name>-primary"


New-CACertsDevice "<device name>-secondary"
./certGen.sh create_device_certificate "<device name>-primary"
./certGen.sh create_device_certificate "<device name>-secondary"

3. Retrieve the SHA1 fingerprint (called a thumbprint in the IoT Hub interface) from each certificate, which is
a 40 hexadecimal character string. Use the following openssl command to view the certificate and find the
fingerprint:

openssl x509 -in <WORKDIR>/certs/iot-device-<device name>-primary.cert.pem -text -fingerprint | sed


's/[:]//g'

4. Navigate to your IoT hub in the Azure portal and create a new IoT device identity with the following
values:
Select X.509 Self-Signed as the authentication type.
Paste the hexadecimal strings that you copied from your device's primary and secondary certificates.
Select Set a parent device and choose the IoT Edge gateway device that this downstream device will
connect through. A parent device is required for X.509 authentication of a downstream device.

5. Copy the following files to any directory on your downstream device:


<WRKDIR>\certs\azure-iot-test-only.root.ca.cert.pem
<WRKDIR>\certs\iot-device-<device name>*.cert.pem
<WRKDIR>\certs\iot-device-<device id>*.cert.pfx
<WRKDIR>\certs\iot-device-<device name>*-full-chain.cert.pem
<WRKDIR>\private\iot-device-<device name>*.key.pem

You'll reference these files in the leaf device applications that connect to IoT Hub. You can use a service
like Azure Key Vault or a function like Secure copy protocol to move the certificate files.
You can use the IoT extension for Azure CLI to complete the same device creation operation. The following
example creates a new IoT device with X.509 self-signed authentication and assigns a parent device:

az iot hub device-identity create -n {iothub name} -d {device ID} --pd {gateway device ID} --am
x509_thumbprint --ptp {primary thumbprint} --stp {secondary thumbprint}

For more information about Azure CLI commands for device creation, certificate generation, and parent and
child management, see the reference content for az iot hub device-identity commands.
Create the device identity with X.509 CA signed certificates
For X.509 certificate authority (CA) signed authentication, you need a root CA certificate registered in IoT Hub
that you use to sign certificates for your IoT device. Any device using a certificate that was issues by the root CA
certificate or any of its intermediate certificates will be permitted to authenticate.
This section is based on the instructions detailed in the IoT Hub article Set up X.509 security in your Azure IoT
hub. Follow the steps in this section to know which values to use to set up a downstream device that connects
through a gateway.
The easiest way to test this scenario is to use the same machine that you used to create certificates in Configure
an IoT Edge device to act as a transparent gateway. That machine should already be set up with the right tool,
root CA certificate, and intermediate CA certificate to create the IoT device certificates. You can copy the final
certificates and their private keys over to your downstream device afterwards. Following the steps in the gateway
article, you set up openssl on your machine, then cloned the IoT Edge repo to access certificate creation scripts.
Then, you made a working directory that we call <WRKDIR> to hold the certificates. The default certificates are
meant for developing and testing, so only last 30 days. You should have created a root CA certificate and an
intermediate certificate.
1. Follow the instructions in the Register X.509 CA certificates to your IoT hub section of Set up X.509
security in your Azure IoT hub. In that section, you perform the following steps:
a. Upload a root CA certificate. If you're using the certificates that you created in the transparent
gateway article, upload <WRKDIR>/certs/azure-iot-test-only.root.ca.cert.pem as the root
certificate file.
b. Verify that you own that root CA certificate. You can verify possession with the cert tools in
<WRKDIR>.

New-CACertsVerificationCert "<verification code from Azure portal>"

./certGen.sh create_verification_certificate <verification code from Azure portal>"

2. Follow the instructions in the Create an X.509 device for your IoT hub section of Set up X.509 security in
your Azure IoT hub. In that section, you perform the following steps:
a. Add a new device. Provide a lowercase name for device ID, and choose the authentication type X.509
CA Signed.
b. Set a parent device. For downstream devices, select Set a parent device and choose the IoT Edge
gateway device that will provide the connection to IoT Hub.
3. Create a certificate chain for your downstream device. Use the same root CA certificate that you uploaded
to IoT Hub to make this chain. Use the same lowercase device ID that you gave to your device identity in
the portal.
New-CACertsDevice "<device id>"

./certGen.sh create_device_certificate "<device id>"

4. Copy the following files to any directory on your downstream device:


<WRKDIR>\certs\azure-iot-test-only.root.ca.cert.pem
<WRKDIR>\certs\iot-device-<device id>*.cert.pem
<WRKDIR>\certs\iot-device-<device id>*.cert.pfx
<WRKDIR>\certs\iot-device-<device id>*-full-chain.cert.pem
<WRKDIR>\private\iot-device-<device id>*.key.pem
You'll reference these files in the leaf device applications that connect to IoT Hub. You can use a service
like Azure Key Vault or a function like Secure copy protocol to move the certificate files.
You can use the IoT extension for Azure CLI to complete the same device creation operation. The following
example creates a new IoT device with X.509 CA signed authentication and assigns a parent device:

az iot hub device-identity create -n {iothub name} -d {device ID} --pd {gateway device ID} --am x509_ca

For more information about Azure CLI commands for device creation and parent/child management, see the
reference content for az iot hub device-identity commands.
Connect to IoT Hub through a gateway
Each Azure IoT SDK handles X.509 authentication a little differently. However, the same process is used to
authenticate regular IoT devices to IoT Hub with X.509 certificates also applies to downstream devices. The only
difference is that you need to add a pointer to the gateway device to route the connection or, in offline scenarios,
to handle the authentication on behalf of IoT Hub. In general, you can follow the same X.509 authentication steps
for all IoT Hub devices, then simply replace the value of Hostname in the connection string to be the hostname
of your gateway device.
The following sections show some examples for different SDK languages.

IMPORTANT
The following samples demonstrate how the IoT Hub SDKs use certificates to authenticate devices. In a production
deployment, you should store all secrets like private or SAS keys in a hardware secure module (HSM).

.NET
For an example of a C# program authenticating to IoT Hub with X.509 certificates, see Set up X.509 security in
your Azure IoT hub. Some of the key lines of that sample are included here to demonstrate the authentication
process.
When declaring the hostname for your DeviceClient instance, use the IoT Edge gateway device's hostname. The
hostname can be found in the gateway device's config.yaml file.
If you're using the test certificates provided by the IoT Edge git repository, the key to the certificates is 1234.
try
{
var cert = new X509Certificate2(@"<absolute-path-to-your-device-pfx-file>", "1234");
var auth = new DeviceAuthenticationWithX509Certificate("<device-id>", cert);
var deviceClient = DeviceClient.Create("<gateway hostname>", auth, TransportType.Amqp_Tcp_Only);

if (deviceClient == null)
{
Console.WriteLine("Failed to create DeviceClient!");
}
else
{
Console.WriteLine("Successfully created DeviceClient!");
SendEvent(deviceClient).Wait();
}

Console.WriteLine("Exiting...\n");
}
catch (Exception ex)
{
Console.WriteLine("Error in sample: {0}", ex.Message);
}

C
For an example of a C program authenticating to IoT Hub with X.509 certificates, see the C IoT SDK's
iotedge_downstream_device_sample sample. Some of the key lines of that sample are included here to
demonstrate the authentication process.
When defining the connection string for your downstream device, use the IoT Edge gateway device's hostname
for the HostName parameter. The hostname can be found in the gateway device's config.yaml file.
// If your downstream device uses X.509 authentication (self signed or X.509 CA) then
// resulting connection string should look like the following:
// "HostName=<gateway device hostname>;DeviceId=<device_id>;x509=true"
static const char* connectionString = "[Downstream device IoT Edge connection string]";

// Path to the Edge "owner" root CA certificate


static const char* edge_ca_cert_path = "[Path to root CA certificate]";

// When the downstream device uses X.509 authentication, a certificate and key
// in PRM format must be provided.
static const char * x509_device_cert_path = "[Path to primary or secondary device cert]";
static const char * x509_device_key_path = "[Path to primary or secondary device key]";

int main(void)
{
// Create the iothub handle here
device_handle = IoTHubDeviceClient_CreateFromConnectionString(connectionString, protocol);

// Provide the Azure IoT device client with the same root
// X509 CA certificate that was used to set up the IoT Edge gateway runtime
if (edge_ca_cert_path != NULL)
{
cert_string = obtain_edge_ca_certificate();
(void)IoTHubDeviceClient_SetOption(device_handle, OPTION_TRUSTED_CERT, cert_string);
}

if ((x509_device_cert_path != NULL) && (x509_device_key_path != NULL))


{
const char *x509certificate = obtain_file_contents(x509_device_cert_path);
const char *x509privatekey = obtain_file_contents(x509_device_key_path);
if ((IoTHubDeviceClient_SetOption(device_handle, OPTION_X509_CERT, x509certificate) !=
IOTHUB_CLIENT_OK) ||
(IoTHubDeviceClient_SetOption(device_handle, OPTION_X509_PRIVATE_KEY, x509privatekey) !=
IOTHUB_CLIENT_OK)
)
{
printf("failure to set options for x509, aborting\r\n");
exit(1);
}
}
}

Node.js
For an example of a Node.js program authenticating to IoT Hub with X.509 certificates, see the Node.js IoT
SDK's simple_sample_device_x509.js sample. Some of the key lines of that sample are included here to
demonstrate the authentication process.
When defining the connection string for your downstream device, use the IoT Edge gateway device's hostname
for the HostName parameter. The hostname can be found in the gateway device's config.yaml file.
If you're using the test certificates provided by the IoT Edge git repository, the key to the certificates is 1234.
// String containing Hostname and Device Id in the following format:
// "HostName=<gateway device hostname>;DeviceId=<device_id>;x509=true"
var connectionString = '<DEVICE CONNECTION STRING WITH x509=true>';
var certFile = '<PATH-TO-CERTIFICATE-FILE>';
var keyFile = '<PATH-TO-KEY-FILE>';
var passphrase = '<KEY PASSPHRASE IF ANY>';

// fromConnectionString must specify a transport constructor, coming from any transport package.
var client = Client.fromConnectionString(connectionString, Protocol);

var options = {
cert : fs.readFileSync(certFile, 'utf-8').toString(),
key : fs.readFileSync(keyFile, 'utf-8').toString(),
passphrase: passphrase
};

// Calling setOptions with the x509 certificate and key (and optionally, passphrase) will configure the
client transport to use x509 when connecting to IoT Hub
client.setOptions(options);

Python
The Python SDK currently only supports using X509 certificates and and keys from files, not ones which are
defined inline. In the following example, relevant filepaths are stored in environment variables.
When defining the hostname for your downstream device, use the IoT Edge gateway device's hostname for the
HostName parameter. The hostname can be found in the gateway device's config.yaml file.

import os
from azure.iot.device import IoTHubDeviceClient, X509

HOSTNAME = "[IoT Edge Gateway Hostname]"


DEVICE_ID = "[Device ID]"

def iothub_client_init():
x509 = X509(
cert_file=os.getenv("X509_CERT_FILE"),
key_file=os.getenv("X509_KEY_FILE")
)

client = IoTHubDeviceClient.create_from_x509_certificate(
x509=x509,
hostname=HOSTNAME,
device_id=DEVICE_ID
)
)

if __name__ == '__main__':
iothub_client_init()

Java
For an example of a Java program authenticating to IoT Hub with X.509 certificates, see the Java IoT SDK's
SendEventX509.java sample. Some of the key lines of that sample are included here to demonstrate the
authentication process.
When defining the connection string for your downstream device, use the IoT Edge gateway device's hostname
for the HostName parameter. The hostname can be found in the gateway device's config.yaml file.
//PEM encoded representation of the public key certificate
private static String publicKeyCertificateString =
"-----BEGIN CERTIFICATE-----\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"-----END CERTIFICATE-----\n";

//PEM encoded representation of the private key


private static String privateKeyString =
"-----BEGIN EC PRIVATE KEY-----\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" +
"-----END EC PRIVATE KEY-----\n";

DeviceClient client = new DeviceClient(connectionString, protocol, publicKeyCertificateString, false,


privateKeyString, false);

Next steps
By completing this article, you should have an IoT Edge device working as a transparent gateway and a
downstream device registered with an IoT hub. Next, you need to configure your downstream devices to trust the
gateway device and send messages to it. For more information, see Connect a downstream device to an Azure
IoT Edge gateway.
Connect a downstream device to an Azure IoT Edge
gateway
11/24/2019 • 12 minutes to read • Edit Online

This article provides instructions for establishing a trusted connection between downstream devices and IoT
Edge transparent gateways. In a transparent gateway scenario, one or more devices can pass their messages
through a single gateway device that maintains the connection to IoT Hub. A downstream device can be any
application or platform that has an identity created with the Azure IoT Hub cloud service. In many cases, these
applications use the Azure IoT device SDK. A downstream device could even be an application running on the
IoT Edge gateway device itself.
There are three general steps to set up a successful transparent gateway connection. This article covers the third
step:
1. The gateway device needs to securely connect to downstream devices, receive communications from
downstream devices, and route messages to the proper destination. For more information, see Configure an
IoT Edge device to act as a transparent gateway.
2. The downstream device needs a device identity to be able to authenticate with IoT Hub, and know to
communicate through its gateway device. For more information, see Authenticate a downstream device to
Azure IoT Hub.
3. The downstream device needs to be able to securely connect to its gateway device.
This article identifies common problems with downstream device connections and guides you in setting up your
downstream devices by:
Explaining transport layer security (TLS ) and certificate fundamentals.
Explaining how TLS libraries work across different operating systems and how each operating system deals
with certificates.
Walking through Azure IoT samples in several languages to help get you started.
In this article, the terms gateway and IoT Edge gateway refer to an IoT Edge device configured as a transparent
gateway.

Prerequisites
Have the azure-iot-test-only.root.ca.cert.pem certificate file that was generated in Configure an IoT Edge
device to act as a transparent gateway available on your downstream device. Your downstream device uses this
certificate to validate the identity of the gateway device.

Prepare a downstream device


A downstream device can be any application or platform that has an identity created with the Azure IoT Hub
cloud service. In many cases, these applications use the Azure IoT device SDK. A downstream device could even
be an application running on the IoT Edge gateway device itself. However, another IoT Edge device cannot be
downstream of an IoT Edge gateway.
NOTE
IoT devices that have identities registered in IoT Hub can use module twins to isolate different process, hardware, or
functions on a single device. IoT Edge gateways support downstream module connections using symmetric key
authentication but not X.509 certificate authentication.

To connect a downstream device to an IoT Edge gateway, you need two things:
A device or application that's configured with an IoT Hub device connection string appended with
information to connect it to the gateway.
This step is explained in Authenticate a downstream device to Azure IoT Hub.
The device or application has to trust the gateway's root CA certificate to validate the TLS connections to
the gateway device.
This step is explained in detail in the rest of this article. This step can be performed one of two ways: by
installing the CA certificate in the operating system's certificate store, or (for certain languages) by
referencing the certificate within applications using the Azure IoT SDKs.

TLS and certificate fundamentals


The challenge of securely connecting downstream devices to IoT Edge is just like any other secure client/server
communication that occurs over the internet. A client and a server securely communicate over the internet using
Transport layer security (TLS ). TLS is built using standard Public key infrastructure (PKI) constructs called
certificates. TLS is a fairly involved specification and addresses a wide range of topics related to securing two
endpoints. This section summarizes the concepts relevant for you to securely connect devices to an IoT Edge
gateway.
When a client connects to a server, the server presents a chain of certificates, called the server certificate chain. A
certificate chain typically comprises a root certificate authority (CA) certificate, one or more intermediate CA
certificates, and finally the server's certificate itself. A client establishes trust with a server by cryptographically
verifying the entire server certificate chain. This client validation of the server certificate chain is called server
chain validation. The client cryptographically challenges the service to prove possession of the private key
associated with the server certificate in a process called proof of possession. The combination of server chain
validation and proof of possession is called server authentication. To validate a server certificate chain, a client
needs a copy of the root CA certificate that was used to create (or issue) the server's certificate. Normally when
connecting to websites, a browser comes pre-configured with commonly used CA certificates so the client has a
seamless process.
When a device connects to Azure IoT Hub, the device is the client and the IoT Hub cloud service is the server. The
IoT Hub cloud service is backed by a root CA certificate called Baltimore CyberTrust Root, which is publicly
available and widely used. Since the IoT Hub CA certificate is already installed on most devices, many TLS
implementations (OpenSSL, Schannel, LibreSSL ) automatically use it during server certificate validation. A
device that may successfully connect to IoT Hub may have issues trying to connect to an IoT Edge gateway.
When a device connects to an IoT Edge gateway, the downstream device is the client and the gateway device is
the server. Azure IoT Edge allows operators (or users) to build gateway certificate chains however they see fit.
The operator may choose to use a public CA certificate, like Baltimore, or use a self-signed (or in-house) root CA
certificate. Public CA certificates often have a cost associated with them, so are typically used in production
scenarios. Self-signed CA certificates are preferred for development and testing. The transparent gateway setup
articles listed in the introduction use self-signed root CA certificates.
When you use a self-signed root CA certificate for an IoT Edge gateway, it needs to be installed on or provided to
all the downstream devices attempting to connect to the gateway.
To learn more about IoT Edge certificates and some production implications, see IoT Edge certificate usage
details.

Provide the root CA certificate


To verify the gateway device's certificates, the downstream device needs its own copy of the root CA certificate. If
you used the scripts provided in the IoT Edge git repository to create test certificates, then the root CA certificate
is called azure-iot-test-only.root.ca.cert.pem. If you haven't already as part of the other downstream device
preparation steps, move this certificate file to any directory on your downstream device. You can use a service
like Azure Key Vault or a function like Secure copy protocol to move the certificate file.

Install certificates in the OS


Installing the root CA certificate in the operating system's certificate store generally allows most applications to
use the root CA certificate. There are some exceptions, like NodeJS applications that don't use the OS certificate
store but rather use the Node runtime's internal certificate store. If you can't install the certificate at the operating
system level, skip ahead to Use certificates with Azure IoT SDKs.
Ubuntu
The following commands are an example of how to install a CA certificate on an Ubuntu host. This example
assumes that you're using the azure-iot-test-only.root.ca.cert.pem certificate from the prerequisites articles,
and that you've copied the certificate into a location on the downstream device.

sudo cp <path>/azure-iot-test-only.root.ca.cert.pem /usr/local/share/ca-certificates/azure-iot-test-


only.root.ca.cert.pem.crt
sudo update-ca-certificates

You should see a message that says, "Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done."
Windows
The following steps are an example of how to install a CA certificate on a Windows host. This example assumes
that you're using the azure-iot-test-only.root.ca.cert.pem certificate from the prerequisites articles, and that
you've copied the certificate into a location on the downstream device.
You can install certificates using PowerShell's Import-Certificate as an administrator:

import-certificate <file path>\azure-iot-test-only.root.ca.cert.pem -certstorelocation


cert:\LocalMachine\root

You can also install certificates using the certlm utility:


1. In the Start menu, search for and select Manage computer certificates. A utility called certlm opens.
2. Navigate to Certificates - Local Computer > Trusted Root Certification Authorities.
3. Right-click Certificates and select All Tasks > Import. The certificate import wizard should launch.
4. Follow the steps as directed and import certificate file <path>/azure-iot-test-only.root.ca.cert.pem . When
completed, you should see a "Successfully imported" message.
You can also install certificates programmatically using .NET APIs, as shown in the .NET sample later in this
article.
Typically applications use the Windows provided TLS stack called Schannel to securely connect over TLS.
Schannel requires that any certificates be installed in the Windows certificate store before attempting to establish
a TLS connection.

Use certificates with Azure IoT SDKs


This section describes how the Azure IoT SDKs connect to an IoT Edge device using simple sample applications.
The goal of all the samples is to connect the device client and send telemetry messages to the gateway, then
close the connection and exit.
Have two things ready before using the application-level samples:
Your downstream device's IoT Hub connection string modified to point to the gateway device, and any
certificates required to authenticate your downstream device to IoT Hub. For more information, see
Authenticate a downstream device to Azure IoT Hub.
The full path to the root CA certificate that you copied and saved somewhere on your downstream device.
For example, <path>/azure-iot-test-only.root.ca.cert.pem .
NodeJS
This section provides a sample application to connect an Azure IoT NodeJS device client to an IoT Edge gateway.
For NodeJS applications, you must install the root CA certificate at the application level as shown here. NodeJS
applications don't use the system's certificate store.
1. Get the sample for edge_downstream_device.js from the Azure IoT device SDK for Node.js samples repo.
2. Make sure that you have all the prerequisites to run the sample by reviewing the readme.md file.
3. In the edge_downstream_device.js file, update the connectionString and edge_ca_cert_path variables.
4. Refer to the SDK documentation for instructions on how to run the sample on your device.
To understand the sample that you're running, the following code snippet is how the client SDK reads the
certificate file and uses it to establish a secure TLS connection:

// Provide the Azure IoT device client via setOptions with the X509
// Edge root CA certificate that was used to setup the Edge runtime
var options = {
ca : fs.readFileSync(edge_ca_cert_path, 'utf-8'),
};

.NET
This section introduces a sample application to connect an Azure IoT .NET device client to an IoT Edge gateway.
However, .NET applications are automatically able to use any installed certificates in the system's certificate store
on both Linux and Windows hosts.
1. Get the sample for EdgeDownstreamDevice from the IoT Edge .NET samples folder.
2. Make sure that you have all the prerequisites to run the sample by reviewing the readme.md file.
3. In the Properties / launchSettings.json file, update the DEVICE_CONNECTION_STRING and
CA_CERTIFICATE_PATH variables. If you want to use the certificate installed in the trusted certificate store
on the host system, leave this variable blank.
4. Refer to the SDK documentation for instructions on how to run the sample on your device.
To programmatically install a trusted certificate in the certificate store via a .NET application, refer to the
InstallCACert() function in the EdgeDownstreamDevice / Program.cs file. This operation is idempotent, so
can be run multiple times with the same values with no additional effect.
C
This section introduces a sample application to connect an Azure IoT C device client to an IoT Edge gateway. The
C SDK can operate with many TLS libraries, including OpenSSL, WolfSSL, and Schannel. For more information,
see the Azure IoT C SDK.
1. Get the iotedge_downstream_device_sample application from the Azure IoT device SDK for C samples.
2. Make sure that you have all the prerequisites to run the sample by reviewing the readme.md file.
3. In the iotedge_downstream_device_sample.c file, update the connectionString and edge_ca_cert_path
variables.
4. Refer to the SDK documentation for instructions on how to run the sample on your device.
The Azure IoT device SDK for C provides an option to register a CA certificate when setting up the client. This
operation doesn't install the certificate anywhere, but rather uses a string format of the certificate in memory.
The saved certificate is provided to the underlying TLS stack when establishing a connection.

(void)IoTHubDeviceClient_SetOption(device_handle, OPTION_TRUSTED_CERT, cert_string);

On Windows hosts, if you're not using OpenSSL or another TLS library, the SDK default to using Schannel. For
Schannel to work, the IoT Edge root CA certificate should be installed in the Windows certificate store, not set
using the IoTHubDeviceClient_SetOption operation.
Java
This section introduces a sample application to connect an Azure IoT Java device client to an IoT Edge gateway.
1. Get the sample for Send-event from the Azure IoT device SDK for Java samples.
2. Make sure that you have all the prerequisites to run the sample by reviewing the readme.md file.
3. Refer to the SDK documentation for instructions on how to run the sample on your device.
Python
This section introduces a sample application to connect an Azure IoT Python device client to an IoT Edge
gateway.
1. Get the sample for send_message from the Azure IoT device SDK for Python samples.
2. Ensure that you are either running in an IoT Edge container, or in a debug scenario, have the
EdgeHubConnectionString and EdgeModuleCACertificateFile environment variables set.
3. Refer to the SDK documentation for instructions on how to run the sample on your device.

Test the gateway connection


Use this sample command to test that your downstream device can connect to the gateway device:

openssl s_client -connect mygateway.contoso.com:8883 -CAfile <CERTDIR>/certs/azure-iot-test-


only.root.ca.cert.pem -showcerts

This command tests connections over MQTTS (port 8883). If you're using a different protocol, adjust the
command as neccessary for AMQPS (5671) or HTTPS (433).
The output of this command may be long, including information about all the certificates in the chain. If your
connection is successful, you'll see a line like Verification: OK or Verify return code: 0 (ok) .

Troubleshoot the gateway connection


If your leaf device has intermittent connection to its gateway device, try the following steps for resolution.
1. Is the gateway hostname in the connection string the same as the hostname value in the IoT Edge config.yaml
file on the gateway device?
2. Is the gateway hostname resolvable to an IP Address? You can resolve intermittent connections either by
using DNS or by adding a host file entry on the leaf device.
3. Are communication ports open in your firewall? Communication based on the protocol used
(MQTTS:8883/AMQPS:5671/HTTPS:433) must be possible between downstream device and the transparent
IoT Edge.

Next steps
Learn how IoT Edge can extend offline capabilities to downstream devices.
Connect Modbus TCP devices through an IoT Edge
device gateway
11/24/2019 • 2 minutes to read • Edit Online

If you want to connect IoT devices that use Modbus TCP or RTU protocols to an Azure IoT hub, use an IoT Edge
device as a gateway. The gateway device reads data from your Modbus devices, then communicates that data to
the cloud using a supported protocol.

This article covers how to create your own container image for a Modbus module (or you can use a prebuilt
sample) and then deploy it to the IoT Edge device that will act as your gateway.
This article assumes that you're using Modbus TCP protocol. For more information about how to configure the
module to support Modbus RTU, see the Azure IoT Edge Modbus module project on GitHub.

Prerequisites
An Azure IoT Edge device. For a walkthrough on how to set up one, see Deploy Azure IoT Edge on Windows or
Linux.
The primary key connection string for the IoT Edge device.
A physical or simulated Modbus device that supports Modbus TCP.

Prepare a Modbus container


If you want to test the Modbus gateway functionality, Microsoft has a sample module that you can use. You can
access the module from the Azure Marketplace, Modbus, or with the image URI,
mcr.microsoft.com/azureiotedge/modbus:1.0.
If you want to create your own module and customize it for your environment, there is an open-source Azure IoT
Edge Modbus module project on GitHub. Follow the guidance in that project to create your own container image.
To create a container image, refer to Develop C# modules in Visual Studio or Develop modules in Visual Studio
Code. Those articles provide instructions on creating new modules and publishing container images to a registry.

Try the solution


This section walks through deploying Microsoft's sample Modbus module to your IoT Edge device.
1. On the Azure portal, go to your IoT hub.
2. Go to IoT Edge and click on your IoT Edge device.
3. Select Set modules.
4. Add the Modbus module:
a. Click Add and select IoT Edge module.
b. In the Name field, enter "modbus".
c. In the Image field, enter the image URI of the sample container:
mcr.microsoft.com/azureiotedge/modbus:1.0 .

d. Check the Enable box to update the module twin's desired properties.
e. Copy the following JSON into the text box. Change the value of SlaveConnection to the IPv4
address of your Modbus device.

{
"properties.desired":{
"PublishInterval":"2000",
"SlaveConfigs":{
"Slave01":{
"SlaveConnection":"<IPV4 address>","HwId":"PowerMeter-0a:01:01:01:01:01",
"Operations":{
"Op01":{
"PollingInterval": "1000",
"UnitId":"1",
"StartAddress":"40001",
"Count":"2",
"DisplayName":"Voltage"
}
}
}
}
}
}

f. Select Save.
5. Back in the Add Modules step, select Next.
6. In the Specify Routes step, copy the following JSON into the text box. This route sends all messages
collected by the Modbus module to IoT Hub. In this route, modbusOutput is the endpoint that Modbus
module uses to output data and $upstream is a special destination that tells IoT Edge hub to send
messages to IoT Hub.

{
"routes": {
"modbusToIoTHub":"FROM /messages/modules/modbus/outputs/modbusOutput INTO $upstream"
}
}

7. Select Next.
8. In the Review Deployment step, select Submit.
9. Return to the device details page and select Refresh. You should see the new modbus module running
along with the IoT Edge runtime.

View data
View the data coming through the modbus module:
iotedge logs modbus

You can also view the telemetry the device is sending by using the Azure IoT Hub Toolkit extension for Visual
Studio Code (formerly Azure IoT Toolkit extension).

Next steps
To learn more about how IoT Edge devices can act as gateways, see Create an IoT Edge device that acts as a
transparent gateway.
For more information about how IoT Edge modules work, see Understand Azure IoT Edge modules.
Configure an IoT Edge device to communicate
through a proxy server
11/24/2019 • 9 minutes to read • Edit Online

IoT Edge devices send HTTPS requests to communicate with IoT Hub. If your device is connected to a network
that uses a proxy server, you need to configure the IoT Edge runtime to communicate through the server. Proxy
servers can also affect individual IoT Edge modules if they make HTTP or HTTPS requests that aren't routed
through the IoT Edge hub.
This article walks through the following four steps to configure and then manage an IoT Edge device behind a
proxy server:
1. Install the IoT Edge runtime on your device.
The IoT Edge installation scripts pull packages and files from the internet, so your device needs to
communicate through the proxy server to make those requests. For detailed steps, see the Install the
runtime through a proxy section of this article. For Windows devices, the installation script also provides
an Offline installation option.
This step is a one-time process performed on the IoT Edge device when you first set it up. The same
connections are also required when you update the IoT Edge runtime.
2. Configure the Docker daemon and the IoT Edge daemon on your device.
IoT Edge uses two daemons on the device, both of which need to make web requests through the proxy
server. The IoT Edge daemon is responsible for communications with IoT Hub. The Moby daemon is
responsible for container management, so communicates with container registries. For detailed steps, see
the Configure the daemons section of this article.
This step is a one-time process performed on the IoT Edge device when you first set it up.
3. Configure the IoT Edge agent properties in the config.yaml file on your device.
The IoT Edge daemon starts the edgeAgent module initially, but then the edgeAgent module is
responsible for retrieving the deployment manifest from IoT Hub and starting all the other modules. For
the IoT Edge agent to make the initial connection to IoT Hub, configure the edgeAgent module
environment variables manually on the device itself. After the initial connection, you can configure the
edgeAgent module remotely. For detailed steps, see the Configure the IoT Edge agent section of this
article.
This step is a one-time process performed on the IoT Edge device when you first set it up.
4. For all future module deployments, set environment variables for any module communicating
through the proxy.
Once your IoT Edge device is set up and connected to IoT Hub through the proxy server, you need to
maintain the connection in all future module deployments. For detailed steps, see the Configure
deployment manifests section of this article.
This step is an ongoing process performed remotely so that every new module or deployment update
maintains the device's ability to communicate through the proxy server.

Know your proxy URL


Before you begin any of the steps in this article, you need to know your proxy URL.
Proxy URLs take the following format: protocol://proxy_host:proxy_port.
The protocol is either HTTP or HTTPS. The Docker daemon can use either protocol, depending on your
container registry settings, but the IoT Edge daemon and runtime containers should always use HTTP to
connect to the proxy.
The proxy_host is an address for the proxy server. If your proxy server requires authentication, you can
provide your credentials as part of the proxy host with the following format:
user:password@proxy_host.
The proxy_port is the network port at which the proxy responds to network traffic.

Install the runtime through a proxy


Whether your IoT Edge device runs on Windows or Linux, you need to access the installation packages through
the proxy server. Depending on your operating system, follow the steps to install the IoT Edge runtime through a
proxy server.
Linux
If you're installing the IoT Edge runtime on a Linux device, configure the package manager to go through your
proxy server to access the installation package. For example, Set up apt-get to use a http-proxy. Once your
package manager is configured, follow the instructions in Install Azure IoT Edge runtime on Linux as usual.
Windows
If you're installing the IoT Edge runtime on a Windows device, you need to go through the proxy server twice.
The first connection downloads the installer script file, and the second connection is during the installation to
download the necessary components. You can configure proxy information in Windows settings, or include your
proxy information directly in the PowerShell commands.
The following steps demonstrate an example of a windows installation using the -proxy argument:
1. The Invoke-WebRequest command needs proxy information to access the installer script. Then the
Deploy-IoTEdge command needs the proxy information to download the installation files.

. {Invoke-WebRequest -proxy <proxy URL> -useb aka.ms/iotedge-win} | Invoke-Expression; Deploy-IoTEdge


-proxy <proxy URL>

2. The Initialize-IoTEdge command doesn't need to go through the proxy server, so the second step only
requires proxy information for Invoke-WebRequest.

. {Invoke-WebRequest -proxy <proxy URL> -useb aka.ms/iotedge-win} | Invoke-Expression; Initialize-


IoTEdge

If you have complicated credentials for the proxy server that can't be included in the URL, use the
-ProxyCredential parameter within -InvokeWebRequestParameters . For example,

$proxyCredential = (Get-Credential).GetNetworkCredential()
. {Invoke-WebRequest -proxy <proxy URL> -ProxyCredential $proxyCredential -useb aka.ms/iotedge-win} |
Invoke-Expression; `
Deploy-IoTEdge -InvokeWebRequestParameters @{ '-Proxy' = '<proxy URL>'; '-ProxyCredential' =
$proxyCredential }

For more information about proxy parameters, see Invoke-WebRequest. For more information about Windows
installation options, including offline installation, see Install Azure IoT Edge runtime on Windows.

Configure the daemons


IoT Edge relies on two daemons running on the IoT Edge device. The Moby daemon makes web requests to pull
container images from container registries. The IoT Edge daemon makes web requests to communicate with IoT
Hub.
Both the Moby and the IoT Edge daemons need to be configured to use the proxy server for ongoing device
functionality. This step takes place on the IoT Edge device during initial device setup.
Moby daemon
Since Moby is built on Docker, refer to the Docker documentation to configure the Moby daemon with
environment variables. Most container registries (including DockerHub and Azure Container Registries) support
HTTPS requests, so the parameter that you should set is HTTPS_PROXY. If you're pulling images from a
registry that doesn't support transport layer security (TLS ), then you should set the HTTP_PROXY parameter.
Choose the article that applies to your IoT Edge device operating system:
Configure Docker daemon on Linux
The Moby daemon on Linux devices keeps the name Docker.
Configure Docker daemon on Windows
The Moby daemon on Windows devices is called iotedge-moby. The names are different because it's
possible to run both Docker Desktop and Moby in parallel on a Windows device.
IoT Edge daemon
The IoT Edge daemon is configured in a similar manner to the Moby daemon. Use the following steps to set an
environment variable for the service, based on your operating system.
The IoT Edge daemon always uses HTTPS to send requests to IoT Hub.
Linux
Open an editor in the terminal to configure the IoT Edge daemon.

sudo systemctl edit iotedge

Enter the following text, replacing <proxy URL> with your proxy server address and port. Then, save and exit.

[Service]
Environment="https_proxy=<proxy URL>"

Refresh the service manager to pick up the new configuration for IoT Edge.

sudo systemctl daemon-reload

Restart IoT Edge for the changes to take effect.

sudo systemctl restart iotedge

Verify that your environment variable was created, and the new configuration was loaded.

systemctl show --property=Environment iotedge


Windows
Open a PowerShell window as an administrator and run the following command to edit the registry with the
new environment variable. Replace <proxy url> with your proxy server address and port.

reg add HKLM\SYSTEM\CurrentControlSet\Services\iotedge /v Environment /t REG_MULTI_SZ /d https_proxy=<proxy


URL>

Restart IoT Edge for the changes to take effect.

Restart-Service iotedge

Configure the IoT Edge agent


The IoT Edge agent is the first module to start on any IoT Edge device. It's started for the first time based on the
information in the IoT Edge config.yaml file. The IoT Edge agent then connects to IoT Hub to retrieve
deployment manifests, which declare what other modules should be deployed on the device.
This step takes place once on the IoT Edge device during initial device setup.
1. Open the config.yaml file on your IoT Edge device. On Linux systems, this file is located at
/etc/iotedge/config.yaml. On Windows systems, this file is located at
C:\ProgramData\iotedge\config.yaml. The configuration file is protected, so you need administrative
privileges to access it. On Linux systems, use the sudo command before opening the file in your
preferred text editor. On Windows, open a text editor like Notepad as administrator and then open the file.
2. In the config.yaml file, find the Edge Agent module spec section. The IoT Edge agent definition includes
an env parameter where you can add environment variables.
3. Remove the curly brackets that are placeholders for the env parameter, and add the new variable on a new
line. Remember that indents in YAML are two spaces.

https_proxy: "<proxy URL>"

4. The IoT Edge runtime uses AMQP by default to talk to IoT Hub. Some proxy servers block AMQP ports.
If that's the case, then you also need to configure edgeAgent to use AMQP over WebSocket. Add a
second environment variable.

UpstreamProtocol: "AmqpWs"

5. Save the changes to config.yaml and close the editor. Restart IoT Edge for the changes to take effect.
Linux:
sudo systemctl restart iotedge

Windows:

Restart-Service iotedge

Configure deployment manifests


Once your IoT Edge device is configured to work with your proxy server, you need to continue to declare the
environment variables in future deployment manifests. You can edit deployment manifests either using the
Azure portal wizard or by editing a deployment manifest JSON file.
Always configure the two runtime modules, edgeAgent and edgeHub, to communicate through the proxy server
so they can maintain a connection with IoT Hub. If you remove the proxy information from the edgeAgent
module, the only way to reestablish connection is by editing the config.yaml file on the device, as described in the
previous section.
Other IoT Edge modules that connect to the internet should be configured to communicate through the proxy
server, too. However, modules that route their messages through edgeHub or that only communicate with other
modules on the device don't need the proxy server details.
This step is ongoing throughout the life of the IoT Edge device.
Azure portal
When you use the Set modules wizard to create deployments for IoT Edge devices, every module has an
Environment Variables section that you can use to configure proxy server connections.
To configure the IoT Edge agent and IoT Edge hub modules, select Configure advanced Edge Runtime
settings on the first step of the wizard.
Add the https_proxy environment variable to both the IoT Edge agent and IoT Edge hub module definitions. If
you included the UpstreamProtocol environment variable in the config.yaml file on your IoT Edge device, add
that to the IoT Edge agent module definition too.
All other modules that you add to a deployment manifest follow the same pattern. In the page where you set the
module name and image, there is an environment variables section.
JSON deployment manifest files
If you create deployments for IoT Edge devices using the templates in Visual Studio Code or by manually
creating JSON files, you can add the environment variables directly to each module definition.
Use the following JSON format:

"env": {
"https_proxy": {
"value": "<proxy URL>"
}
}

With the environment variables included, your module definition should look like the following edgeHub
example:
"edgeHub": {
"type": "docker",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-hub:1.0",
"createOptions": ""
},
"env": {
"https_proxy": {
"value": "http://proxy.example.com:3128"
}
},
"status": "running",
"restartPolicy": "always"
}

If you included the UpstreamProtocol environment variable in the confige.yaml file on your IoT Edge device,
add that to the IoT Edge agent module definition too.

"env": {
"https_proxy": {
"value": "<proxy URL>"
},
"UpstreamProtocol": {
"value": "AmqpWs"
}
}

Next steps
Learn more about the roles of the IoT Edge runtime.
Troubleshoot installation and configuration errors with Common issues and resolutions for Azure IoT Edge
Give modules access to a device's local storage
10/14/2019 • 2 minutes to read • Edit Online

In addition to storing data using Azure storage services or in your device's container storage, you can also dedicate
storage on the host IoT Edge device itself for improved reliability, especially when operating offline.

Link module storage to device storage


To enable a link from module storage to the storage on the host system, create an environment variable for your
module that points to a storage folder in the container. Then, use the create options to bind that storage folder to a
folder on the host machine.
For example, if you wanted to enable the IoT Edge hub to store messages in your device's local storage and
retrieve them later, you can configure the environment variables and the create options in the Azure portal in the
Configure advanced Edge Runtime settings section.
1. For both IoT Edge hub and IoT Edge agent, add an environment variable called storageFolder that points
to a directory in the module.
2. For both IoT Edge hub and IoT Edge agent, add binds to connect a local directory on the host machine to a
directory in the module. For example:

Or, you can configure the local storage directly in the deployment manifest. For example:
"systemModules": {
"edgeAgent": {
"settings": {
"image": "mcr.microsoft.com/azureiotedge-agent:1.0",
"createOptions": {
"HostConfig": {
"Binds":["<HostStoragePath>:<ModuleStoragePath>"]
}
}
},
"type": "docker",
"env": {
"storageFolder": {
"value": "<ModuleStoragePath>"
}
}
},
"edgeHub": {
"settings": {
"image": "mcr.microsoft.com/azureiotedge-hub:1.0",
"createOptions": {
"HostConfig": {
"Binds":["<HostStoragePath>:<ModuleStoragePath>"],
"PortBindings":{"5671/tcp":[{"HostPort":"5671"}],"8883/tcp":
[{"HostPort":"8883"}],"443/tcp":[{"HostPort":"443"}]}}}
},
"type": "docker",
"env": {
"storageFolder": {
"value": "<ModuleStoragePath>"
}
},
"status": "running",
"restartPolicy": "always"
}
}

Replace <HostStoragePath> and <ModuleStoragePath> with your host and module storage path; both values must
be an absolute path.
For example, on a Linux system, "Binds":["/etc/iotedge/storage/:/iotedge/storage/"] means the directory
/etc/iotedge/storage on your host system is mapped to the directory /iotedge/storage/ in the container. On a
Windows system, as another example, "Binds":["C:\\temp:C:\\contemp"] means the directory C:\temp on your
host system is mapped to the directory C:\contemp in the container.
Additionally, on Linux devices, make sure that the user profile for your module has the required read, write, and
execute permissions to the host system directory. Returning to the earlier example of enabling IoT Edge hub to
store messages in your device's local storage, you need to grant permissions to its user profile, UID 1000. (The IoT
Edge agent operates as root, so it doesn't need additional permissions.) There are several ways to manage
directory permissions on Linux systems, including using chown to change the directory owner and then chmod to
change the permissions, such as:

sudo chown 1000 <HostStoragePath>


sudo chmod 700 <HostStoragePath>

You can find more details about create options from docker docs.

Next steps
For an additional example of accessing host storage from a module, see Store data at the edge with Azure Blob
Storage on IoT Edge.
Store data at the edge with Azure Blob Storage on IoT Edge
11/24/2019 • 11 minutes to read • Edit Online

Azure Blob Storage on IoT Edge provides a block blob storage solution at the edge. A blob storage module on your IoT Edge device behaves like an
Azure block blob service, except the block blobs are stored locally on your IoT Edge device. You can access your blobs using the same Azure storage
SDK methods or block blob API calls that you're already used to. This article explains the concepts related to Azure Blob Storage on IoT Edge container
that runs a blob service on your IoT Edge device.
This module is useful in scenarios:
where data needs to be stored locally until it can be processed or transferred to the cloud. This data can be videos, images, finance data, hospital
data, or any other unstructured data.
when devices are located in a place with limited connectivity.
when you want to efficiently process the data locally to get low latency access to the data, such that you can respond to emergencies as quickly as
possible.
when you want to reduce bandwidth costs and avoid transferring terabytes of data to the cloud. You can process the data locally and send only the
processed data to the cloud.
Watch the video for quick introduction

This module comes with deviceToCloudUpload and deviceAutoDelete features.


deviceToCloudUpload is a configurable functionality. This function automatically uploads the data from your local blob storage to Azure with
intermittent internet connectivity support. It allows you to:
Turn ON/OFF the deviceToCloudUpload feature.
Choose the order in which the data is copied to Azure like NewestFirst or OldestFirst.
Specify the Azure Storage account to which you want your data uploaded.
Specify the containers you want to upload to Azure. This module allows you to specify both source and target container names.
Choose the ability to delete the blobs immediately, after upload to cloud storage is finished
Do full blob upload (using Put Blob operation) and block level upload (using Put Block and Put Block List operations).
This module uses block level upload, when your blob consists of blocks. Here are some of the common scenarios:
Your application updates some blocks of a previously uploaded blob, this module uploads only the updated blocks and not the whole blob.
The module is uploading blob and internet connection goes away, when the connectivity is back again it uploads only the remaining blocks and not
the whole blob.
If an unexpected process termination (like power failure) happens during a blob upload, all blocks that were due for the upload will be uploaded again
once the module comes back online.
deviceAutoDelete is a configurable functionality. This function automatically deletes your blobs from the local storage when the specified duration
(measured in minutes) expires. It allows you to:
Turn ON/OFF the deviceAutoDelete feature.
Specify the time in minutes (deleteAfterMinutes) after which the blobs will be automatically deleted.
Choose the ability to retain the blob while it's uploading if the deleteAfterMinutes value expires.

Prerequisites
An Azure IoT Edge device:
You can use your development machine or a virtual machine as an IoT Edge device by following the steps in the quickstart for Linux or
Windows devices.
Refer to Azure IoT Edge supported systems for a list of supported operating systems and architectures. The Azure Blob Storage on IoT Edge
module supports following architectures:
Windows AMD64
Linux AMD64
Linux ARM32
Linux ARM64 (preview )
Cloud resources:
A standard-tier IoT Hub in Azure.

deviceToCloudUpload and deviceAutoDelete properties


Use the module's desired properties to set deviceToCloudUploadProperties and deviceAutoDeleteProperties. Desired properties can be set
during deployment or changed later by editing the module twin without the need to redeploy. We recommend checking the "Module Twin" for
reported configuration and configurationValidation to make sure values are correctly propagated.

deviceToCloudUploadProperties
The name of this setting is deviceToCloudUploadProperties . If you are using the IoT Edge simulator, set the values to the related environment variables
for these properties, which you can find in the explanation section.

PROPERTY POSSIBLE VALUES EXPLANATION

uploadOn true, false Set to false by default. If you want to turn the
feature on, set this field to true .

Environment variable:
deviceToCloudUploadProperties__uploadOn=
{false,true}

uploadOrder NewestFirst, OldestFirst Allows you to choose the order in which the data is
copied to Azure. Set to OldestFirst by default. The
order is determined by last modified time of Blob.

Environment variable:
deviceToCloudUploadProperties__uploadOrder=
{NewestFirst,OldestFirst}

cloudStorageConnectionString "DefaultEndpointsProtocol=https;AccountName=
<your Azure Storage Account Name>;AccountKey=
<your Azure Storage Account
Key>;EndpointSuffix=<your end point suffix>"
is a connection string that allows you to specify the
storage account to which you want your data
uploaded. Specify Azure Storage Account Name ,
Azure Storage Account Key , End point suffix .
Add appropriate EndpointSuffix of Azure where data
will be uploaded, it varies for Global Azure,
Government Azure, and Microsoft Azure Stack.

You can choose to specify Azure Storage SAS


connection string here. But you have to update this
property when it expires.

Environment variable:
deviceToCloudUploadProperties__cloudStorageConnectionString=
<connection string>

storageContainersForUpload "<source container name1>": {"target": " Allows you to specify the container names you want
<target container name>"} to upload to Azure. This module allows you to specify
, both source and target container names. If you don't
specify the target container name, it will automatically
"<source container name1>": {"target": "%h- assign the container name as
%d-%m-%c"}
<IoTHubName>-<IotEdgeDeviceID>-<ModuleName>-
, <SourceContainerName>
. You can create template strings for target container
"<source container name1>": {"target": "%d- name, check out the possible values column.
%c"}
* %h -> IoT Hub Name (3-50 characters).
* %d -> IoT Edge Device ID (1 to 129 characters).
* %m -> Module Name (1 to 64 characters).
* %c -> Source Container Name (3 to 63 characters).

Maximum size of the container name is 63 characters,


while automatically assigning the target container
name if the size of container exceeds 63 characters it
will trim each section (IoTHubName, IotEdgeDeviceID,
ModuleName, SourceContainerName) to 15
characters.

Environment variable:
deviceToCloudUploadProperties__storageContainersForUpload__<sour
<targetName>

deleteAfterUpload true, false Set to false by default. When it is set to true , it


will automatically delete the data when upload to
cloud storage is finished.

Environment variable:
deviceToCloudUploadProperties__deleteAfterUpload=
{false,true}

deviceAutoDeleteProperties
The name of this setting is deviceAutoDeleteProperties . If you are using the IoT Edge simulator, set the values to the related environment variables for
these properties, which you can find in the explanation section.
PROPERTY POSSIBLE VALUES EXPLANATION

deleteOn true, false Set to false by default. If you want to turn the
feature on, set this field to true .

Environment variable:
deviceAutoDeleteProperties__deleteOn=
{false,true}

deleteAfterMinutes <minutes> Specify the time in minutes. The module will


automatically delete your blobs from local storage
when this value expires.

Environment variable:
deviceAutoDeleteProperties__
deleteAfterMinutes=<minutes>

retainWhileUploading true, false By default it is set to true , and it will retain the blob
while it is uploading to cloud storage if
deleteAfterMinutes expires. You can set it to false
and it will delete the data as soon as
deleteAfterMinutes expires. Note: For this property to
work uploadOn should be set to true.

Environment variable:
deviceAutoDeleteProperties__retainWhileUploading=
{false,true}

Using SMB share as your local storage


You can provide SMB share as your local storage path, when you deploy Windows container of this module on Windows host.
Make sure the SMB share and IoT device are in mutually trusted domains.
You can run New-SmbGlobalMapping PowerShell command to map the SMB share locally on the IoT device running Windows.
Below are the configuration steps:

$creds = Get-Credential
New-SmbGlobalMapping -RemotePath <remote SMB path> -Credential $creds -LocalPath <Any available drive letter>

Example:
$creds = Get-Credential
New-SmbGlobalMapping -RemotePath \\contosofileserver\share1 -Credential $creds -LocalPath G:

This command will use the credentials to authenticate with the remote SMB server. Then, map the remote share path to G: drive letter (can be any
other available drive letter). The IoT device now have the data volume mapped to a path on the G: drive.
Make sure the user in IoT device can read/write to the remote SMB share.
For your deployment the value of <storage mount> can be G:/ContainerData:C:/BlobRoot.

Granting directory access to container user on Linux


If you have used volume mount for storage in your create options for Linux containers then you don't have to do any extra steps, but if you used bind
mount then these steps are required to run the service correctly.
Following the principle of least privilege to limit the access rights for users to bare minimum permissions they need to perform their work, this module
includes a user (name: absie, ID: 11000) and a user group (name: absie, ID: 11000). If the container is started as root (default user is root), our service
will be started as the low-privilege absie user.
This behavior makes configuration of the permissions on host path binds crucial for the service to work correctly, otherwise the service will crash with
access denied errors. The path that is used in directory binding needs to be accessible by the container user (example: absie 11000). You can grant the
container user access to the directory by executing the commands below on the host:

sudo chown -R 11000:11000 <blob-dir>


sudo chmod -R 700 <blob-dir>

Example:
sudo chown -R 11000:11000 /srv/containerdata
sudo chmod -R 700 /srv/containerdata

If you need to run the service as a user other than absie, you can specify your custom user ID in createOptions under "User" property in your
deployment manifest. In such case you need to use default or root group ID 0 .
"createOptions": {
"User": "<custom user ID>:0"
}

Now, grant the container user access to the directory

sudo chown -R <user ID>:<group ID> <blob-dir>


sudo chmod -R 700 <blob-dir>

Configure log files


For information on configuring log files for your module, see these production best practices.

Connect to your blob storage module


You can use the account name and account key that you configured for your module to access the blob storage on your IoT Edge device.
Specify your IoT Edge device as the blob endpoint for any storage requests that you make to it. You can Create a connection string for an explicit
storage endpoint using the IoT Edge device information and the account name that you configured.
For modules that are deployed on the same device as where the Azure Blob Storage on IoT Edge module is running, the blob endpoint is:
http://<module name>:11002/<account name> .
For modules or applications running on a different device, you have to choose the right endpoint for your network. Depending on your network
setup, choose an endpoint format such that the data traffic from your external module or application can reach the device running the Azure Blob
Storage on IoT Edge module. The blob endpoint for this scenario is one of:
http://<device IP >:11002/<account name>
http://<IoT Edge device hostname>:11002/<account name>
http://<fully qualified domain name>:11002/<account name>

Azure Blob Storage quickstart samples


The Azure Blob Storage documentation includes quickstart sample code in several languages. You can run these samples to test Azure Blob Storage on
IoT Edge by changing the blob endpoint to connect to your local blob storage module.
The following quickstart samples use languages that are also supported by IoT Edge, so you could deploy them as IoT Edge modules alongside the
blob storage module:
.NET
Python
We have a known issue while using this SDK because this version of the module does not return blob creation time. Hence few methods like
list blobs does not work. As a workaround set explicitly API version on the blob client to '2017-04-17'.
Example: block_blob_service._X_MS_VERSION = '2017-04-17'
Node.js
JS/HTML
Ruby
Go
PHP

Connect to your local storage with Azure Storage Explorer


You can use Azure Storage Explorer to connect to your local storage account.
1. Download and install Azure Storage Explorer
2. Connect to Azure Storage using a connection string
3. Provide connection string:
DefaultEndpointsProtocol=http;BlobEndpoint=http://<host device name>:11002/<your local account name>;AccountName=<your local account
name>;AccountKey=<your local account key>;

4. Go through the steps to connect.


5. Create container inside your local storage account
6. Start uploading files as Block blobs.

NOTE
This module does not support Page blobs.

7. You can choose to connect your Azure storage accounts in Storage Explorer, too. This configuration gives you a single view for both your local
storage account and Azure storage account

Supported storage operations


Blob storage modules on IoT Edge use the Azure Storage SDKs, and are consistent with the 2017-04-17 version of the Azure Storage API for block
blob endpoints.
Because not all Azure Blob Storage operations are supported by Azure Blob Storage on IoT Edge, this section lists the status of each.
Account
Supported:
List containers
Unsupported:
Get and set blob service properties
Preflight blob request
Get blob service stats
Get account information
Containers
Supported:
Create and delete container
Get container properties and metadata
List blobs
Get and set container ACL
Set container metadata
Unsupported:
Lease container
Blobs
Supported:
Put, get, and delete blob
Get and set blob properties
Get and set blob metadata
Unsupported:
Lease blob
Snapshot blob
Copy and abort copy blob
Undelete blob
Set blob tier
Block blobs
Supported:
Put block
Put and get block list
Unsupported:
Put block from URL

Event Grid on IoT Edge Integration


Cau t i on

The integration with Event Grid on IoT Edge is in preview


This Azure Blob Storage on IoT Edge module now provides integration with Event Grid on IoT Edge. For detailed information on this integration, see
the tutorial to deploy the modules, publish events and verify event delivery.

Release Notes
Here are the release notes in docker hub for this module

Feedback
Your feedback is important to us to make this module and its features useful and easy to use. Please share your feedback and let us know how we can
improve.
You can reach us at absiotfeedback@microsoft.com

Next steps
Learn how to Deploy Azure Blob Storage on IoT Edge
Stay up-to-date with recent updates and announcement in the Azure Blob Storage on IoT Edge blog
Deploy the Azure Blob Storage on IoT Edge module
to your device
12/1/2019 • 8 minutes to read • Edit Online

There are several ways to deploy modules to an IoT Edge device and all of them work for Azure Blob Storage on
IoT Edge modules. The two simplest methods are to use the Azure portal or Visual Studio Code templates.

Prerequisites
An IoT hub in your Azure subscription.
An IoT Edge device with the IoT Edge runtime installed.
Visual Studio Code and the Azure IoT Tools if deploying from Visual Studio Code.

Deploy from the Azure portal


The Azure portal guides you through creating a deployment manifest and pushing the deployment to an IoT Edge
device.
Select your device
1. Sign in to the Azure portal and navigate to your IoT hub.
2. Select IoT Edge from the menu.
3. Click on the ID of the target device from the list of devices.
4. Select Set Modules.
Configure a deployment manifest
A deployment manifest is a JSON document that describes which modules to deploy, how data flows between the
modules, and desired properties of the module twins. The Azure portal has a wizard that walks you through
creating a deployment manifest, instead of building the JSON document manually. It has three steps: Add
modules, Specify routes, and Review deployment.
Add modules
1. In the Deployment modules section of the page, select Add.
2. From the types of modules in the drop-down list, select IoT Edge Module.
3. Provide a name for the module and then specify the container image:
Name - azureblobstorageoniotedge
Image URI - mcr.microsoft.com/azure-blob-storage:latest

IMPORTANT
Azure IoT Edge is case-sensitive when you make calls to modules, and the Storage SDK also defaults to lowercase.
Although the name of the module in the Azure Marketplace is AzureBlobStorageonIoTEdge, changing the name
to lowercase helps to ensure that your connections to the Azure Blob Storage on IoT Edge module aren't interrupted.

4. The default Container Create Options values define the port bindings that your container needs, but you
also need to add your storage account information and a mount for the storage on your device. Replace the
default JSON in the portal with the JSON below:
{
"Env":[
"LOCAL_STORAGE_ACCOUNT_NAME=<your storage account name>",
"LOCAL_STORAGE_ACCOUNT_KEY=<your storage account key>"
],
"HostConfig":{
"Binds":[
"<storage mount>"
],
"PortBindings":{
"11002/tcp":[{"HostPort":"11002"}]
}
}
}

5. Update the JSON that you copied with the following information:
Replace <your storage account name> with a name that you can remember. Account names should be
3 to 24 characters long, with lowercase letters and numbers. No spaces.
Replace <your storage account key> with a 64-byte base64 key. You can generate a key with tools
like GeneratePlus. You'll use these credentials to access the blob storage from other modules.
Replace <storage mount> according to your container operating system. Provide the name of a
volume or the absolute path to a directory on your IoT Edge device where you want the blob module
to store its data. The storage mount maps a location on your device that you provide to a set location
in the module.
For Linux containers, the format is <storage path or volume>:/blobroot. For example
use volume mount: my-volume:/blobroot
use bind mount: /srv/containerdata:/blobroot. Make sure to follow the steps to grant
directory access to the container user
For Windows containers, the format is <storage path or volume>:C:/BlobRoot. For example
use volume mount: my-volume:C:/blobroot.
use bind mount: C:/ContainerData:C:/BlobRoot.
Instead of using your local drive, you can map your SMB network location, for more
information see using SMB share as your local storage

IMPORTANT
Do not change the second half of the storage mount value, which points to a specific location in the module.
The storage mount should always end with :/blobroot for Linux containers and :C:/BlobRoot for Windows
containers.

6. Set deviceToCloudUploadProperties and deviceAutoDeleteProperties properties for your module by


copying the following JSON and pasting it into the Set module twin's desired properties box. Configure
each property with an appropriate value, save it, and continue with the deployment. If you are using the IoT
Edge simulator, set the values to the related environment variables for these properties, which you can find
in the explanation section of deviceToCloudUploadProperties and deviceAutoDeleteProperties.
{
"properties.desired": {
"deviceAutoDeleteProperties": {
"deleteOn": <true, false>,
"deleteAfterMinutes": <timeToLiveInMinutes>,
"retainWhileUploading":<true,false>
},
"deviceToCloudUploadProperties": {
"uploadOn": <true, false>,
"uploadOrder": "<NewestFirst, OldestFirst>",
"cloudStorageConnectionString": "DefaultEndpointsProtocol=https;AccountName=<your Azure Storage
Account Name>;AccountKey=<your Azure Storage Account Key>; EndpointSuffix=<your end point suffix>",
"storageContainersForUpload": {
"<source container name1>": {
"target": "<target container name1>"
}
},
"deleteAfterUpload":<true,false>
}
}
}
For information on configuring deviceToCloudUploadProperties and deviceAutoDeleteProperties after your
module has been deployed, see Edit the Module Twin. For more information about desired properties, see
Define or update desired properties.
7. Select Save.
8. Select Next to continue to the routes section.
Specify routes
Keep the default routes, and select Next to continue to the review section.
Review deployment
The review section shows you the JSON deployment manifest that was created based on your selections in the
previous two sections. There are also two modules declared that you didn't add: $edgeAgent and $edgeHub.
These two modules make up the IoT Edge runtime and are required defaults in every deployment.
Review your deployment information, then select Submit.
Verify your deployment
After you submit the deployment, you return to the IoT Edge page of your IoT hub.
1. Select the IoT Edge device that you targeted with the deployment to open its details.
2. In the device details, verify that the blob storage module is listed as both Specified in deployment and
Reported by device.
It may take a few moments for the module to be started on the device and then reported back to IoT Hub. Refresh
the page to see an updated status.

Deploy from Visual Studio Code


Azure IoT Edge provides templates in Visual Studio Code to help you develop edge solutions. Use the following
steps to create a new IoT Edge solution with a blob storage module and to configure the deployment manifest.
1. Select View > Command Palette.
2. In the command palette, enter and run the command Azure IoT Edge: New IoT Edge solution.

Follow the prompts in the command palette to create your solution.

FIELD VALUE

Select folder Choose the location on your development machine for


Visual Studio Code to create the solution files.

Provide a solution name Enter a descriptive name for your solution or accept the
default EdgeSolution.

Select module template Choose Existing Module (Enter full image URL).

Provide a module name Enter an all-lowercase name for your module, like
azureblobstorageoniotedge.

It's important to use a lowercase name for the Azure Blob


Storage on IoT Edge module. IoT Edge is case-sensitive
when referring to modules, and the Storage SDK defaults
to lowercase.

Provide Docker image for the module Provide the image URI: mcr.microsoft.com/azure-blob-
storage:latest

Visual Studio Code takes the information you provided, creates an IoT Edge solution, and then loads it in a
new window. The solution template creates a deployment manifest template that includes your blob storage
module image, but you need to configure the module's create options.
3. Open deployment.template.json in your new solution workspace and find the modules section. Make the
following configuration changes:
a. Delete the SimulatedTemperatureSensor module, as it's not necessary for this deployment.
b. Copy and paste the following code into the createOptions field:

"Env":[
"LOCAL_STORAGE_ACCOUNT_NAME=<your storage account name>",
"LOCAL_STORAGE_ACCOUNT_KEY=<your storage account key>"
],
"HostConfig":{
"Binds": ["<storage mount>"],
"PortBindings":{
"11002/tcp": [{"HostPort":"11002"}]
}
}

4. Replace <your storage account name> with a name that you can remember. Account names should be 3 to
24 characters long, with lowercase letters and numbers. No spaces.
5. Replace <your storage account key> with a 64-byte base64 key. You can generate a key with tools like
GeneratePlus. You'll use these credentials to access the blob storage from other modules.
6. Replace <storage mount> according to your container operating system. Provide the name of a volume or
the absolute path to a directory on your IoT Edge device where you want the blob module to store its data.
The storage mount maps a location on your device that you provide to a set location in the module.
For Linux containers, the format is <storage path or volume>:/blobroot. For example
use volume mount: my-volume:/blobroot
use bind mount: /srv/containerdata:/blobroot. Make sure to follow the steps to grant directory
access to the container user
For Windows containers, the format is <storage path or volume>:C:/BlobRoot. For example
use volume mount: my-volume:C:/blobroot.
use bind mount: C:/ContainerData:C:/BlobRoot.
Instead of using your local drive, you can map your SMB network location, for more information
see using SMB share as your local storage

IMPORTANT
Do not change the second half of the storage mount value, which points to a specific location in the module. The
storage mount should always end with :/blobroot for Linux containers and :C:/BlobRoot for Windows containers.
7. Configure deviceToCloudUploadProperties and deviceAutoDeleteProperties for your module by adding the
following JSON to the deployment.template.json file. Configure each property with an appropriate value
and save the file. If you are using the IoT Edge simulator, set the values to the related environment variables
for these properties, which you can find in the explanation section of deviceToCloudUploadProperties and
deviceAutoDeleteProperties

"<your azureblobstorageoniotedge module name>":{


"properties.desired": {
"deviceAutoDeleteProperties": {
"deleteOn": <true, false>,
"deleteAfterMinutes": <timeToLiveInMinutes>,
"retainWhileUploading": <true, false>
},
"deviceToCloudUploadProperties": {
"uploadOn": <true, false>,
"uploadOrder": "<NewestFirst, OldestFirst>",
"cloudStorageConnectionString": "DefaultEndpointsProtocol=https;AccountName=<your Azure Storage
Account Name>;AccountKey=<your Azure Storage Account Key>;EndpointSuffix=<your end point suffix>",
"storageContainersForUpload": {
"<source container name1>": {
"target": "<target container name1>"
}
},
"deleteAfterUpload": <true, false>
}
}
}

For information on configuring deviceToCloudUploadProperties and deviceAutoDeleteProperties after your


module has been deployed, see Edit the Module Twin. For more information about container create options,
restart policy, and desired status, see EdgeAgent desired properties.
8. Save the deployment.template.json file.
9. Right-click deployment.template.json and select Generate IoT Edge deployment manifest.
10. Visual Studio Code takes the information that you provided in deployment.template.json and uses it to
create a new deployment manifest file. The deployment manifest is created in a new config folder in your
solution workspace. Once you have that file, you can follow the steps in Deploy Azure IoT Edge modules
from Visual Studio Code or Deploy Azure IoT Edge modules with Azure CLI 2.0.

Deploy multiple module instances


If you want to deploy multiple instances of the Azure Blob Storage on IoT Edge module, you need to provide a
different storage path and change the HostPort value that the module binds to. The blob storage modules always
expose port 11002 in the container, but you can declare which port it's bound to on the host.
Edit Container Create Options (in the Azure portal) or the createOptions field (in the deployment.template.json
file in Visual Studio Code) to change the HostPort value:

"PortBindings":{
"11002/tcp": [{"HostPort":"<port number>"}]
}

When you connect to additional blob storage modules, change the endpoint to point to the updated host port.

Next steps
Learn more about Azure Blob Storage on IoT Edge
For more information about how deployment manifests work and how to create them, see Understand how IoT
Edge modules can be used, configured, and reused.
Create a CI/CD pipeline for IoT Edge with Azure
DevOps Projects
11/24/2019 • 5 minutes to read • Edit Online

Configure continuous integration (CI) and continuous delivery (CD ) for your IoT Edge application with DevOps
Projects. DevOps Projects simplifies the initial configuration of a build and release pipeline in Azure Pipelines.
If you don't have an active Azure subscription, create a free account before you begin.

Sign in to the Azure portal


DevOps Projects creates a CI/CD pipeline in Azure DevOps. You can create a new Azure DevOps organization or
use an existing organization. DevOps Projects also creates Azure resources in the Azure subscription of your
choice.
1. Sign in to the Microsoft Azure portal.
2. In the left pane, select Create a resource, and then search for DevOps Projects.
3. Select Create.

Create a new application pipeline


1. Your Azure IoT Edge module(s) can be written in C#, Node.js, Python, C and Java. Select your preferred
language to start a new application: .NET, Node.js, Python, C, or Java. Select Next to continue.

2. Select Simple IoT as your application framework, and then select Next.
3. Select IoT Edge as the Azure service that deploys your application, and then select Next.

4. Create a new free Azure DevOps organization or choose an existing organization.


a. Provide a name for your project.
b. Select your Azure DevOps organization. If you don't have an existing organization, select Additional
settings to create a new one.
c. Select your Azure subscription.
d. Use the IoT Hub name generated by your project name, or provide your own.
e. Accept the default location, or choose one close to you.
f. Select Additional settings to configure the Azure resources that DevOps Projects creates on your
behalf.
g. Select Done to finish creating your project.
After a few minutes, the DevOps Projects dashboard is displayed in the Azure portal. Select your project name to
see the progress. You may need to refresh the page. A sample IoT Edge application is set up in a repository in your
Azure DevOps organization, a build is executed, and your application is deployed to the IoT Edge device. This
dashboard provides visibility into your code repository, the CI/CD pipeline, and your application in Azure.
Commit code changes and execute CI/CD
DevOps Projects created a Git repository for your project in Azure Repos. In this section, you view the repository
and make code changes to your application.
1. To navigate to the repo created for your project, select Repositories in the menu of your project dashboard.

2. The following steps walk through using the web browser to make code changes. If you want to clone your
repository locally instead, select Clone from the top right of the window. Use the provided URL to clone
your Git repository in Visual Studio Code or your preferred development tool.
3. The repository already contains code for a module called FilterModule based on the application language
that you chose in the creation process. Open the modules/FilterModule/module.json file.
4. Notice that this file uses Azure DevOps build variables in the version parameter. This configuration ensures
that a new version of the module will be created every time a new build runs.

Examine the CI/CD pipeline


In the previous sections, Azure DevOps Projects automatically configured a full CI/CD pipeline for your IoT Edge
application. Now, explore and customize the pipeline as needed. Use the following steps to familiarize yourself
with the Azure DevOps build and release pipelines.
1. To view the build pipelines in your DevOps project, select Build Pipelines in the menu of your project
dashboard. This link opens a browser tab and the Azure DevOps build pipeline for your new project.

2. Select Edit.

3. In the panel that opens, you can examine the tasks that occur when your build pipeline runs. The build
pipeline performs various tasks, such as fetching sources from the Git repository, building IoT Edge module
images, pushing IoT Edge modules to a container registry, and publishing outputs that are used for
deployments. To learn more about Azure IoT Edge tasks in Azure DevOps, see Configure Azure Pipelines
for continuous integration.
4. Select the Pipeline header at the top of the build pipeline to open the pipeline details. Change the name of
your build pipeline to something more descriptive.

5. Select Save & queue, and then select Save.


6. Select Triggers from the build pipeline menu. DevOps Projects automatically created a CI trigger, and every
commit to the repository starts a new build. You can optionally choose to include or exclude branches from
the CI process.
7. Select Retention. Depending on your scenario, you can specify policies to keep or remove a certain
number of builds.
8. Select History. The history panel contains an audit trail of recent changes to the build. Azure Pipelines
keeps track of any changes that are made to the build pipeline, and it allows you to compare versions.
9. When you're done exploring the build pipeline, navigate to the corresponding release pipeline. Select
Releases under Pipelines, then select Edit to view the pipeline details.

10. Under Artifacts, select Drop. The source that this artifact watches is the output of the build pipeline you
examined in the previous steps.
11. Next to the Drop icon, select the Continuous deployment trigger that looks like a lightning bolt. This
release pipeline has enabled the trigger, which runs a deployment every time there is a new build artifact
available. Optionally, you can disable the trigger so that your deployments require manual execution.
12. In the menu for your release pipeline, select Tasks then choose the dev stage from the dropdown list.
DevOps Projects created a release stage for you that creates an IoT hub, creates an IoT Edge device in that
hub, deploys the sample module from the build pipeline, and provisions a virtual machine to run as your
IoT Edge device. To learn more about Azure IoT Edge tasks for CD, see Configure Azure Pipelines for
continuous deployment.
13. On the right, select View releases. This view shows a history of releases.
14. Select the name of a release to view more information about it.

Clean up resources
You can delete Azure App Service and other related resources that you created when you don't need them
anymore. Use the Delete functionality on the DevOps Projects dashboard.

Next steps
Learn about the Tasks for Azure IoT Edge on Azure DevOps in Continuous integration and continuous
deployment to Azure IoT Edge
Understand the IoT Edge deployment in Understand IoT Edge deployments for single devices or at scale
Walk through the steps to create, update, or delete a deployment in Deploy and monitor IoT Edge modules at
scale.
Continuous integration and continuous deployment
to Azure IoT Edge
12/1/2019 • 10 minutes to read • Edit Online

You can easily adopt DevOps with your Azure IoT Edge applications with the built-in Azure IoT Edge tasks in
Azure Pipelines. This article demonstrates how you can use the continuous integration and continuous
deployment features of Azure Pipelines to build, test, and deploy applications quickly and efficiently to your Azure
IoT Edge.

In this article, you learn how to use the built-in Azure IoT Edge tasks for Azure Pipelines to create two pipelines
for your IoT Edge solution. There are four actions can be used in the Azure IoT Edge tasks.
Azure IoT Edge - Build Module images takes your IoT Edge solution code and builds the container images.
Azure IoT Edge - Push Module images pushes module images to the container registry you specified.
Azure IoT Edge - Generate Deployment Manifest takes a deployment.template.json file and the variables,
then generates the final IoT Edge deployment manifest file.
Azure IoT Edge - Deploy to IoT Edge devices helps create IoT Edge deployments to single/multiple IoT
Edge devices.

Prerequisites
An Azure Repos repository. If you don't have one, you can Create a new Git repo in your project.
An IoT Edge solution committed and pushed to your repository. If you want to create a new sample solution
for testing this article, follow the steps in Develop and debug modules in Visual Studio Code or Develop and
debug C# modules in Visual Studio.
For this article, all you need is the solution folder created by the IoT Edge templates in either Visual
Studio Code or Visual Studio. You don't need to build, push, deploy, or debug this code before
proceeding. You'll set those processes up in Azure Pipelines.
If you're creating a new solution, clone your repository locally first. Then, when you create the solution
you can choose to create it directly in the repository folder. You can easily commit and push the new files
from there.
A container registry where you can push module images. You can use Azure Container Registry or a third-
party registry.
An active IoT hub with at least IoT Edge devices for testing the separate test and production deployment
stages. You can follow the quickstart articles to create an IoT Edge device on Linux or Windows
For more information about using Azure Repos, see Share your code with Visual Studio and Azure Repos

Configure continuous integration


In this section, you create a new build pipeline. Configure the pipeline to run automatically when you check in any
changes to the sample IoT Edge solution, and publish build logs.

NOTE
This article uses the Azure DevOps visual designer. Before you follow the steps in this section, turn off the preview feature
for the new YAML pipeline creation experience.
1. In Azure DevOps, select your profile icon then select Preview features.
2. Turn New YAML pipeline creation experience off.
For more information, see Create a build pipeline.

1. Sign into your Azure DevOps organization (https://dev.azure.com/{your organization}/) and open the
project that contains your IoT Edge solution repository.
For this article, we created a repository called IoTEdgeRepo. That repository contains IoTEdgeSolution
which has the code for a module named filtermodule.

2. Navigate to Azure Pipelines in your project. Open the Builds tab and select New pipeline. Or, if you
already have build pipelines, select the New button. Then choose New build pipeline.
3. Follow the prompts to create your pipeline.
a. Provide the source information for your new build pipeline. Select Azure Repos Git as the source,
then select the project, repository, and branch where your IoT Edge solution code is located. Then,
select Continue.

b. Select Empty job instead of a template.


4. Once your pipeline is created, you are taken to the pipeline editor. In your pipeline description, choose the
correct agent pool based on your target platform:
If you would like to build your modules in platform amd64 for Linux containers, choose Hosted
Ubuntu 1604
If you would like to build your modules in platform amd64 for Windows 1809 containers, you need
to set up self-hosted agent on Windows.
If you would like to build your modules in platform arm32v7 or arm64 for Linux containers, you
need to set up self-hosted agent on Linux.

5. Your pipeline comes preconfigured with a job called Agent job 1. Select the plus sign (+) to add three
tasks to the job: Azure IoT Edge twice, Copy Files once and Publish Build Artifacts once. (Hover over
the name of each task to see the Add button.)
When all four tasks are added, your Agent job looks like the following example:

6. Select the first Azure IoT Edge task to edit it. This task builds all modules in the solution with the target
platform that you specify.
Display name: Accept the default Azure IoT Edge - Build module images.
Action: Accept the default Build module images.
.template.json file: Select the ellipsis (...) and navigate to the deployment.template.json file in the
repository that contains your IoT Edge solution.
Default platform: Select the appropriate platform for your modules based on your target IoT Edge
device.
Output variables: The output variables include a reference name that you can use to configure the file
path where your deployment.json file will be generated. Set the reference name to something
memorable like edge.
7. Select the second Azure IoT Edge task to edit it. This task pushes all module images to the container
registry that you select.
Display name: The display name is automatically updated when the action field changes.
Action: Use the dropdown list to select Push module images.
Container registry type: Select the type of container registry that you use to store your module
images. Depending on which registry type you choose, the form changes. If you choose Azure
Container Registry, use the dropdown lists to select the Azure subscription and the name of your
container registry. If you choose Generic Container Registry, select New to create a registry service
connection.
.template.json file: Select the ellipsis (...) and navigate to the deployment.template.json file in the
repository that contains your IoT Edge solution.
Default platform: Select the same platform as your built module images.
If you have multiple container registries to host your module images, you need to duplicate this task, select
different container registry, and use Bypass module(s) in the advanced settings to bypass the images
which are not for this specific registry.
8. Select the Copy Files task to edit it. Use this task to copy files to the artifact staging directory.
Display name: Copy Files to: Drop folder.
Contents: Put two lines in this section, deployment.template.json and **/module.json . These two types
of files are the inputs to generate IoT Edge deployment manifest. Need to be copied to the artifact
staging folder and published for release pipeline.
Target Folder: Put the variable $(Build.ArtifactStagingDirectory) . See Build variables to learn about
the description.
9. Select the Publish Build Artifacts task to edit it. Provide artifact staging directory path to the task so that
the path can be published to release pipeline.
Display name: Publish Artifact: drop.
Path to publish: Put the variable $(Build.ArtifactStagingDirectory) . See Build variables to learn about
the description.
Artifact name: drop.
Artifact publish location: Azure Pipelines.
10. Open the Triggers tab and check the box to Enable continuous integration. Make sure the branch
containing your code is included.

11. Save the new build pipeline with Save button.


This pipeline is now configured to run automatically when you push new code to your repo. The last task,
publishing the pipeline artifacts, triggers a release pipeline. Continue to the next section to build the release
pipeline.

Configure continuous deployment


In this section, you create a release pipeline that is configured to run automatically when your build pipeline drops
artifacts, and it will show deployment logs in Azure Pipelines.
Create a new pipeline, and add a new stage
1. In the Releases tab, choose + New pipeline. Or, if you already have release pipelines, choose the + New
button and select + New release pipeline.
2. When prompted to select a template, choose to start with an Empty job.

3. Your new release pipeline initializes with one stage, called Stage 1. Rename Stage 1 to dev and treat it as a
test environment. Usually, continuous deployment pipelines have multiple stages including dev, staging
and prod. You can create more based on your DevOps practice. Close the stage details window once it's
renamed.
4. Link the release to the build artifacts that are published by the build pipeline. Click Add in artifacts area.

5. In Add an artifact page, select source type Build. Then, select the project and the build pipeline you
created. Then, select Add.
6. Open the artifact triggers and select the toggle to enable the continuous deployment trigger. Now, a new
release will be created each time a new build is available.

7. The dev stage is preconfigured with one job and zero tasks. From the pipeline menu, select Tasks then
choose the dev stage. Select the job and task count to configure the tasks in this stage.
8. In the dev stage, you should see a default Agent job. You can configure details about the agent job, but the
deployment task is platform insensitive so you can use either Hosted VS2017 or Hosted Ubuntu 1604 in
the Agent pool (or any other agent managed by yourself).
9. Select the plus sign (+) to add two task. Search for and add Azure IoT Edge twice.

10. Select the first Azure IoT Edge task and configure it with the following values:
Display name: The display name is automatically updated when the action field changes.
Action: Use the dropdown list to select Generate deployment manifest. Changing the action value
also updates the task display name to match.
.template.json file: Put the path
$(System.DefaultWorkingDirectory)/Drop/drop/deployment.template.json . The path is published from build
pipeline.
Default platform: Choose the same value when building the module images.
Output path: Put the path $(System.DefaultWorkingDirectory)/Drop/drop/configs/deployment.json . This
path is the final IoT Edge deployment manifest file.
These configurations helps replace the module image URLs in the deployment.template.json file. The
Generate deployment manifest also helps replace the variables with the exact value you defined in the
deployment.template.json file. In VS/VS Code, you are specifying the actual value in a .env file. In Azure
Pipelines, you set the value in Release Pipeline Variables tab. Move to Variables tab and configure the
Name and Value as following.
ACR_ADDRESS: Your Azure Container Registry address.
ACR_PASSWORD: Your Azure Container Registry password.
ACR_USER: Your Azure Container Registry username.
If you have other variables in your project, you can specify the name and value in this tab. The Generate
deployment manifest can only recognize the variables are in ${VARIABLE} flavor, make sure you are
using this in your *.template.json files.
11. Select the second Azure IoT Edge task and configure it with the following values:
Display name: The display name is automatically updated when the action field changes.
Action: Use the dropdown list to select Deploy to IoT Edge devices. Changing the action value also
updates the task display name to match.
Azure subscription: Select the subscription that contains your IoT Hub.
IoT Hub name: Select your IoT hub.
Choose single/multiple device: Choose whether you want the release pipeline to deploy to one
device or multiple devices.
If you deploy to a single device, enter the IoT Edge device ID.
If you are deploying to multiple devices, specify the device target condition. The target
condition is a filter to match a set of IoT Edge devices in IoT Hub. If you want to use Device Tags
as the condition, you need to update your corresponding devices Tags with IoT Hub device twin.
Update the IoT Edge deployment ID and IoT Edge deployment priority in the advanced
settings. For more information about creating a deployment for multiple devices, see Understand
IoT Edge automatic deployments.
Expand Advanced Settings, select IoT Edge deployment ID, put the variable
$(System.TeamProject)-$(Release.EnvironmentName) . This maps the project and release name with your
IoT Edge deployment ID.
12. Select Save to save your changes to the new release pipeline. Return to the pipeline view by selecting
Pipeline from the menu.

Verify IoT Edge CI/CD with the build and release pipelines
To trigger a build job, you can either push a commit to source code repository or manually trigger it. In this
section, you manually trigger the CI/CD pipeline to test that it works. Then verify that the deployment succeeds.
1. Navigate to the build pipeline that you created at the beginning of this article.
2. You can trigger a build job in your build pipeline by selecting the Queue button as in following screenshot.
3. Select the build job to watch its progress. If the build pipeline is completed successfully, it triggers a release
to dev stage.

4. The successful dev release creates IoT Edge deployment to target IoT Edge devices.

5. Click dev stage to see release logs.

Next steps
IoT Edge DevOps best practices sample in Azure DevOps Project for IoT Edge
Understand the IoT Edge deployment in Understand IoT Edge deployments for single devices or at scale
Walk through the steps to create, update, or delete a deployment in Deploy and monitor IoT Edge modules at
scale.
Integrate Azure IoT Edge with Jenkins pipelines
1/25/2019 • 2 minutes to read • Edit Online

Azure IoT Edge has built-in support for Azure DevOps and Azure DevOps Projects, but also provides a plugin to
expand DevOps functionality to Jenkins. Jenkins is an open-source automation server that uses plugins to support
many types of development and deployment projects, including IoT Edge.
The Azure IoT Edge plugin for Jenkins focuses on continuous integration and continuous deployment. You can
create a build and push pipeline that builds modules and pushes their container images to your container registry.
Then, create a release pipeline that deploys modules to your IoT Edge devices.
Before you start using the IoT Edge plugin for Jenkins, you need an IoT hub in Azure and a container registry to
hold your container images. Use an Azure Service Principal to give Jenkins contributor permissions to your IoT
hub so that the plugin can create deployments for your IoT Edge devices.
If you're ready to get started, find installation and use details for the Azure IoT Edge plugin for Jenkins.
Common issues and resolutions for Azure IoT Edge
11/24/2019 • 12 minutes to read • Edit Online

If you experience issues running Azure IoT Edge in your environment, use this article as a guide for
troubleshooting and resolution.

Run the iotedge 'check' command


Your first step when troubleshooting IoT Edge should be to use the check command, which performs a
collection of configuration and connectivity tests for common issues. The check command is available in release
1.0.7 and later.
You can run the check command as follows, or include the --help flag to see a complete list of options:
On Linux:

sudo iotedge check

On Windows:

iotedge check

The types of checks run by the tool can be classified as:


Configuration checks: Examines details that could prevent Edge devices from connecting to the cloud,
including issues with config.yaml and the container engine.
Connection checks: Verifies the IoT Edge runtime can access ports on the host device and all the IoT Edge
components can connect to the IoT Hub.
Production readiness checks: Looks for recommended production best practices, such as the state of device
certificate authority (CA) certificates and module log file configuration.
For a complete list of diagnostic checks, see Built-in troubleshooting functionality.

Standard diagnostic steps


If you encounter an issue, you can learn more about the state of your IoT Edge device by reviewing the container
logs and the messages that pass to and from the device. Use the commands and tools in this section to gather
information.
Check the status of the IoT Edge Security Manager and its logs
On Linux:
To view the status of the IoT Edge Security Manager:

sudo systemctl status iotedge

To view the logs of the IoT Edge Security Manager:


sudo journalctl -u iotedge -f

To view more detailed logs of the IoT Edge Security Manager:


Edit the iotedge daemon settings:

sudo systemctl edit iotedge.service

Update the following lines:

[Service]
Environment=IOTEDGE_LOG=edgelet=debug

Restart the IoT Edge Security Daemon:

sudo systemctl cat iotedge.service


sudo systemctl daemon-reload
sudo systemctl restart iotedge

On Windows:
To view the status of the IoT Edge Security Manager:

Get-Service iotedge

To view the logs of the IoT Edge Security Manager:

. {Invoke-WebRequest -useb aka.ms/iotedge-win} | Invoke-Expression; Get-IoTEdgeLog

If the IoT Edge Security Manager is not running, verify your yaml configuration file

WARNING
YAML files cannot contain tabs as indentation. Use 2 spaces instead.

On Linux:

sudo nano /etc/iotedge/config.yaml

On Windows:

notepad C:\ProgramData\iotedge\config.yaml

Check container logs for issues


Once the IoT Edge Security Daemon is running, look at the logs of the containers to detect issues. Start with your
deployed containers, then look at the containers that make up the IoT Edge runtime: edgeAgent and edgeHub.
The IoT Edge agent logs typically provide info on the lifecycle of each container. The IoT Edge hub logs provide
info on messaging and routing.
iotedge logs <container name>

View the messages going through the IoT Edge hub


You can view the messages going through the IoT Edge hub, and gather insights from verbose logs from the
runtime containers. To turn on verbose logs on these containers, set RuntimeLogLevel in your yaml configuration
file. To open the file:
On Linux:

sudo nano /etc/iotedge/config.yaml

On Windows:

notepad C:\ProgramData\iotedge\config.yaml

By default, the agent element will look like the following example:

agent:
name: edgeAgent
type: docker
env: {}
config:
image: mcr.microsoft.com/azureiotedge-agent:1.0
auth: {}

Replace env: {} with:

env:
RuntimeLogLevel: debug

WARNING
YAML files cannot contain tabs as identation. Use 2 spaces instead.

Save the file and restart the IoT Edge security manager.
You can also check the messages being sent between IoT Hub and the IoT Edge devices. View these messages by
using the Azure IoT Hub Toolkit extension (formerly Azure IoT Toolkit extension) for Visual Studio Code. For
more information, see Handy tool when you develop with Azure IoT.
Restart containers
After investigating the logs and messages for information, you can try restarting containers:

iotedge restart <container name>

Restart the IoT Edge runtime containers:

iotedge restart edgeAgent && iotedge restart edgeHub

Restart the IoT Edge security manager


If issue is still persisting, you can try restarting the IoT Edge security manager.
On Linux:

sudo systemctl restart iotedge

On Windows:

Stop-Service iotedge -NoWait


sleep 5
Start-Service iotedge

IoT Edge agent stops after about a minute


The edgeAgent module starts and runs successfully for about a minute, then stops. The logs indicate that the IoT
Edge agent attempts to connect to IoT Hub over AMQP, and then attempts to connect using AMQP over
WebSocket. When that fails, the IoT Edge agent exits.
Example edgeAgent logs:

2017-11-28 18:46:19 [INF] - Starting module management agent.


2017-11-28 18:46:19 [INF] - Version - 1.0.7516610 (03c94f85d0833a861a43c669842f0817924911d5)
2017-11-28 18:46:19 [INF] - Edge agent attempting to connect to IoT Hub via AMQP...
2017-11-28 18:46:49 [INF] - Edge agent attempting to connect to IoT Hub via AMQP over WebSocket...

Root cause
A networking configuration on the host network is preventing the IoT Edge agent from reaching the network.
The agent attempts to connect over AMQP (port 5671) first. If the connection fails, it tries WebSockets (port 443).
The IoT Edge runtime sets up a network for each of the modules to communicate on. On Linux, this network is a
bridge network. On Windows, it uses NAT. This issue is more common on Windows devices using Windows
containers that use the NAT network.
Resolution
Ensure that there is a route to the internet for the IP addresses assigned to this bridge/NAT network. Sometimes
a VPN configuration on the host overrides the IoT Edge network.

IoT Edge hub fails to start


The edgeHub module fails to start, and prints the following message to the logs:

One or more errors occurred.


(Docker API responded with status code=InternalServerError, response=
{\"message\":\"driver failed programming external connectivity on endpoint edgeHub
(6a82e5e994bab5187939049684fb64efe07606d2bb8a4cc5655b2a9bad5f8c80):
Error starting userland proxy: Bind for 0.0.0.0:443 failed: port is already allocated\"}\n)

Root cause
Some other process on the host machine has bound port 443. The IoT Edge hub maps ports 5671 and 443 for
use in gateway scenarios. This port mapping fails if another process has already bound this port.
Resolution
Find and stop the process that is using port 443. This process is usually a web server.

IoT Edge agent can't access a module's image (403)


A container fails to run, and the edgeAgent logs show a 403 error.
Root cause
The Iot Edge agent doesn't have permissions to access a module's image.
Resolution
Make sure that your registry credentials are correctly specified in your deployment manifest

IoT Edge security daemon fails with an invalid hostname


The command sudo journalctl -u iotedge fails and prints the following message:

Error parsing user input data: invalid hostname. Hostname cannot be empty or greater than 64 characters

Root cause
The IoT Edge runtime can only support hostnames that are shorter than 64 characters. Physical machines usually
don't have long hostnames, but the issue is more common on a virtual machine. The automatically generated
hostnames for Windows virtual machines hosted in Azure, in particular, tend to be long.
Resolution
When you see this error, you can resolve it by configuring the DNS name of your virtual machine, and then
setting the DNS name as the hostname in the setup command.
1. In the Azure portal, navigate to the overview page of your virtual machine.
2. Select configure under DNS name. If your virtual machine already has a DNS name configured, you
don't need to configure a new one.

3. Provide a value for DNS name label and select Save.


4. Copy the new DNS name, which should be in the format <DNSnamelabel>.
<vmlocation>.cloudapp.azure.com.
5. Inside the virtual machine, use the following command to set up the IoT Edge runtime with your DNS
name:
On Linux:
sudo nano /etc/iotedge/config.yaml

On Windows:

notepad C:\ProgramData\iotedge\config.yaml

Stability issues on resource constrained devices


You may encounter stability problems on constrained devices like the Raspberry Pi, especially when used as a
gateway. Symptoms include out of memory exceptions in the edge hub module, downstream devices cannot
connect or the device stops sending telemetry messages after a few hours.
Root cause
The IoT Edge hub, which is part of the IoT Edge runtime, is optimized for performance by default and attempts to
allocate large chunks of memory. This optimization is not ideal for constrained edge devices and can cause
stability problems.
Resolution
For the IoT Edge hub, set an environment variable OptimizeForPerformance to false. There are two ways to
do this:
In the UI:
In the portal, navigate to Device Details > Set Modules > Configure advanced Edge Runtime settings.
Create an environment variable for the Edge Hub module called OptimizeForPerformance that is set to false.
OR
In the deployment manifest:

"edgeHub": {
"type": "docker",
"settings": {
"image": "mcr.microsoft.com/azureiotedge-hub:1.0",
"createOptions": <snipped>
},
"env": {
"OptimizeForPerformance": {
"value": "false"
}
},

Can't get the IoT Edge daemon logs on Windows


If you get an EventLogException when using Get-WinEvent on Windows, check your registry entries.
Root cause
The Get-WinEvent PowerShell command relies on a registry entry to be present to find logs by a specific
ProviderName .
Resolution
Set a registry entry for the IoT Edge daemon. Create a iotedge.reg file with the following content, and import in
to the Windows Registry by double-clicking it or using the reg import iotedge.reg command:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application\iotedged]
"CustomSource"=dword:00000001
"EventMessageFile"="C:\\ProgramData\\iotedge\\iotedged.exe"
"TypesSupported"=dword:00000007

IoT Edge module fails to send a message to the edgeHub with 404
error
A custom IoT Edge module fails to send a message to the edgeHub with a 404 Module not found error. The IoT
Edge daemon prints the following message to the logs:

Error: Time:Thu Jun 4 19:44:58 2018 File:/usr/sdk/src/c/provisioning_client/adapters/hsm_client_http_edge.c


Func:on_edge_hsm_http_recv Line:364 executing HTTP request fails, status=404, response_buffer=
{"message":"Module not found"}u, 04 )

Root cause
The IoT Edge daemon enforces process identification for all modules connecting to the edgeHub for security
reasons. It verifies that all messages being sent by a module come from the main process ID of the module. If a
message is being sent by a module from a different process ID than initially established, it will reject the message
with a 404 error message.
Resolution
As of version 1.0.7, all module processes are authorized to connect. If upgrading to 1.0.7 isn't possible, complete
the following steps. For more information, see the 1.0.7 release changelog.
Make sure that the same process ID is always used by the custom IoT Edge module to send messages to the
edgeHub. For instance, make sure to ENTRYPOINT instead of CMD command in your Docker file, since CMD will
lead to one process ID for the module and another process ID for the bash command running the main program
whereas ENTRYPOINT will lead to a single process ID.

Firewall and Port configuration rules for IoT Edge deployment


Azure IoT Edge allows communication from an on-premises server to Azure cloud using supported IoT Hub
protocols, see choosing a communication protocol. For enhanced security, communication channels between
Azure IoT Edge and Azure IoT Hub are always configured to be Outbound. This configuration is based on the
Services Assisted Communication pattern, which minimizes the attack surface for a malicious entity to explore.
Inbound communication is only required for specific scenarios where Azure IoT Hub needs to push messages to
the Azure IoT Edge device. Cloud-to-device messages are protected using secure TLS channels and can be
further secured using X.509 certificates and TPM device modules. The Azure IoT Edge Security Manager governs
how this communication can be established, see IoT Edge Security Manager.
While IoT Edge provides enhanced configuration for securing Azure IoT Edge runtime and deployed modules, it
is still dependent on the underlying machine and network configuration. Hence, it is imperative to ensure proper
network and firewall rules are set up for secure edge to cloud communication. The following table can be used as
a guideline when configuration firewall rules for the underlying servers where Azure IoT Edge runtime is hosted:
PROTOCOL PORT INCOMING OUTGOING GUIDANCE

MQTT 8883 BLOCKED (Default) BLOCKED (Default) Configure


Outgoing
(Outbound) to
be Open
when using
MQTT as the
communicatio
n protocol.
1883 for
MQTT is not
supported by
IoT Edge.
Incoming
(Inbound)
connections
should be
blocked.

AMQP 5671 BLOCKED (Default) OPEN (Default) Default


communicatio
n protocol for
IoT Edge.
Must be
configured to
be Open if
Azure IoT
Edge is not
configured for
other
supported
protocols or
AMQP is the
desired
communicatio
n protocol.
5672 for
AMQP is not
supported by
IoT Edge.
Block this port
when Azure
IoT Edge uses
a different IoT
Hub
supported
protocol.
Incoming
(Inbound)
connections
should be
blocked.

HTTPS 443 BLOCKED (Default) OPEN (Default) Configure


Outgoing
(Outbound) to
be Open on
443 for IoT
Edge
provisioning.
This
PROTOCOL PORT INCOMING OUTGOING GUIDANCE
configuration
is required
when using
manual scripts
or Azure IoT
Device
Provisioning
Service (DPS).
Incoming
(Inbound)
connection
should be
Open only for
specific
scenarios:
If you
have a
transp
arent
gatewa
y with
leaf
devices
that
may
send
metho
d
reques
ts. In
this
case,
Port
443
does
not
need
to be
open
to
extern
al
networ
ks to
connec
t to
IoTHu
b or
provid
e
IoTHu
b
service
s
throug
h
Azure
IoT
Edge.
Thus
the
incomi
ng rule
could
be
PROTOCOL PORT INCOMING OUTGOING GUIDANCE
restrict
ed to
only
open
Incomi
ng
(Inbou
nd)
from
the
interna
l
networ
k.
For
Client
to
Device
(C2D)
scenari
os.
80 for HTTP is
not supported
by IoT Edge.
If non-HTTP
protocols (for
example,
AMQP or
MQTT) cannot
be configured
in the
enterprise; the
messages can
be sent over
WebSockets.
Port 443 will
be used for
WebSocket
communicatio
n in that case.

Edge Agent module continually reports 'empty config file' and no


modules start on the device
The device has trouble starting modules defined in the deployment. Only the edgeAgent is running but
continually reporting 'empty config file...'.
Root cause
By default, IoT Edge starts modules in their own isolated container network. The device may be having trouble
with DNS name resolution within this private network.
Resolution
Option 1: Set DNS server in container engine settings
Specify the DNS server for your environment in the container engine settings which will apply to all container
modules started by the engine. Create a file named daemon.json specifying the DNS server to use. For example:
{
"dns": ["1.1.1.1"]
}

The above example sets the DNS server to a publicly accessible DNS service. If the edge device cannot access
this IP from its environment, replace it with DNS server address that is accessible.
Place daemon.json in the right location for your platform:

PLATFORM LOCATION

Linux /etc/docker

Windows host with Windows containers C:\ProgramData\iotedge-moby\config

If the location already contains daemon.json file, add the dns key to it and save the file.
Restart the container engine for the updates to take effect

PLATFORM COMMAND

Linux sudo systemctl restart docker

Windows (Admin Powershell) Restart-Service iotedge-moby -Force

Option 2: Set DNS server in IoT Edge deployment per module


You can set DNS server for each module's createOptions in the IoT Edge deployment. For example:

"createOptions": {
"HostConfig": {
"Dns": [
"x.x.x.x"
]
}
}

Be sure to set this for the edgeAgent and edgeHub modules as well.

Next steps
Do you think that you found a bug in the IoT Edge platform? Submit an issue so that we can continue to improve.
If you have more questions, create a Support request for help.

You might also like