Python Azure IoT SDK: How to receive direct methods from IoT Hub

Introduction

Recently, Microsoft has released the new version of Python Azure IoT SDK (V2.0) (refer to this page on IoT blog: New version of the Python SDK released).  According to the release announcement, we should upgrade SDK from V1 to V2 since the v2 SDK aims to provide a simplified, more natural experience for developers. It’s designed in native Python.

In the last tutorial, we Installed the new Python Azure IoT SDK on Windows 10 and made a demo Python project with Visual Studio to send simulation date to the Azure IoTHub. Please refer to the article “How to use Python Azure IoT SDK with Visual Studio” for more details. In this article, we will walk you through the steps required to build a sample application for receiving direct methods from IoT Hub with Python Azure IoT SDK.

Direct methods represent a request-reply interaction with a device similar to an HTTP call in that they succeed or fail immediately (after a user-specified timeout). This approach is very useful for device management. Please refer to the following two articles for more details: “Understand and invoke direct methods from IoT Hub” and “Overview of device management with IoT Hub”. Take remote reboot control for example, as shown in Fig. 1, the back-end app informs the device through a direct method that it has initiated a reboot. The device uses the reported properties to update the reboot status of the device.

Fig. 1 Direct method call for reboot control

Prerequisites

  1. Windows 10 with Visual Studio 2019 Community (“Python development” workload required)
  2. Python Azure IoT SDK: https://github.com/Azure/azure-iot-sdk-python/tree/master/azure-iot-device/samples
  3. Device Explorer from Github: https://github.com/Azure/azure-iot-sdks/releases

You can refer to the article “How to use Python Azure IoT SDK with Visual Studio” for more details.

Create Device using Device Explore

As we demonstrated in the last article, we will create a device and save the connection string for further use. Please refer to the session “Create Device using Device Explore” in this article “How to use Python Azure IoT SDK with Visual Studio”.

 

Create and Debug Python Project with Visual Studio

Create a  Python project with “Python Application” project temple,  give a name such as “PythonIoTDemo”.Copy and paste the following code to “PythonIoTDemo.py”. Make sure that you substitute with your own connection string in the code.

# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------
 
import os
import asyncio
import threading
from six.moves import input
from azure.iot.device.aio import IoTHubDeviceClient
from azure.iot.device import MethodResponse
 
 
async def  main():
    # The connection string for your device.
    conn_str =  "HostName=***.azure-devices.net;DeviceId=***;SharedAccessKey=***"
    # The client object is used to interact with your Azure IoT hub.
    device_client =  IoTHubDeviceClient.create_from_connection_string(conn_str)
 
    # connect the client.
    await device_client.connect()
 
    # define behavior for handling methods
    async def  method1_listener(device_client):
        while True:
            method_request =  await device_client.receive_method_request(
                "method1"
            )  # Wait for method1 calls
            payload =  {"result":  True, "data": "execute successfully"}  # set response payload
            status =  200  # set return status code
            print("executed method1")
            method_response =  MethodResponse.create_from_method_request(
                method_request, status, payload
            )
            await device_client.send_method_response(method_response)  # send response
 
    async def  method2_listener(device_client):
        while True:
            method_request =  await device_client.receive_method_request(
                "method2"
            )  # Wait for method2 calls
            payload =  {"result":  True, "data": 1234}   # set response payload
            status =  200  # set return status code
            print("executed method2")
            method_response =  MethodResponse.create_from_method_request(
                method_request, status, payload
            )
            await device_client.send_method_response(method_response)  # send response
 
    async def  generic_method_listener(device_client):
        while True:
            method_request =  (
                await device_client.receive_method_request()
            )  # Wait for unknown method calls
            payload =  {"result":  False, "data": "unknown method"}  # set response payload
            status =  400  # set return status code
            print("executed unknown method: " +  method_request.name)
            method_response =  MethodResponse.create_from_method_request(
                method_request, status, payload
            )
            await device_client.send_method_response(method_response)  # send response
 
    # define behavior for halting the application
    def stdin_listener():
        while True:
            selection =  input("Press Q to quit\n")
            if selection == "Q"  or selection == "q":
                print("Quitting...")
                break
 
    # Schedule tasks for Method Listener
    listeners =  asyncio.gather(
        method1_listener(device_client),
        method2_listener(device_client),
        generic_method_listener(device_client),
    )
 
    # Run the stdin listener in the event loop
    loop =  asyncio.get_running_loop()
    user_finished =  loop.run_in_executor(None, stdin_listener)
 
    # Wait for user to indicate they are done listening for method calls
    await user_finished
 
    # Cancel listening
    listeners.cancel()
 
    # Finally, disconnect
    await device_client.disconnect()
 
 
if __name__ == "__main__":
    asyncio.run(main())
 
    # If using Python 3.6 or below, use the following code instead of asyncio.run(main()):
    # loop = asyncio.get_event_loop()
    # loop.run_until_complete(main())
# loop.close()

Then, press F5 to start debug. As soon as the local Python application runs, you will see “Press Q to quit” in the window.

Invoke Direct Methods from Backend App

Here, we use Device Explorer as “Backend App”, and it will send direct method call via IoTHub to the device. Once the device receives the method call, it will execute the method that is defined in the code.

Take method1 for example. Choose the right device that you create, input “method1” in the “Method name” as shown in Fig. 2. Then, click “Call method” button to send the message.

Fig. 2  Invoke Direct Method from Device Explorer

Once the device receives the method call, it will execute the code that defined in “method1_listener”. It will do something locally and send the results back. Consequently, you will see “executed method1” in the local Visual Studio debug output window and receive the results on Deivce Explorer, which are shown in Fig. 3 and Fig. 4 respectively.


Fig. 3  Visual Studio debug output window


Fig. 4  Messages received on Device Explorer

You can also try to use method2 or method3 for tests.

Summary

In this tutorial, we showed the steps to receive direct methods from IoT Hub with Python Azure IoT SDK including ** “Create Device using Device Explore”, “Create and Debug Python Project with Visual Studio” and “Invoke Direct Methods from Backend App”.**

Resources

  1. IoT Blog: New version of the Python SDK released
  2. Device Explorer: https://github.com/Azure/azure-iot-sdks/releases
  3. azure-iot-sdk-python: https://github.com/Azure/azure-iot-sdk-python/tree/master/azure-iot-device/samples 
  4. Understandand invoke direct methods from IoT Hub
  5. Overviewof device management with IoT Hub
  6. My Projects on Hackster: Jiong Shi
  7. Azure IoT Docs: Azure IoTHub

See Also

  1. How to use Python Azure IoT SDK with Visual Studio
  2. Python Azure IoT SDK: How to use device twins in IoT Hub 
  3. Python Azure IoT SDK: How to use device provision service with symmetric keys 
  4. Build a Azure Sphere IoT Car with Remote Control 
  5. Python Azure IoT SDK: How to send and receive C2D messages