Use Azure IoT Edge to send device-to-cloud messages with a simulated device (Linux)

This walkthrough of the Simulated Device Cloud Upload sample shows how to use Azure IoT Edge to send device-to-cloud telemetry to IoT Hub from simulated devices.

This walkthrough covers:

  1. Architecture: important architectural information about the Simulated Device Cloud Upload sample.
  2. Build and run: the steps required to build and run the sample.

Architecture

The Simulated Device Cloud Upload sample shows how to use IoT Edge to create a gateway which sends telemetry from simulated devices to an IoT hub. The simulated devices cannot connect directly to IoT Hub because:

  • The devices do not use a communications protocol understood by IoT Hub.
  • The devices are not smart enough to remember the identity assigned to them by IoT Hub.

The IoT Edge gateway solves these problems for the simulated devices in the following ways:

  • The gateway understands the protocol used by the simulated devices, receives device-to-cloud telemetry from the devices, and forwards those messages to IoT Hub using a protocol understood by the IoT hub.
  • The gateway stores IoT Hub identities on behalf of the simulated devices and acts as a proxy when the simulated devices send messages to IoT Hub.

The following diagram shows the main components of the sample, including the IoT Edge modules:

Note

The modules do not pass messages directly to each other. The modules publish messages to an internal broker that delivers the messages to the other modules using a subscription mechanism as shown in the diagram below. For more information, see Get started with Azure IoT Edge.

Protocol ingestion module

This module is the starting point for getting data from devices, through the gateway, and into the cloud. In the sample, the module performs four tasks:

  1. It creates simulated temperature data. Note that if you use real devices, the module reads data from those physical devices.
  2. It places the simulated temperature data into the contents of a message.
  3. It adds a property with a fake MAC address to the message that contains the simulated temperature data.
  4. It makes the message available to the next module in the chain.
Note

The module called Protocol X ingestion in the diagram above is called Simulated device in the source code.

MAC <-> IoT Hub ID module

This module scans for messages that include a property that contains the MAC address, added by the protocol ingestion module, of the simulated device app. If the module finds such a property, it adds another property with an IoT Hub device key to the message and then makes the message available to the next module in the chain. This is how the sample associates IoT Hub device identities with simulated devices. The developer sets up the mapping between MAC addresses and IoT Hub identities manually as part of the module configuration.

Note

This sample uses a MAC address as a unique device identifier and correlates it with an IoT Hub device identity. However, you can write your own module that uses a different unique identifier. For example, you may have devices with unique serial numbers or telemetry data that has a unique device name embedded in it that you could use to determine the IoT Hub device identity.

IoT Hub communication module

This module takes messages with an IoT Hub device identity assigned by the previous module and sends the message content to IoT Hub using HTTP. HTTP is one of the three protocols understood by IoT Hub.

Instead of opening a connection to IoT Hub for each simulated device app, this module opens a single HTTP connection from the gateway to the IoT hub and multiplexes connections from all the simulated devices over that connection. This enables a single gateway to connect many more devices, simulated or otherwise, than would be possible if it opened a unique connection for every device.

Build and run the sample

Before you get started, you must:

  • Set up your development environment for working with the SDK on Linux.
  • Create an IoT hub in your Azure subscription, you will need the name of your hub to complete this walkthrough. If you don't have an account, you can create a free account in just a couple of minutes.
  • Add two devices to your IoT hub and make a note of their ids and device keys. You can use the device explorer or iothub-explorer tool to add your devices to the IoT hub you created in the previous step and retrieve their keys.

To build the sample:

  1. Open a shell.
  2. Navigate to the root folder in your local copy of the iot-edge repository.
  3. Run the tools/build.sh script. This script uses the cmake utility to create a folder called build in the root folder of your local copy of the iot-edge repository and generate a makefile. The script then builds the solution, skipping unit tests and end to end tests. Add the --run-unittests parameter if you want to build and run the unit tests. Add the --run-e2e-tests if you want to build and run the end to end tests.
Note

Every time you run the build.sh script, it deletes and then recreates the build folder in the root folder of your local copy of the iot-edge repository.

To run the sample:

In a text editor, open the file samples/simulated_device_cloud_upload/src/simulated_device_cloud_upload_lin.json in your local copy of the iot-edge repository. This file configures the IoT Edge modules in the sample gateway:

  • The IoTHub module connects to your IoT hub. You must configure it to send data to your IoT hub. Specifically, set the IoTHubName value to the name of your IoT hub and set the IoTHubSuffix value to azure-devices.net. Set the Transport value to one of: "HTTP", "AMQP", or "MQTT". Note that currently, only "HTTP" will share one TCP connection for all device messages. If you set the value to "AMQP", or "MQTT", the gateway will maintain a separate TCP connection to IoT Hub for each device.
  • The mapping module maps the MAC addresses of your simulated devices to your IoT Hub device ids. Make sure that deviceId values match the ids of the two devices you added to your IoT hub, and that the deviceKey values contain the keys of your two devices.
  • The BLE1 and BLE2 modules are the simulated devices. Note how their MAC addresses match those in the mapping module.
  • The Logger module logs your gateway activity to a file.
  • The module path values shown below assume that you will run the sample from the root of your local copy of the iot-edge repository.
  • The links array at the bottom of the JSON file connects the BLE1 and BLE2 modules to the mapping module, and the mapping module to the IoTHub module. It also ensures that all messages are logged by the Logger module.
{
    "modules": [
        {
            "name": "IotHub",
          "loader": {
            "name": "native",
            "entrypoint": {
              "module.path": "./modules/iothub/libiothub.so"
            }
            },
            "args": {
              "IoTHubName": "<<insert here IoTHubName>>",
              "IoTHubSuffix": "<<insert here IoTHubSuffix>>",
              "Transport": "HTTP"
            }
          },
        {
            "name": "mapping",
          "loader": {
            "name": "native",
            "entrypoint": {
              "module.path": "./modules/identitymap/libidentity_map.so"
            }
            },
            "args": [
              {
                "macAddress": "01:01:01:01:01:01",
                "deviceId": "<<insert here deviceId>>",
                "deviceKey": "<<insert here deviceKey>>"
              },
              {
                "macAddress": "02:02:02:02:02:02",
                "deviceId": "<<insert here deviceId>>",
                "deviceKey": "<<insert here deviceKey>>"
              }
            ]
          },
        {
            "name": "BLE1",
          "loader": {
            "name": "native",
            "entrypoint": {
              "module.path": "./modules/simulated_device/libsimulated_device.so"
            }
            },
            "args": {
              "macAddress": "01:01:01:01:01:01"
            }
          },
        {
            "name": "BLE2",
          "loader": {
            "name": "native",
            "entrypoint": {
              "module.path": "./modules/simulated_device/libsimulated_device.so"
            }
            },
            "args": {
              "macAddress": "02:02:02:02:02:02"
            }
          },
        {
            "name": "Logger",
          "loader": {
            "name": "native",
            "entrypoint": {
              "module.path": "./modules/logger/liblogger.so"
            }
            },
            "args": {
              "filename": "deviceCloudUploadGatewaylog.log"
            }
          }
    ],
    "links": [
        {
            "source": "*",
            "sink": "Logger"
        },
        {
            "source": "BLE1",
            "sink": "mapping"
        },
        {
            "source": "BLE2",
            "sink": "mapping"
        },
        {
            "source": "mapping",
            "sink": "IotHub"
        }
    ]
}

Save any changes you made to the configuration file.

To run the sample:

  1. In your shell, navigate to the iot-edge/build folder.
  2. Run the following command:

    ./samples/simulated_device_cloud_upload/simulated_device_cloud_upload_sample ./../samples/simulated_device_cloud_upload/src/simulated_device_cloud_upload_lin.json
    
  3. You can use the device explorer or iothub-explorer tool to monitor the messages that IoT hub receives from the IoT Edge gateway.

Next steps

If you want to gain a more advanced understanding of Azure IoT Edge and experiment with some code examples, visit the following developer tutorials and resources:

To further explore the capabilities of IoT Hub, see: