学完本章节后,您的解决方案将能够:
在这一章节,您将构建无服务器应用程序,分析来自智能恒温器的输入数据并确定相应(虚构)的 HVAC 系统的行为。您将使用 IoT Events 来部署检测器模型这一资源来处理 IoT Core 规则转发的设备影子消息,评估是否需要将状态从制热切换到制冷再切换到待机,然后将最新的状态更改(如果有)以消息的形式发送回智能恒温器。
我们先来了解一下要创建的检测器模型:
如您所见,HVAC 应用程序有三种状态:制热、制冷和待机。应用程序会处于其中一种状态并且初始化为 standby(待机) 状态。来自智能恒温器的新消息送达后,检测器模型会对照条件逻辑来评估输入数据,以便确定模型是否应该转换到新的状态。
例如,之前处于 待机 状态,但如果新的温度读数高于 80 华氏度,那么模型评估结果为需要转换到 制冷 状态。进入 制冷 状态后,模型会向 IoT Core 发送一条新消息,来更新智能恒温器的设备影子,消息内容类似于:{ "state": { "desired": { "hvacStatus": "COOLING" } } }
。根据您最初在 数据同步 章节所做的工作,新命令会得到确认,并且设备上的状态也会据此进行更新,方式是 LED 灯变为红色、蓝色或关闭,以便体现出命令执行结果。
本学习模块不详细讲解如何在 IoT Events 中创建检测器模型。但是,您可以参照以下步骤来启动和运行检测器模型,您还可以了解到一些有关主要内容的说明,以便了解 该模型 的工作原理。如果您刚刚开始使用 AWS IoT Events,请参阅 开发人员指南 。
要创建上图中显示的检测器模型,请完成以下步骤:
首先,在本地桌面上创建一个文件,文件内容如下。文件名可以设置为 model.json
,您务必使用您的设备的客户端 Id/序列号(显示在您的设备屏幕上)替换 «CLIENT_ID»。
{
"detectorModelDefinition": {
"states": [
{
"stateName": "standby",
"onInput": {
"events": [],
"transitionEvents": [
{
"eventName": "startHeating",
"condition": "($input.thermostat.current.state.reported.temperature <= $variable.heatingThresholdUnoccupied) || ($input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature <= $variable.heatingThresholdOccupied) ",
"actions": [],
"nextState": "heating"
},
{
"eventName": "startCooling",
"condition": "($input.thermostat.current.state.reported.temperature >= $variable.coolingThresholdUnoccupied) || ($input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature >= $variable.coolingThresholdOccupied) ",
"actions": [],
"nextState": "cooling"
}
]
},
"onEnter": {
"events": [
{
"eventName": "setThresholds",
"condition": "true",
"actions": [
{
"setVariable": {
"variableName": "heatingThresholdUnoccupied",
"value": "60"
}
},
{
"setVariable": {
"variableName": "heatingThresholdOccupied",
"value": "68"
}
},
{
"setVariable": {
"variableName": "coolingThresholdOccupied",
"value": "72"
}
},
{
"setVariable": {
"variableName": "coolingThresholdUnoccupied",
"value": "80"
}
}
]
},
{
"eventName": "setStandbyInShadow",
"condition": "true",
"actions": [
{
"iotTopicPublish": {
"mqttTopic": "'$aws/things/<<CLIENT_ID>>/shadow/update'",
"payload": {
"contentExpression": "'{\"state\":{\"desired\":{\"hvacStatus\":\"STANDBY\"}}}'",
"type": "JSON"
}
}
}
]
}
]
},
"onExit": {
"events": []
}
},
{
"stateName": "cooling",
"onInput": {
"events": [],
"transitionEvents": [
{
"eventName": "stopCooling",
"condition": "(!$input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature < $variable.coolingThresholdUnoccupied) || ($input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature < $variable.coolingThresholdOccupied) ",
"actions": [],
"nextState": "standby"
}
]
},
"onEnter": {
"events": [
{
"eventName": "setCoolingInShadow",
"condition": "true",
"actions": [
{
"iotTopicPublish": {
"mqttTopic": "'$aws/things/<<CLIENT_ID>>/shadow/update'",
"payload": {
"contentExpression": "'{\"state\":{\"desired\":{\"hvacStatus\":\"COOLING\"}}}'",
"type": "JSON"
}
}
}
]
}
]
},
"onExit": {
"events": []
}
},
{
"stateName": "heating",
"onInput": {
"events": [],
"transitionEvents": [
{
"eventName": "stopHeating",
"condition": "(!$input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature > $variable.heatingThresholdUnoccupied) || ($input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature > $variable.heatingThresholdOccupied) ",
"actions": [],
"nextState": "standby"
}
]
},
"onEnter": {
"events": [
{
"eventName": "setHeatingInShadow",
"condition": "true",
"actions": [
{
"iotTopicPublish": {
"mqttTopic": "'$aws/things/<<CLIENT_ID>>/shadow/update'",
"payload": {
"contentExpression": "'{\"state\":{\"desired\":{\"hvacStatus\":\"HEATING\"}}}'",
"type": "JSON"
}
}
}
]
}
]
},
"onExit": {
"events": []
}
}
],
"initialStateName": "standby"
},
"detectorModelName": "hvacApplication",
"detectorModelDescription": "cloud application to manage HVAC state",
"evaluationMethod": "BATCH"
}
接下来,使用该文件在 AWS IoT Events 控制台中导入新的检测器模型:
edukit-iotevents
。控制台将创建新的 IAM 角色,该角色授予 IoT Events 操作模型的权限。您已经将检测器模型部署到 IoT Events。智能恒温器发布新消息后,您在上一章节中创建的 IoT Core 规则会将消息转发给 IoT Events 输入资源,然后 IoT Events 会将来自任何输入的消息副本推送到任何使用数据的检测器模型,就像当前这个一样,用于评估是否需要更改状态。
我们来了解一下有关模型的几项重要内容。模型的每种状态(制热/制冷/待机)都几乎相同。待机 状态有一项额外的操作,即设置数值阈值,用于确定是否需要更改状态。您可以在第一次进入 待机 状态之前,在初始化状态下设置一次数值阈值,但是,为了便于演示,待机 状态中已经包含了这些值。
其他状态配置也类似。OnEnter 事件会向智能恒温器的设备影子发布消息,说明 HVAC 系统应进入何种状态。系统处理每一条消息后,会评估条件转换,以便确定是否需要更改状态。例如,如果模型处于 制热 状态,并且针对 stopHeating 的条件表达式评估为真,则模型将转换为 待机 状态。请注意,待机 状态涉及两种转换,一种是转换为 制热,另一种是转换为 制冷。我们对模型进行了简化,因为系统总是要从 待机 状态转换到 制热 状态或 制冷 状态,而不是直接从 制热 状态转换到 制冷 状态或直接从 制冷 状态转换到 制热 状态。条件转换逻辑考虑到了两个温度界限:空间内有人时的温度界限和空间内无人时的温度界限。
以下是从 制热 状态(标记为 stopHeating)进行转换的示例。有两个与 OR ||
逻辑关联的布尔表达式。简而言之,表达式的意思是 “如果空间内没有人,并且空间内没有人时也足够暖和,则停止制热,或者如果空间内有人,并且足够暖和,则停止制热。”
(!$input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature > $variable.heatingThresholdUnoccupied) || ($input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature > $variable.heatingThresholdOccupied)
如果您已经按照本模块中的说明完成了所有配置,那么现在应该能够看到发送到智能恒温器的状态更改信息,其形式为更新 LED 灯条状态,至此,我们已经完成了端到端的解决方案!
在进入下一章节之前,您可以验证您的解决方案是否已按预期配置完毕,方法是:
请注意:温度传感器位于套件外壳内,代码包含硬编码的偏移。不同的温度读数之间的偏差可能高达 10 度。
如果解决方案符合预期,就可以进入 总结 部分。
AWS IoT Kit now features direct access to
AWS re:Post
, which is a community-driven, questions-and-answers service. Search re:Post using the
AWS IoT Kit
tag to see if your question has been asked and answered. If not, ask a new question using the AWS IoT Kit
tag.