IoT 中心模块标识和模块孪生 (Python) 入门

模块标识和模块孪生类似于 Azure IoT 中心设备标识和设备孪生,但提供更精细的粒度。 Azure IoT 中心设备标识和设备孪生允许后端应用程序配置设备并提供对设备状况的可见性,而模块标识和模块孪生为设备的各个组件提供这些功能。 在支持这些功能的多组件设备上(例如操作系统设备或固件设备),它们允许每个组件拥有独立的配置和状条件。

注意

本文所述的功能只能用于 IoT 中心的标准层。 有关 IoT 中心基本层和标准/免费层的详细信息,请参阅选择适合你的解决方案的 IoT 中心层

在本文结束时,你会有三个 Python 应用:

  • CreateModule:用于创建设备标识、模块标识和相关的安全密钥,以连接设备和模块客户端。

  • UpdateModuleTwinDesiredProperties:将更新的模块孪生所需属性发送到 IoT 中心。

  • ReceiveModuleTwinDesiredPropertiesPatch:在设备上接收模块孪生所需属性修补程序。

注意

有关可用于生成设备和后端应用的 SDK 工具的详细信息,请参阅 Azure IoT SDK

先决条件

  • 有效的 Azure 帐户。 (如果没有帐户,可以创建一个试用帐户,只需几分钟即可完成。)

  • IoT 中心。 使用 CLIAzure 门户创建一个。

  • 建议使用 Python 版本 3.7 或更高版本。 请确保根据安装程序的要求,使用 32 位或 64 位安装。 在安装过程中出现提示时,请确保将 Python 添加到特定于平台的环境变量中。

获取 IoT 中心连接字符串

在本文中,将创建一个后端服务,该服务在标识注册表中添加一个设备,然后向该设备添加一个模块。 此服务需要“注册表写入”权限(也包括“注册表读取”权限) 。 你还要创建一个服务,用于将所需属性添加到新建的模块的模块孪生中。 此服务需要“服务连接”权限 。 尽管有默认的共享访问策略可分别授予这些权限,但在本部分,你将创建一个包含这两个权限的自定义共享访问策略。

若要创建授予“服务连接” 和“注册表写入” 权限的共享访问策略,并获取此策略的连接字符串,请执行以下步骤:

  1. Azure 门户中,选择“资源组” 。 选择中心所在的资源组,然后从资源列表中选择中心。

  2. 在中心的左侧窗格上,选择“共享访问策略”。

  3. 在策略列表上方的菜单中,选择“添加共享访问策略”。

  4. 在“添加共享访问策略”下,输入策略的描述性名称,例如 serviceAndRegistryReadWrite。 在“权限”下,选择“注册表写入”和“服务连接”,然后选择“添加”。 (当你选择“注册表写入”时,将自动包括“注册表读取”权限。)

    Screen capture that shows how to add a new shared access policy

  5. 从策略列表中选择新策略。

  6. 在“共享访问密钥”下,选择“主连接字符串”的复制图标并保存值。

    Screen capture that shows how to retrieve the connection string

有关 IoT 中心共享访问策略和权限的详细信息,请参阅访问控制和权限

在 IoT 中心中创建设备标识和模块标识

本部分将创建一个 Python 服务应用,用于在 IoT 中心的标识注册表中创建设备标识和模块标识。 设备或模块无法连接到 IoT 中心,除非它在标识注册表中具有条目。 有关详细信息,请参阅了解 IoT 中心的标识注册表。 运行此控制台应用时,它会为设备和模块生成唯一的 ID 和密钥。 ID 和密钥区分大小写。 设备和模块在向 IoT 中心发送设备到云的消息时,使用这些值来标识自身。

  1. 在命令提示符处,运行以下命令以安装 azure-iot-hub 包:

    pip install azure-iot-hub
    
  2. 在命令提示符下,运行以下命令安装 msrest 包 。 需要使用此包来捕获 HTTPOperationError 异常 。

    pip install msrest
    
  3. 使用文本编辑器在工作目录中创建名为 CreateModule.py 的文件 。

  4. 将以下代码添加到 Python 文件。 将 YourIoTHubConnectionString 替换为在获取 IoT 中心连接字符串中复制的连接字符串 。

    import sys
    from msrest.exceptions import HttpOperationError
    from azure.iot.hub import IoTHubRegistryManager
    
    CONNECTION_STRING = "YourIotHubConnectionString"
    DEVICE_ID = "myFirstDevice"
    MODULE_ID = "myFirstModule"
    
    try:
        # RegistryManager
        iothub_registry_manager = IoTHubRegistryManager(CONNECTION_STRING)
    
        try:
            # CreateDevice - let IoT Hub assign keys
            primary_key = ""
            secondary_key = ""
            device_state = "enabled"
            new_device = iothub_registry_manager.create_device_with_sas(
                DEVICE_ID, primary_key, secondary_key, device_state
            )
        except HttpOperationError as ex:
            if ex.response.status_code == 409:
                # 409 indicates a conflict. This happens because the device already exists.
                new_device = iothub_registry_manager.get_device(DEVICE_ID)
            else:
                raise
    
        print("device <" + DEVICE_ID +
              "> has primary key = " + new_device.authentication.symmetric_key.primary_key)
    
        try:
            # CreateModule - let IoT Hub assign keys
            primary_key = ""
            secondary_key = ""
            managed_by = ""
            new_module = iothub_registry_manager.create_module_with_sas(
                DEVICE_ID, MODULE_ID, managed_by, primary_key, secondary_key
            )
        except HttpOperationError as ex:
            if ex.response.status_code == 409:
                # 409 indicates a conflict. This happens because the module already exists.
                new_module = iothub_registry_manager.get_module(DEVICE_ID, MODULE_ID)
            else:
                raise
    
        print("device/module <" + DEVICE_ID + "/" + MODULE_ID +
              "> has primary key = " + new_module.authentication.symmetric_key.primary_key)
    
    except Exception as ex:
        print("Unexpected error {0}".format(ex))
    except KeyboardInterrupt:
        print("IoTHubRegistryManager sample stopped")
    
  5. 在命令提示符下运行以下命令:

    python CreateModule.py
    

此应用在设备“myFirstDevice”下创建 ID 为“myFirstDevice”的设备标识,以及 ID 为“myFirstModule”的模块标识 。 (如果该设备或模块 ID 已存在于标识注册表中,代码就只检索现有的设备或模块信息。)应用将显示每个标识的 ID 和主密钥。

注意

IoT 中心标识注册表只存储设备和模块标识,以启用对 IoT 中心的安全访问。 标识注册表存储用作安全凭据的设备 ID 和密钥。 标识注册表还为每个设备存储启用/禁用标志,该标志可以用于禁用对该设备的访问。 如果应用程序需要存储其他特定于设备的元数据,则应使用特定于应用程序的存储。 没有针对模块标识的“已启用/已禁用”标记。 有关详细信息,请参阅了解 IoT 中心的标识注册表

使用 Python 服务 SDK 更新模块孪生

在本部分,你将创建一个用于更新模块孪生所需属性的 Python 服务应用。

  1. 在命令提示符下,运行以下命令以安装 azure-iot-hub 包 。 如果在上一部分已安装 azure-iot-hub 包,则可以跳过此步骤 。

    pip install azure-iot-hub
    
  2. 使用文本编辑器在工作目录中创建名为 UpdateModuleTwinDesiredProperties.py 的文件 。

  3. 将以下代码添加到 Python 文件。 将 YourIoTHubConnectionString 替换为在获取 IoT 中心连接字符串中复制的连接字符串 。

    import sys
    from azure.iot.hub import IoTHubRegistryManager
    from azure.iot.hub.models import Twin, TwinProperties
    
    CONNECTION_STRING = "YourIoTHubConnectionString"
    DEVICE_ID = "myFirstDevice"
    MODULE_ID = "myFirstModule"
    
    try:
        # RegistryManager
        iothub_registry_manager = IoTHubRegistryManager(CONNECTION_STRING)
    
        module_twin = iothub_registry_manager.get_module_twin(DEVICE_ID, MODULE_ID)
        print ( "" )
        print ( "Module twin properties before update    :" )
        print ( "{0}".format(module_twin.properties) )
    
        # Update twin
        twin_patch = Twin()
        twin_patch.properties = TwinProperties(desired={"telemetryInterval": 122})
        updated_module_twin = iothub_registry_manager.update_module_twin(
            DEVICE_ID, MODULE_ID, twin_patch, module_twin.etag
        )
        print ( "" )
        print ( "Module twin properties after update     :" )
        print ( "{0}".format(updated_module_twin.properties) )
    
    except Exception as ex:
        print ( "Unexpected error {0}".format(ex) )
    except KeyboardInterrupt:
        print ( "IoTHubRegistryManager sample stopped" )
    

在设备端获取更新

在本部分,你将创建一个用于在设备上获取模块孪生所需属性更新的 Python 应用。

  1. 获取模块连接字符串。 在 Azure 门户中导航到你的 IoT 中心,并在左侧窗格中选择“设备”。 从设备列表中选择“myFirstDevice”并将其打开 。 在“模块标识”下选择“myFirstModule”。 选择“连接字符串(主密钥)”的复制图标。 需要在以下步骤中使用此连接字符串。

    Screenshot of the Module Identity Details page in the Azure portal.

  2. 在命令提示符处,运行以下命令以安装 azure-iot-device 包:

    pip install azure-iot-device
    
  3. 使用文本编辑器在工作目录中创建名为 ReceiveModuleTwinDesiredPropertiesPatch.py 的文件 。

  4. 将以下代码添加到 Python 文件。 将 YourModuleConnectionString 替换为在步骤 1 中复制的模块连接字符串 。

    import time
    from azure.iot.device import IoTHubModuleClient
    
    CONNECTION_STRING = "YourModuleConnectionString"
    
    
    def twin_patch_handler(twin_patch):
        print("")
        print("Twin desired properties patch received:")
        print(twin_patch)
    
    
    def main():
        print ("Starting the IoT Hub Python sample...")
        client = IoTHubModuleClient.create_from_connection_string(CONNECTION_STRING)
    
        print ("Waiting for commands, press Ctrl-C to exit")
        try:
            # Attach the handler to the client
            client.on_twin_desired_properties_patch_received = twin_patch_handler
    
            while True:
                time.sleep(1000)
        except KeyboardInterrupt:
            print("IoTHubModuleClient sample stopped")
        finally:
            # Graceful exit
            print("Shutting down IoT Hub Client")
            client.shutdown()
    
    if __name__ == '__main__':
        main()
    

运行应用

在本部分,你将运行 ReceiveModuleTwinDesiredPropertiesPatch 设备应用,然后运行 UpdateModuleTwinDesiredProperties 服务应用来更新模块的所需属性 。

  1. 打开命令提示符并运行设备应用:

    python ReceiveModuleTwinDesiredPropertiesPatch.py
    

    Device app initial output

  2. 打开单独的命令提示符并运行服务应用:

    python UpdateModuleTwinDesiredProperties.py
    

    请注意,TelemetryInterval 所需属性显示在服务应用输出中已更新的模块孪生内 :

    Service app output

    相同的属性显示在设备应用输出中收到的所需属性修补程序内:

    Device app output shows desired properties patch

后续步骤

若要继续了解 IoT 中心入门知识并浏览其他 IoT 方案,请参阅: