设备孪生入门 (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 中心

此部分介绍如何使用 Azure 门户创建 IoT 中心。

  1. 登录到 Azure 门户

  2. 选择+“创建资源”,然后选择“物联网”。

  3. 在右侧列表中单击“Iot 中心”。 随即显示 IoT 中心创建过程的第一个屏幕。

    显示了在 Azure 门户中创建中心的屏幕截图

    填充字段。

    订阅:请选择要用于 IoT 中心的订阅。

    资源组:可创建新的资源组或使用现有资源组。 若要新建一个,请单击“新建”,并填写要使用的名称。 若要使用现有资源组,请单击“使用现有资源组”并从下拉列表中选择该组。 有关详细信息,请参阅使用资源组管理 Azure 资源

    区域:这是要在其中设置中心的区域。 从下拉列表中选择最靠近自己的位置。

    IoT 中心名称:输入 IoT 中心的名称。 此名称必须全局唯一。 如果输入的名称可用,会显示一个绿色复选标记。

    Important

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

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

    屏幕截图显示使用 Azure 门户为新的 IoT 中心设置大小和缩放级别

    在此屏幕上,可以采用默认值,只需在底部单击“查看+创建”即可。

    定价和缩放层级:可以根据需要的功能数以及每天通过解决方案发送的消息数从多个层中进行选择。 免费层适用于测试和评估。 它允许 500 台设备连接到 IoT 中心,并且每天最多传输 8,000 条信息。 每个 Azure 订阅可以在免费层中创建一个 IoT 中心。

    IoT 中心单位:每日每单位允许的消息数取决于中心的定价层。 例如,如果希望 IoT 中心支持 700,000 条消息输入,则选择两个 S1 层单位。

    有关其他层选项的详细信息,请参阅选择合适的 IoT 中心层

    高级/设备到云的分区:此属性将设备到云消息与这些消息的同步读取器数目相关联。 大多数 IoT 中心只需要 4 个分区。

  5. 单击“查看+创建”可查看选择。 会显示类似于以下的屏幕。

    屏幕截图显示用于创建新 IoT 中心的信息

  6. 单击“创建”以创建新的 IoT 中心。 创建中心需要几分钟时间。

检索 IoT 中心的连接字符串

创建中心以后,请检索中心的连接字符串。 该字符串用于将设备和应用程序连接到中心。

  1. 单击中心,查看“IoT 中心”窗格,其中包含“设置”等内容。 单击“共享访问策略”。

  2. 在“共享访问策略”中,选择 iothubowner 策略。

  3. 在“共享访问密钥”下,复制“连接字符串 -- 主密钥”供以后使用。

    显示如何检索连接字符串

    有关详细信息,请参阅“IoT 中心开发人员指南”中的访问控制

在 IoT 中心内注册新设备

本部分在 IoT 中心的标识注册表中创建设备标识。 设备无法连接到 IoT 中心,除非它在标识注册表中具有条目。 有关详细信息,请参阅 IoT 中心开发人员指南的“标识注册表”部分

  1. 在 IoT 中心导航菜单中,打开“IoT 设备”,然后单击“添加”,在 IoT 中心注册新设备。

    在门户中创建设备标识

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

    添加新设备

    Important

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

  3. 创建设备后,在“IoT 设备”窗格的列表中打开该设备。 复制“连接字符串 ---主密钥”供以后使用。

    设备连接字符串

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 中心的标识注册表中创建了设备标识。 已从后端应用以标记形式添加了设备元数据,并编写了模拟的设备应用,用于报告设备孪生中的设备连接信息。 你还学习了如何使用注册表查询此信息。

充分利用以下资源: