设备孪生入门 (Python)

设备孪生是存储设备状态信息(元数据、配置和条件)的 JSON 文档。 IoT 中心为连接到它的每台设备保留一个设备孪生。

Note

本文中所述的功能仅可在 IoT 中心的标准层中使用。 有关基本和标准 IoT 中心层的详细信息,请参阅如何选择合适的 IoT 中心层

使用设备孪生可以:

  • 存储来自解决方案后端的设备元数据。
  • 通过设备应用报告当前状态信息,例如可用功能和条件(例如,使用的连接方法)。
  • 同步设备应用和后端应用之间的长时间运行的工作流的状态(例如固件和配置更新)。
  • 查询设备的元数据、配置或状态。

设备孪生旨在执行同步以及查询设备的配置和条件。 了解设备孪生中提供了有关何时使用设备孪生的详细信息。

设备孪生存储在 IoT 中心内,其中包含:

  • 标记,仅可由解决方案后端访问的设备元数据;
  • 所需属性,可以由解决方案后端修改以及由设备应用观察的 JSON 对象;以及
  • 报告属性,可由设备应用修改以及由解决方案后端读取的 JSON 对象。 标记和属性不能包含数组,但可以嵌套对象。

此外,解决方案后端可以根据上述所有数据查询设备孪生。 有关设备孪生的详细信息,请参阅了解设备孪生,有关查询的参考,请参阅 IoT 中心查询语言

本教程演示如何:

  • 创建将标记添加到设备孪生的后端应用,以及将其连接通道作为设备孪生上的报告属性进行报告的模拟设备应用。
  • 使用标记上的筛选器和之前创建的属性通过后端应用查询设备。

在本教程结束时,会获得两个 Python 控制台应用:

  • AddTagsAndQuery.py,这是一个 Python 后端应用,用于添加标记并查询设备孪生。
  • ReportConnectivity.py,这是一个 .Python 应用,用于模拟使用早先创建的设备标识连接到 IoT 中心的设备,并报告其连接状况。

Note

Azure IoT SDK 文章介绍了可用于构建设备和后端应用的 Azure IoT SDK。

若要完成本教程,需要满足以下条件:

Note

适用于 azure-iothub-service-clientazure-iothub-device-client 的 pip 包目前仅供 Windows OS 使用。 对于 Linux/Mac OS,请参阅准备适用于 Python 的开发环境一文中特定于 Linux 和 Mac OS 的部分。

创建 IoT 中心

创建模拟设备应用要连接到的 IoT 中心。 以下步骤说明如何使用 Azure 门户来完成此任务。

  1. 登录到 Azure 门户

  2. 选择“创建资源” > “物联网” > “IoT 中心”。

    Azure 门户跳转栏

  3. 在“IoT 中心”窗格中,输入 IoT 中心的以下信息:

    • 订阅:选择需要将其用于创建此 IoT 中心的订阅。

    • 资源组:创建用于托管 IoT 中心的资源组,或使用现有的资源组。 有关详细信息,请参阅使用资源组管理 Azure 资源

    • 区域:选择最近的位置。

    • 名称:创建 IoT 中心的名称。 如果输入的名称可用,会显示一个绿色复选标记。

    Important

    IoT 中心将公开为 DNS 终结点,因此,命名时请务必避免包含任何敏感信息。

    IoT 中心基本信息窗口

  4. 选择“下一步: 大小和规模”,以便继续创建 IoT 中心。

  5. 选择“定价和缩放层”。 就本文来说,请选择“F1 - 免费”层(前提是此层在订阅上仍然可用)。 有关详细信息,请参阅定价和缩放层

    IoT 中心大小和规模窗口

  6. 选择“查看 + 创建”。

  7. 查看 IoT 中心信息,然后单击“创建”。 创建 IoT 中心可能需要数分钟的时间。 可在“通知”窗格中监视进度。

  8. 新的 IoT 中心就绪以后,请在 Azure 门户中单击其磁贴,打开其属性窗口。 创建 IoT 中心以后,即可找到将设备和应用程序连接到 IoT 中心时需要使用的重要信息。 单击“共享访问策略”。

  9. 在“共享访问策略”中,选择 iothubowner 策略。 复制 IoT 中心连接字符串 ---主密钥供以后使用。 有关详细信息,请参阅“IoT 中心开发人员指南”中的访问控制

    共享访问策略

创建设备标识

在本部分中,将使用 Azure 门户在 IoT 中心的标识注册表中创建设备标识。 设备无法连接到 IoT 中心,除非它在标识注册表中具有条目。 有关详细信息,请参阅 IoT 中心开发人员指南的“标识注册表”部分。 使用门户中的“IoT 设备”面板为设备生成唯一设备 ID 和密钥,以用于在 IoT 中心中标识它本身。 设备 ID 区分大小写。

  1. 登录到 Azure 门户

  2. 选择“所有资源”,并查找 IoT 中心资源。

  3. 打开 IoT 中心资源后,单击“IoT 设备”工具,并单击顶部的“添加”。

    在门户中创建设备标识

  4. 提供新设备的名称(例如 myDeviceId),然后单击“保存”。 此操作会为 IoT 中心创建新设备标识。

    Important

    收集的日志中可能会显示设备 ID 用于客户支持和故障排除,因此,在为日志命名时,请务必避免包含任何敏感信息。

    添加新设备

  5. 在设备列表中,单击新创建的设备,复制“连接字符串---主键”供以后使用。

    设备连接字符串

Note

IoT 中心标识注册表仅存储用于实现 IoT 中心安全访问的设备标识。 它存储设备 ID 和密钥作为安全凭据,以及启用/禁用标志让你禁用对单个设备的访问。 如果应用程序需要存储其他特定于设备的元数据,则应使用特定于应用程序的存储。 有关详细信息,请参阅 IoT 中心开发人员指南

创建服务应用

在本部分中,将创建一个 Python 控制台应用,该应用将位置元数据添加到与 {Device Id} 关联的设备孪生。 然后,该应用将选择位于 Redmond 的设备来查询存储在 IoT 中心的设备孪生,然后查询报告移动电话网络连接的设备孪生。

  1. 打开命令提示符,然后安装用于 Python 的 Azure IoT 中心服务 SDK。 在安装 SDK 之后关闭命令提示符。

    pip install azure-iothub-service-client
    
  2. 使用文本编辑器,新建一个 AddTagsAndQuery.py 文件。

  3. 添加以下代码,从服务 SDK 导入所需模块:

    import sys
    import iothub_service_client
    from iothub_service_client import IoTHubRegistryManager, IoTHubRegistryManagerAuthMethod
    from iothub_service_client import IoTHubDeviceTwin, IoTHubError
    
  4. 添加以下代码,将 [IoTHub Connection String][Device Id] 的占位符替换为在前面的部分中创建的 IoT 中心的连接字符串和设备 ID。

    CONNECTION_STRING = "[IoTHub Connection String]"
    DEVICE_ID = "[Device Id]"
    
    UPDATE_JSON = "{\"properties\":{\"desired\":{\"location\":\"Redmond\"}}}"
    
    UPDATE_JSON_SEARCH = "\"location\":\"Redmond\""
    UPDATE_JSON_CLIENT_SEARCH = "\"connectivity\":\"cellular\""
    
  5. 将以下代码添加到 AddTagsAndQuery.py 文件:

    def iothub_service_sample_run():
       try:
           iothub_registry_manager = IoTHubRegistryManager(CONNECTION_STRING)
    
           iothub_registry_statistics = iothub_registry_manager.get_statistics()
           print ( "Total device count                       : {0}".format(iothub_registry_statistics.totalDeviceCount) )
           print ( "Enabled device count                     : {0}".format(iothub_registry_statistics.enabledDeviceCount) )
           print ( "Disabled device count                    : {0}".format(iothub_registry_statistics.disabledDeviceCount) )
           print ( "" )
    
           number_of_devices = iothub_registry_statistics.totalDeviceCount
           dev_list = iothub_registry_manager.get_device_list(number_of_devices)
    
           iothub_twin_method = IoTHubDeviceTwin(CONNECTION_STRING)
    
           for device in range(0, number_of_devices):
               if dev_list[device].deviceId == DEVICE_ID:
                   twin_info = iothub_twin_method.update_twin(dev_list[device].deviceId, UPDATE_JSON)
    
           print ( "Devices in Redmond: " )        
           for device in range(0, number_of_devices):
               twin_info = iothub_twin_method.get_twin(dev_list[device].deviceId)
    
               if twin_info.find(UPDATE_JSON_SEARCH) > -1:
                   print ( dev_list[device].deviceId )
    
           print ( "" )
    
           print ( "Devices in Redmond using cellular network: " )
           for device in range(0, number_of_devices):
               twin_info = iothub_twin_method.get_twin(dev_list[device].deviceId)
    
               if twin_info.find(UPDATE_JSON_SEARCH) > -1:
                   if twin_info.find(UPDATE_JSON_CLIENT_SEARCH) > -1:
                       print ( dev_list[device].deviceId )
    
       except IoTHubError as iothub_error:
           print ( "Unexpected error {0}".format(iothub_error) )
           return
       except KeyboardInterrupt:
           print ( "IoTHub sample stopped" )
    

    Registry 对象公开从服务与设备孪生进行交互所需的所有方法。 此代码将首先初始化 Registry 对象,然后更新 deviceId 的设备孪生,最后运行两个查询。 第一个查询仅选择位于 Redmond43 工厂的设备的设备孪生,第二个查询将查询细化为仅选择还要通过移动电话网络连接的设备。

  6. AddTagsAndQuery.py 的末尾添加以下代码来实现 iothub_service_sample_run 函数:

    if __name__ == '__main__':
        print ( "Starting the IoT Hub Device Twins Python service sample..." )
    
        iothub_service_sample_run()
    
  7. 使用以下内容运行应用程序:

    python AddTagsAndQuery.py
    

    在查询位于 Redmond43 的所有设备的查询结果中,应该会看到一个设备,而在将结果限制为使用蜂窝网络的设备的查询结果中没有任何设备。

    第一个查询

在下一部分中,创建的设备应用会报告连接信息,并更改上一部分中查询的结果。

创建设备应用

在本部分中,将创建一个 Python 控制台应用,该应用以你的 {Device Id} 身份连接到中心,然后更新其设备孪生的报告属性,来说明它是使用手机网络进行连接的。

  1. 打开命令提示符,然后安装用于 Python 的 Azure IoT 中心服务 SDK。 在安装 SDK 之后关闭命令提示符。

    pip install azure-iothub-device-client
    
  2. 使用文本编辑器,新建一个 ReportConnectivity.py 文件。

  3. 添加以下代码,从服务 SDK 导入所需模块:

    import time
    import iothub_client
    from iothub_client import IoTHubClient, IoTHubClientError, IoTHubTransportProvider, IoTHubClientResult, IoTHubError
    
  4. 添加以下代码,将 [IoTHub Device Connection String] 的占位符替换为在前面的部分中创建的 IoT 中心设备的连接字符串。

    CONNECTION_STRING = "[IoTHub Device Connection String]"
    
    # choose HTTP, AMQP, AMQP_WS or MQTT as transport protocol
    PROTOCOL = IoTHubTransportProvider.MQTT
    
    TIMER_COUNT = 5
    TWIN_CONTEXT = 0
    SEND_REPORTED_STATE_CONTEXT = 0
    
  5. 将以下代码添加到 ReportConnectivity.py 文件以实现设备孪生功能:

    def device_twin_callback(update_state, payload, user_context):
        print ( "" )
        print ( "Twin callback called with:" )
        print ( "    updateStatus: %s" % update_state )
        print ( "    payload: %s" % payload )
    
    def send_reported_state_callback(status_code, user_context):
        print ( "" )
        print ( "Confirmation for reported state called with:" )
        print ( "    status_code: %d" % status_code )
    
    def iothub_client_init():
        client = IoTHubClient(CONNECTION_STRING, PROTOCOL)
    
        if client.protocol == IoTHubTransportProvider.MQTT or client.protocol == IoTHubTransportProvider.MQTT_WS:
            client.set_device_twin_callback(
                device_twin_callback, TWIN_CONTEXT)
    
        return client
    
    def iothub_client_sample_run():
        try:
            client = iothub_client_init()
    
            if client.protocol == IoTHubTransportProvider.MQTT:
                print ( "Sending data as reported property..." )
    
                reported_state = "{\"connectivity\":\"cellular\"}"
    
                client.send_reported_state(reported_state, len(reported_state), send_reported_state_callback, SEND_REPORTED_STATE_CONTEXT)
    
            while True:
                print ( "Press Ctrl-C to exit" )
    
                status_counter = 0
                while status_counter <= TIMER_COUNT:
                    status = client.get_send_status()
                    time.sleep(10)
                    status_counter += 1 
        except IoTHubError as iothub_error:
            print ( "Unexpected error %s from IoTHub" % iothub_error )
            return
        except KeyboardInterrupt:
            print ( "IoTHubClient sample stopped" )
    

    Client 对象公开从该设备与设备孪生交互所需的所有方法。 上面的代码首先初始化 Client 对象,然后检索你的设备的设备孪生,并使用连接信息更新其报告属性。

  6. ReportConnectivity.py 的末尾添加以下代码来实现 iothub_client_sample_run 函数:

    if __name__ == '__main__':
        print ( "Starting the IoT Hub Device Twins Python client sample..." )
    
        iothub_client_sample_run()
    
  7. 运行设备应用

    python ReportConnectivity.py
    

    应当会看到关于设备孪生已更新的确认。

    更新孪生

  8. 现在设备报告了其连接信息,应出现在两个查询中。 回过头来再次运行查询:

    python AddTagsAndQuery.py
    

    这一次,两个查询结果中应当都会显示你的 {Device Id}

    第二个查询

后续步骤

本教程中,在 Azure 门户中配置了新的 IoT 中心,并在 IoT 中心的标识注册表中创建了设备标识。 已从后端应用以标记形式添加了设备元数据,并编写了模拟的设备应用,用于报告设备孪生中的设备连接信息。 你还学习了如何使用注册表查询此信息。

充分利用以下资源: