你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
IoT 中心模块标识和模块孪生 (Python) 入门
模块标识和模块孪生类似于 Azure IoT 中心设备标识和设备孪生,但提供更精细的粒度。 Azure IoT 中心设备标识和设备孪生允许后端应用程序配置设备并提供对设备状况的可见性,而模块标识和模块孪生为设备的各个组件提供这些功能。 在支持这些功能的多组件设备上(例如操作系统设备或固件设备),它们允许每个组件拥有独立的配置和状条件。
注意
本文所述的功能只能用于 IoT 中心的标准层。 有关 IoT 中心基本层和标准/免费层的详细信息,请参阅选择适合你的解决方案的 IoT 中心层。
在本文结束时,你会有三个 Python 应用:
CreateModule:用于创建设备标识、模块标识和相关的安全密钥,以连接设备和模块客户端。
UpdateModuleTwinDesiredProperties:将更新的模块孪生所需属性发送到 IoT 中心。
ReceiveModuleTwinDesiredPropertiesPatch:在设备上接收模块孪生所需属性修补程序。
注意
有关可用于生成设备和后端应用的 SDK 工具的详细信息,请参阅 Azure IoT SDK。
先决条件
有效的 Azure 帐户。 (如果没有帐户,只需几分钟即可创建一个免费帐户。)
Azure 订阅中的 IoT 中心。 如果还没有中心,则可以按照创建 IoT 中心中的步骤进行操作。
建议使用 Python 版本 3.7 或更高版本。 请确保根据安装程序的要求,使用 32 位或 64 位安装。 在安装过程中出现提示时,请确保将 Python 添加到特定于平台的环境变量中。
模块身份验证
你可以使用对称密钥或 X.509 证书对模块标识进行身份验证。 对于 X.509 证书身份验证,模块的证书的公用名 (CN) 格式必须 如 CN=<deviceid>/<moduleid>
所示。 例如:
openssl req -new -key d1m1.key.pem -out d1m1.csr -subj "/CN=device01\/module01"
获取 IoT 中心连接字符串
在本文中,将创建一个后端服务,该服务在标识注册表中添加一个设备,然后向该设备添加一个模块。 此服务需要“注册表写入”权限(也包括“注册表读取”权限) 。 你还要创建一个服务,用于将所需属性添加到新建的模块的模块孪生中。 此服务需要“服务连接”权限 。 尽管有默认的共享访问策略可分别授予这些权限,但在本部分,你将创建一个包含这两个权限的自定义共享访问策略。
若要创建授予“服务连接” 和“注册表写入” 权限的共享访问策略,并获取此策略的连接字符串,请执行以下步骤:
在 Azure 门户中,选择“资源组” 。 选择中心所在的资源组,然后从资源列表中选择中心。
在中心的左侧窗格上,选择“共享访问策略”。
在策略列表上方的菜单中,选择“添加共享访问策略”。
在“添加共享访问策略”下,输入策略的描述性名称,例如 serviceAndRegistryReadWrite。 在“权限”下,选择“注册表写入”和“服务连接”,然后选择“添加”。 (当你选择“注册表写入”时,将自动包括“注册表读取”权限。)
从策略列表中选择新策略。
在“共享访问密钥”下,选择“主连接字符串”的复制图标并保存值。
有关 IoT 中心共享访问策略和权限的详细信息,请参阅访问控制和权限。
重要
本文介绍使用共享访问签名连接到服务的步骤。 虽然可使用此身份验证方法进行测试和评估,但使用 Microsoft Entra ID 或托管标识对设备进行身份验证是一种更安全的方法。 有关详细信息,请参阅安全最佳做法和云安全。
在 IoT 中心中创建设备标识和模块标识
本部分将创建一个 Python 服务应用,用于在 IoT 中心的标识注册表中创建设备标识和模块标识。 设备或模块无法连接到 IoT 中心,除非它在标识注册表中具有条目。 有关详细信息,请参阅了解 IoT 中心的标识注册表。 运行此控制台应用时,它会为设备和模块生成唯一的 ID 和密钥。 ID 和密钥区分大小写。 设备和模块在向 IoT 中心发送设备到云的消息时,使用这些值来标识自身。
重要
本文包括使用共享访问签名(也称为对称密钥身份验证)连接设备的步骤。 此身份验证方法便于测试和评估,但使用 X.509 证书对设备进行身份验证是一种更安全的方法。 若要了解详细信息,请参阅“安全最佳做法 > 连接安全性”。
在命令提示符处,运行以下命令以安装 azure-iot-hub 包:
pip install azure-iot-hub
在命令提示符下,运行以下命令安装 msrest 包 。 需要使用此包来捕获 HTTPOperationError 异常 。
pip install msrest
使用文本编辑器在工作目录中创建名为 CreateModule.py 的文件 。
将以下代码添加到 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")
在命令提示符下运行以下命令:
python CreateModule.py
此应用在设备“myFirstDevice”下创建 ID 为“myFirstDevice”的设备标识,以及 ID 为“myFirstModule”的模块标识 。 (如果该设备或模块 ID 已存在于标识注册表中,代码就只检索现有的设备或模块信息。)应用将显示每个标识的 ID 和主密钥。
注意
IoT 中心标识注册表只存储设备和模块标识,以启用对 IoT 中心的安全访问。 标识注册表存储用作安全凭据的设备 ID 和密钥。 标识注册表还为每个设备存储启用/禁用标志,该标志可以用于禁用对该设备的访问。 如果应用程序需要存储其他特定于设备的元数据,则应使用特定于应用程序的存储。 没有针对模块标识的“已启用/已禁用”标记。 有关详细信息,请参阅了解 IoT 中心的标识注册表。
使用 Python 服务 SDK 更新模块孪生
在本部分,你将创建一个用于更新模块孪生所需属性的 Python 服务应用。
在命令提示符下,运行以下命令以安装 azure-iot-hub 包 。 如果在上一部分已安装 azure-iot-hub 包,则可以跳过此步骤 。
pip install azure-iot-hub
使用文本编辑器在工作目录中创建名为 UpdateModuleTwinDesiredProperties.py 的文件 。
将以下代码添加到 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 应用。
获取模块连接字符串。 在 Azure 门户中导航到你的 IoT 中心,并在左侧窗格中选择“设备”。 从设备列表中选择“myFirstDevice”并将其打开 。 在“模块标识”下选择“myFirstModule”。 选择“连接字符串(主密钥)”的复制图标。 需要在以下步骤中使用此连接字符串。
在命令提示符处,运行以下命令以安装 azure-iot-device 包:
pip install azure-iot-device
使用文本编辑器在工作目录中创建名为 ReceiveModuleTwinDesiredPropertiesPatch.py 的文件 。
将以下代码添加到 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 服务应用来更新模块的所需属性 。
打开命令提示符并运行设备应用:
python ReceiveModuleTwinDesiredPropertiesPatch.py
打开单独的命令提示符并运行服务应用:
python UpdateModuleTwinDesiredProperties.py
请注意,TelemetryInterval 所需属性显示在服务应用输出中已更新的模块孪生内 :
相同的属性显示在设备应用输出中收到的所需属性修补程序内:
后续步骤
若要继续了解 IoT 中心入门知识并浏览其他 IoT 方案,请参阅: