Connect your simulated device to your IoT hub using Python

Introduction

Azure IoT Hub is a fully managed service that enables reliable and secure bi-directional communications between millions of Internet of Things (IoT) devices and a solution back end. One of the biggest challenges that IoT projects face is how to reliably and securely connect devices to the solution back end. To address this challenge, IoT Hub:

  • Offers reliable device-to-cloud and cloud-to-device hyper-scale messaging.
  • Enables secure communications using per-device security credentials and access control.
  • Includes device libraries for the most popular languages and platforms.

This tutorial shows you how to:

  • Use the Azure portal to create an IoT hub.
  • Create a device identity in your IoT hub.
  • Create a simulated device app that sends telemetry to your solution back end.

At the end of this tutorial, you will have two Python apps:

  • CreateDeviceIdentity.py, which creates a device identity and associated security key to connect your simulated device app.
  • SimulatedDevice.py, which connects to your IoT hub with the device identity created earlier, and periodically sends a telemetry message using the MQTT protocol.

Note

The article Azure IoT SDKs provides information about the Azure IoT SDKs that you can use to build both applications to run on devices and your solution back end.

To complete this tutorial, you need the following:

Note

The pip packages for azure-iothub-service-client and azure-iothub-device-client are currently available only for Windows OS. For Linux/Mac OS, please refer to the Linux and Mac OS-specific sections on the Prepare your development environment for Python post.

Create an IoT hub

Create an IoT hub for your simulated device app to connect to. The following steps show you how to complete this task by using the Azure portal.

  1. Sign in to the Azure portal.
  2. Select New > Internet of Things > IoT Hub.

    Azure portal Jumpbar

  3. In the IoT hub pane, enter the following information for your IoT hub:

    • Name: Create a name for your IoT hub. If the name you enter is valid, a green check mark appears.

    Important

    The IoT hub will be publicly discoverable as a DNS endpoint, so make sure to avoid any sensitive information while naming it.

    • Pricing and scale tier: For this tutorial, select the F1 - Free tier. For more information, see the Pricing and scale tier.

    • Resource group: Create a resource group to host the IoT hub or use an existing one. For more information, see Use resource groups to manage your Azure resources

    • Location: Select the closest location to you.

    • Pin to dashboard: Check this option for easy access to your IoT hub from the dashboard.

      IoT hub window

  4. Click Create. Your IoT hub might take a few minutes to create. You can monitor the progress in the Notifications pane.

Now that you have created an IoT hub, locate the important information that you use to connect devices and applications to your IoT hub.

  1. When the IoT hub has been created successfully, click the new tile for your IoT hub in the Azure portal to open the properties window for the new IoT hub. Make a note of the Hostname, and then click Shared access policies.

    New IoT hub window

  2. In Shared access policies, click the iothubowner policy, and then copy and make note of the IoT Hub connection string in the iothubowner window. For more information, see Access control in the "IoT Hub developer guide."

    Shared access policies

You have now created your IoT hub. Use the IoT Hub host name and the IoT Hub connection string in the rest of this tutorial.

Note

You can also easily create your IoT hub on a command line, using the Python or Node.js based Azure CLI. The article Create an IoT hub using the Azure CLI 2.0 shows you the quick steps to do so.

Create a device identity

This section lists the steps to create a Python console app, that creates a device identity in the identity registry of your IoT hub. A device can only connect to IoT Hub if it has an entry in the identity registry. For more information, see the Identity Registry section of the IoT Hub developer guide. When you run this console app, it generates a unique device ID and key that your device can use to identify itself when it sends device-to-cloud messages to IoT Hub.

  1. Open a command prompt and install the Azure IoT Hub Service SDK for Python. Close the command prompt after you install the SDK.

    pip install azure-iothub-service-client
    
  2. Create a Python file named CreateDeviceIdentity.py. Open it in a Python editor/IDE of your choice, for example, the default IDLE.

  3. Add the following code to import the required modules from the service SDK:

    import sys
    import iothub_service_client
    from iothub_service_client import IoTHubRegistryManager, IoTHubRegistryManagerAuthMethod
    from iothub_service_client import IoTHubDeviceStatus, IoTHubError
    
  4. Add the following code, replacing the placeholder for [IoTHub Connection String] with the connection string for the IoT hub you created in the previous section. You can use any name as the DEVICE_ID.

    CONNECTION_STRING = "[IoTHub Connection String]"
    DEVICE_ID = "MyFirstPythonDevice"
    

    Important

    The device ID may be visible in the logs collected for customer support and troubleshooting, so make sure to avoid any sensitive information while naming it.

  5. Add the following function to print some of the device information.

    def print_device_info(title, iothub_device):
        print ( title + ":" )
        print ( "iothubDevice.deviceId                    = {0}".format(iothub_device.deviceId) )
        print ( "iothubDevice.primaryKey                  = {0}".format(iothub_device.primaryKey) )
        print ( "iothubDevice.secondaryKey                = {0}".format(iothub_device.secondaryKey) )
        print ( "iothubDevice.connectionState             = {0}".format(iothub_device.connectionState) )
        print ( "iothubDevice.status                      = {0}".format(iothub_device.status) )
        print ( "iothubDevice.lastActivityTime            = {0}".format(iothub_device.lastActivityTime) )
        print ( "iothubDevice.cloudToDeviceMessageCount   = {0}".format(iothub_device.cloudToDeviceMessageCount) )
        print ( "iothubDevice.isManaged                   = {0}".format(iothub_device.isManaged) )
        print ( "iothubDevice.authMethod                  = {0}".format(iothub_device.authMethod) )
        print ( "" )
    
  6. Add the following function to create the device identification using the Registry Manager.

    def iothub_createdevice():
        try:
            iothub_registry_manager = IoTHubRegistryManager(CONNECTION_STRING)
            auth_method = IoTHubRegistryManagerAuthMethod.SHARED_PRIVATE_KEY
            new_device = iothub_registry_manager.create_device(DEVICE_ID, "", "", auth_method)
            print_device_info("CreateDevice", new_device)
    
        except IoTHubError as iothub_error:
            print ( "Unexpected error {0}".format(iothub_error) )
            return
        except KeyboardInterrupt:
            print ( "iothub_createdevice stopped" )
    
  7. Finally, add the main function as follows and save the file.

    if __name__ == '__main__':
        print ( "" )
        print ( "Python {0}".format(sys.version) )
        print ( "Creating device using the Azure IoT Hub Service SDK for Python" )
        print ( "" )
        print ( "    Connection string = {0}".format(CONNECTION_STRING) )
        print ( "    Device ID         = {0}".format(DEVICE_ID) )
    
        iothub_createdevice()
    
  8. On the command prompt, run the CreateDeviceIdentity.py as follows:

    python CreateDeviceIdentity.py
    
  9. You should see the simulated device getting created. Note down the deviceId and the primaryKey of this device. You need these values later when you create an application that connects to IoT Hub as a device.

    Create device success

Note

The IoT Hub identity registry only stores device identities to enable secure access to the IoT hub. It stores device IDs and keys to use as security credentials and an enabled/disabled flag that you can use to disable access for an individual device. If your application needs to store other device-specific metadata, it should use an application-specific store. For more information, see the IoT Hub developer guide.

Create a simulated device app

This section lists the steps to create a Python console app, that simulates a device and sends device-to-cloud messages to your IoT hub.

  1. Open a new command prompt and install the Azure IoT Hub Device SDK for Python as follows. Close the command prompt after the installation.

    pip install azure-iothub-device-client
    
  2. Create a file named SimulatedDevice.py. Open this file in a Python editor/IDE of your choice (for example, IDLE).

  3. Add the following code to import the required modules from the device SDK.

    import random
    import time
    import sys
    import iothub_client
    from iothub_client import IoTHubClient, IoTHubClientError, IoTHubTransportProvider, IoTHubClientResult
    from iothub_client import IoTHubMessage, IoTHubMessageDispositionResult, IoTHubError, DeviceMethodReturnValue
    
  4. Add the following code and replace the placeholder for [IoTHub Device Connection String] with the connection string for your device. The device connection string is usually in the format of HostName=<hostName>;DeviceId=<deviceId>;SharedAccessKey=<primaryKey>. Use the deviceId and primaryKey of the device you created in the previous section to replace the <deviceId> and <primaryKey> respectively. Replace <hostName> with your IoT hub's host name, usually as <IoT hub name>.azure-devices.net.

    # String containing Hostname, Device Id & Device Key in the format
    CONNECTION_STRING = "[IoTHub Device Connection String]"
    # choose HTTP, AMQP or MQTT as transport protocol
    PROTOCOL = IoTHubTransportProvider.MQTT
    MESSAGE_TIMEOUT = 10000
    AVG_WIND_SPEED = 10.0
    SEND_CALLBACKS = 0
    MSG_TXT = "{\"deviceId\": \"MyFirstPythonDevice\",\"windSpeed\": %.2f}"    
    
  5. Add the following code to define a send confirmation callback.

    def send_confirmation_callback(message, result, user_context):
        global SEND_CALLBACKS
        print ( "Confirmation[%d] received for message with result = %s" % (user_context, result) )
        map_properties = message.properties()
        print ( "    message_id: %s" % message.message_id )
        print ( "    correlation_id: %s" % message.correlation_id )
        key_value_pair = map_properties.get_internals()
        print ( "    Properties: %s" % key_value_pair )
        SEND_CALLBACKS += 1
        print ( "    Total calls confirmed: %d" % SEND_CALLBACKS )
    
  6. Add the following code to initialize the device client.

    def iothub_client_init():
        # prepare iothub client
        client = IoTHubClient(CONNECTION_STRING, PROTOCOL)
        # set the time until a message times out
        client.set_option("messageTimeout", MESSAGE_TIMEOUT)
        client.set_option("logtrace", 0)
        client.set_option("product_info", "HappyPath_Simulated-Python")
        return client
    
  7. Add the following function to format and send a message from your simulated device to your IoT hub.

    def iothub_client_telemetry_sample_run():
    
        try:
            client = iothub_client_init()
            print ( "IoT Hub device sending periodic messages, press Ctrl-C to exit" )
            message_counter = 0
    
            while True:
                msg_txt_formatted = MSG_TXT % (AVG_WIND_SPEED + (random.random() * 4 + 2))
                # messages can be encoded as string or bytearray
                if (message_counter & 1) == 1:
                    message = IoTHubMessage(bytearray(msg_txt_formatted, 'utf8'))
                else:
                    message = IoTHubMessage(msg_txt_formatted)
                # optional: assign ids
                message.message_id = "message_%d" % message_counter
                message.correlation_id = "correlation_%d" % message_counter
                # optional: assign properties
                prop_map = message.properties()
                prop_text = "PropMsg_%d" % message_counter
                prop_map.add("Property", prop_text)
    
                client.send_event_async(message, send_confirmation_callback, message_counter)
                print ( "IoTHubClient.send_event_async accepted message [%d] for transmission to IoT Hub." % message_counter )
    
                status = client.get_send_status()
                print ( "Send status: %s" % status )
                time.sleep(30)
    
                status = client.get_send_status()
                print ( "Send status: %s" % status )
    
                message_counter += 1
    
        except IoTHubError as iothub_error:
            print ( "Unexpected error %s from IoTHub" % iothub_error )
            return
        except KeyboardInterrupt:
            print ( "IoTHubClient sample stopped" )
    
  8. Finally, add the main function.

    if __name__ == '__main__':
        print ( "Simulating a device using the Azure IoT Hub Device SDK for Python" )
        print ( "    Protocol %s" % PROTOCOL )
        print ( "    Connection string=%s" % CONNECTION_STRING )
    
        iothub_client_telemetry_sample_run()
    
  9. Save and close the SimulatedDevice.py file. You are now ready to run this app.

Note

To keep things simple, this tutorial does not implement any retry policy. In production code, you should implement retry policies (such as an exponential backoff), as suggested in the MSDN article Transient Fault Handling.

Receive messages from your simulated device

To receive telemetry messages from your device, you need to use an Event Hubs-compatible endpoint exposed by the IoT Hub, which reads the device-to-cloud messages. Read the Get Started with Event Hubs tutorial for information on how to process messages from Event Hubs for your IoT hub's Event Hub-compatible endpoint. Event Hubs does not support telemetry in Python yet, so you can either create a Node.js or a .NET Event Hubs-based console app to read the device-to-cloud messages from IoT Hub. This tutorial shows how you can use the IoT Hub Explorer tool to read these device messages.

  1. Open a command prompt and install the IoT Hub Explorer.

    npm install -g iothub-explorer
    
  2. Run the following command on the command prompt, to begin monitoring the device-to-cloud messages from your device. Use your IoT hub's connection string in the placeholder after --login.

    iothub-explorer monitor-events MyFirstPythonDevice --login "[IoTHub connection string]"
    
  3. Open a new command prompt and navigate to the directory containing the SimulatedDevice.py file.

  4. Run the SimulatedDevice.py file, which periodically sends telemetry data to your IoT hub.

    python SimulatedDevice.py
    
  5. Observe the device messages on the command prompt running the IoT Hub Explorer from the previous section.

    Python device-to-cloud messages

Next steps

In this tutorial, you configured a new IoT hub in the Azure portal, and then created a device identity in the IoT hub's identity registry. You used this device identity to enable the simulated device app to send device-to-cloud messages to the IoT hub. You observed the messages received by the IoT hub with the help of the IoT Hub Explorer tool.

To explore the Python SDK for Azure IoT Hub usage in depth, visit this Git Hub repo. To review the messaging capabilities of the Azure IoT Hub Service SDK for Python, you can download and run iothub_messaging_sample.py. For device side simulation using the Azure IoT Hub Device SDK for Python, you can download and run the iothub_client_sample.py.

To continue getting started with IoT Hub and to explore other IoT scenarios, see:

To learn how to extend your IoT solution and process device-to-cloud messages at scale, see the Process device-to-cloud messages tutorial.

To continue to get started with Azure IoT Hub and to explore other IoT scenarios, see the following: