Create a IoT Edge Device and send a deployment using REST

Update: from preview to GA there are two main changes for this article:
1) new api version: 2018-06-30
2) the applyConfigurationContent is now requiring a modulesContent object (previously was moduleContent)

In this article you will find some example code snippets to create a new Azure IoT Edge Device programmatically and send it a deployment.json (via REST API)

Authenticate the HTTP Requests:

Each REST request to the IoT Hub endpoint must be authenticated; in order to do that you need to retrieve a SAS Token.
To better understand how the Azure IoT Hub Security works, I suggest you to read this official documentation

using System;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
using System.Web;

class Program
{
    static void Main(string[] args)
    {
        createToken("iotedgedev-iothub-79024e.azure-devices.net",
                    "iothubowner",
                    "SGKiXLmEuxwzlkP7J70BqQF8N4DgdKdr/cUM2BK3eWc=");
    }

    private static void createToken(string resourceUri, string keyName, string key)
    {
        //For example we decided to create a token expiring in a week
        TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
        var week = 60 * 60 * 24 * 7;
        var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + week);
        //IoT Hub Security docs here: https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-security
        string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
        HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(key));
        var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
        var sasToken = String.Format(CultureInfo.InvariantCulture, 
                                    "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}", 
                                    HttpUtility.UrlEncode(resourceUri), 
                                    HttpUtility.UrlEncode(signature), 
                                    expiry, 
                                    keyName);
        Console.WriteLine(sasToken);
    }
}
C# Sample to get SAS Token

Create your Edge Device:

PUT https://{iot-hub-name}.azure-devices.net/devices/{edge-device-name}?api-version=2018-06-30
Request
Authorization: {the key obtained with the C# snippet before}
Content-Type: application/json
Headers
{
	"deviceId": "edge-device-name",
	"capabilities": {
		"iotEdge": true
	}
}
Request body
{
	"deviceId": "edge-device-name",
	"generationId": "636579134228272173",
	"etag": "MjE0MDgyNTg0",
	"connectionState": "Disconnected",
	"status": "enabled",
	"statusReason": null,
	"connectionStateUpdatedTime": "0001-01-01T00:00:00",
	"statusUpdatedTime": "0001-01-01T00:00:00",
	"lastActivityTime": "0001-01-01T00:00:00",
	"cloudToDeviceMessageCount": 0,
	"authentication": {
		"symmetricKey": {
			"primaryKey": "base64primarykey",
			"secondaryKey": "base64secondarykey"
		},
		"x509Thumbprint": {
			"primaryThumbprint": null,
			"secondaryThumbprint": null
		},
		"type": "sas"
	},
	"capabilities": {
		"iotEdge": true
	}
}
Sample response

Apply a deployment.json to the newly created IoT Edge Device:

POST https://{iot-hub-name}.azure-devices.net/devices/{edge-device-name}/applyConfigurationContent?api-version=2018-06-30
Request
Authorization: {the key obtained with the C# snippet before}
Content-Type: application/json
Headers
{
	"modulesContent": {
		"$edgeAgent": {
			"properties.desired": {
				"schemaVersion": "1.0",
				"runtime": {
					"type": "docker",
					"settings": {
						"minDockerVersion": "v1.25",
							"loggingOptions": ""
					}
				},
				"systemModules": {
					"edgeAgent": {
						"type": "docker",
						"settings": {
							"image": "mcr.microsoft.com/azureiotedge-agent:1.0.2",
							"createOptions": ""
						}
					},
					"edgeHub": {
						"type": "docker",
						"status": "running",
						"restartPolicy": "always",
						"settings": {
							"image": "mcr.microsoft.com/azureiotedge-agent:1.0.2",
							"createOptions": ""
						}
					}
				},
				"modules": {
					"yourModule": {
						"version": "1.0",
						"type": "docker",
						"status": "running",
						"restartPolicy": "always",
						"settings": {
							"image": "yourRepository/yourModule:yourTag",
							"createOptions": "{}"
						}
					}
				}
			}
		},
		"$edgeHub": {
			"properties.desired": {
				"schemaVersion": "1.0",
				"routes": {
					"route": "FROM /* INTO $upstream"
				},
				"storeAndForwardConfiguration": {
					"timeToLiveSecs": 7200
				}
			}
		}
	}
}
Request body
204 - No content
Sample response

If you want, you can find other Azure IoT related articles here

Spread this article

4 Replies to “Create a IoT Edge Device and send a deployment using REST”

  1. Hi Daniel,
    Fantastic article!

    I’ve got a use case where downstream clients can only use HTTPS to POST their sensor data into the IoT Edge pipeline. I’ve got my IoT Edge setup and configured as a “Transparent Gateway” following all the Azure instructions. If I use a Simulator Device using the Azure IoT SDK I have no issues with sending my data. I simply enter my Device Connection String and tack on the GatewayHostName at the end and the messages flow from the Device into the IoT Edge.

    Where I’m unclear is how can I hook into the IoT processing pipeline from a basic REST Client making HTTPS requests where the messages flow into the IoT Edge Transparent Gateway machine?

    Would you happen to have any ideas how I could figure that out? I don’t want to make a post to the IoT Hub and then make a direct method call back down to the IoT Edge.

    Thanks,

    Chris

    1. Hi Chris, thank you and sorry for the delay but I was OOF!
      You can not use the any Device Client SDK for this project, right?
      If you can use it I suggest you to use it, otherwise hypothetically you could do the following:
      1) Generate an Authorization Header with the a method similar to the one of the post by:
      1.1) Modifying the resourceUri to: {iothubname}.azure-devices.net/devices/{deviceName}
      1.2) Use the Device Key for the HMACSHA256 signing
      1.3) Remove the part related to the key name (&skn={3} in the SAS Token
      2) POST https://{gatewayhostname}/devices/{deviceName}/messages/events?api-version=2018-06-30 the ByteArray of your JSON

      Please let me know if you will be able to solve

  2. Would love to see this article updated with the latest GA endpoints / json

    1. @Sam: sorry for the delay, the article is now updated with the latest GA endpoints and json

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.