Amazon IoT Device Shadow 演示应用程序 - FreeRTOS
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Amazon IoT Device Shadow 演示应用程序

重要

此演示托管在 Amazon-FreeRTOS 存储库中,该存储库已过时。建议您在创建新项目时从这里开始。如果您已经有一个基于现已弃用的 Amazon-FreeRTOS 存储库的现有 FreeRTOS 项目,请参阅亚马逊 FreeRTOS Github 存储库迁移指南

介绍

此演示说明如何使用Device Shadow 库连接到Device Shadow 服务。Amazon IoTAmazon它使用 TLS(双CoreMQTLARARARAR向身份验证)建立与 MQTT 代理的Amazon IoT MQTT 连接,并使用 CoreJSON 库解析器来解析从影子服务收到的Amazon影子文档。该演示显示了基本的影子操作,例如如何更新影子文档和如何删除影子文档。该演示还展示了如何在 CoreMQTT 库中注册回调函数,以处理诸如影子之类的/update/delta消息/update以及从 Device Shadow 服务发送的Amazon IoT消息。

此演示仅用于学习练习,因为更新影子文档(状态)的请求和更新响应是由同一个应用程序完成的。在实际生产场景中,即使设备当前未连接,外部应用程序也会远程请求更新设备的状态。设备连接后将确认更新请求。

注意

要设置和运行 FreeRTOS 演示,请按照中的步骤操作FreeRTOS 入门

功能

该演示创建了一个单一的应用程序任务,该任务循环浏览了一组示例,这些示例演示了暗影/update/update/delta回调,以模拟切换远程设备的状态。它发送带有新desired状态的影子更新,并等待设备根据新reported状态更改其desired状态。此外,阴影/update回调用于打印不断变化的阴影状态。此演示还使用了与 MQTT Broker 的安全Amazon IoT MQTT 连接,并假设设备影子中存在powerOn状态。

该演示执行以下操作:

  1. 使用中的帮助函数建立 MQTT 连接shadow_demo_helpers.c

  2. 使用Device Shadow 库定义的宏汇编用于设备影子操作的 MQTT 主题字符串。Amazon IoT

  3. 发布到用于删除设备影子的 MQTT 主题以删除任何现有的设备影子。

  4. 订阅有关的 MQTT 主题/update/delta/update/accepted并在中/update/rejected使用辅助函数shadow_demo_helpers.c

  5. 在中发布powerOn使用辅助函数的所需状态shadow_demo_helpers.c。这将导致向设备发送/update/delta消息。

  6. 处理传入的 MQTT 消息prvEventCallback,并使用Device Shadow 库 (Shadow_MatchTopic) 定义的函数确定该消息是否与Amazon IoT设备影子有关。如果消息是设备影子/update/delta消息,则主演示功能将发布第二条消息,将报告的状态更新为powerOn。如果收到/update/accepted消息,请验证该消息是否与先前在更新消息中发布的消息clientToken相同。这将标志着演示的结束。


                影子演示终端输出

演示可以在文件中找到,freertos/demos/device_shadow_for_aws/shadow_demo_main.c也可以在上面找到 GitHub

以下屏幕截图显示 Demo 成功执行时的预期输出。


                影子演示终端输出显示成功

Connect 到Amazon IoT MQTT 经纪人

要连接到Amazon IoT MQTT 代理,我们使用与MQTT_Connect()中相同的方法CoreMQTT 双向身份验证演示

删除影子文档

要删除影子文档,请xPublishToTopic使用 Device Shadow 库定义的宏调Amazon IoT用一条空消息。这MQTT_Publish用于发布/delete主题。以下代码部分显示了如何在函数中执行此操作prvShadowDemoTask

/* First of all, try to delete any Shadow document in the cloud. */ returnStatus = PublishToTopic( SHADOW_TOPIC_STRING_DELETE( THING_NAME ), SHADOW_TOPIC_LENGTH_DELETE( THING_NAME_LENGTH ), pcUpdateDocument, 0U );

订阅影子主题

订阅 Device Shadow 主题以接收来自Amazon IoT代理的有关影子变更的通知。Device Shadow 主题由Device Shadow 库中定义的宏组合而成。以下代码部分显示了如何在prvShadowDemoTask函数中执行此操作。

/* Then try to subscribe shadow topics. */ if( returnStatus == EXIT_SUCCESS ) { returnStatus = SubscribeToTopic( SHADOW_TOPIC_STRING_UPDATE_DELTA( THING_NAME ), SHADOW_TOPIC_LENGTH_UPDATE_DELTA( THING_NAME_LENGTH ) ); } if( returnStatus == EXIT_SUCCESS ) { returnStatus = SubscribeToTopic( SHADOW_TOPIC_STRING_UPDATE_ACCEPTED( THING_NAME ), SHADOW_TOPIC_LENGTH_UPDATE_ACCEPTED( THING_NAME_LENGTH ) ); } if( returnStatus == EXIT_SUCCESS ) { returnStatus = SubscribeToTopic( SHADOW_TOPIC_STRING_UPDATE_REJECTED( THING_NAME ), SHADOW_TOPIC_LENGTH_UPDATE_REJECTED( THING_NAME_LENGTH ) ); }

发送影子更新

要发送影子更新,演示使用Device Shadow 库定义的宏调xPublishToTopic用 JSON 格式的消息。这MQTT_Publish用于发布/delete主题。以下代码部分显示了如何在prvShadowDemoTask函数中执行此操作。

#define SHADOW_REPORTED_JSON \ "{" \ "\"state\":{" \ "\"reported\":{" \ "\"powerOn\":%01d" \ "}" \ "}," \ "\"clientToken\":\"%06lu\"" \ "}" snprintf( pcUpdateDocument, SHADOW_REPORTED_JSON_LENGTH + 1, SHADOW_REPORTED_JSON, ( int ) ulCurrentPowerOnState, ( long unsigned ) ulClientToken ); xPublishToTopic( SHADOW_TOPIC_STRING_UPDATE( THING_NAME ), SHADOW_TOPIC_LENGTH_UPDATE( THING_NAME_LENGTH ), pcUpdateDocument, ( SHADOW_DESIRED_JSON_LENGTH + 1 ) );

处理影子增量消息和影子更新消息

使用该函数注册到 CoreMQTT 客户端库的用户回调MQTT_Init函数将通知我们传入的数据包事件。请参阅 prvEventCallback上的回调函数 GitHub。

回调函数确认传入的数据包是类型的MQTT_PACKET_TYPE_PUBLISH,并使用Device Shadow 库 APIShadow_MatchTopic 来确认传入的消息是影子消息。

如果传入的消息是类型为的影子消息ShadowMessageTypeUpdateDelta,则我们调用 prvUpdateDeltaHandler 来处理此消息。处理程序prvUpdateDeltaHandler使用 CoreJSON 库解析消息以获取powerOn状态的增量值,并将其与本地维护的当前设备状态进行比较。如果两者不同,则会更新本地设备状态以反映影子文档中powerOn状态的新值。

如果传入的消息是类型为的影子消息ShadowMessageTypeUpdateAccepted,则我们调用 prvUpdateAcceptedHandler 来处理此消息。处理程序使用 CoreJSON 库prvUpdateAcceptedHandler解析消息,以clientToken从消息中获取。此处理函数检查 JSON 消息中的客户端令牌是否与应用程序使用的客户端令牌相匹配。如果不匹配,该函数会记录警告消息。