树莓派+node-red搭建温湿度监控告警系统
简介
本文档介绍了基于树莓派+百度天工(物接入、TSDB、物可视)快速搭建一个环境温湿度监测告警系统。帮助用户熟悉天工物接入的接入方式、物影子概念以及使用方式等内容,快速搭建自己物联网硬件和应用。
阅读本示例前建议先熟悉快速入门文档。
场景描述
该场景演示物联网应用场景中常用的功能,包括设备接入、数据上报、数据存储、数据展示、远程控制、配置下发等。
- 硬件设计
首先我们设计了一款智能温湿度监测仪,监测仪运行时会实时监测当前所处环境的温湿度,同时可以设置温湿度的告警值,当温湿度达到设定值时,相应的告警灯亮起——这是设备硬件部分具备的功能,还未涉及到物联网
- 设备接入
为了能够实时查看到环境温信息,进而需要将设备接入物联网平台,如果当前环境温湿度达到设置的阈值,触发设备告警灯亮起,并上报设备当前状态和温湿度信息,正常情况下则每30秒上报一次当前温湿度信息到平台
- 配置下发
通过远程向监测仪下发配置信息,修改温湿度的告警值
- 远程控制
硬件部分具备告警指示灯功能,温度、湿度值分别达到告警值时,对应的指示灯会亮起并保持常亮,通过远程指令消除告警状态熄灭指示灯
- 数据存储(拓展)
平台接收到信息后可以将温湿度数据存储,以便进行数据展示、分析
- 数据展示(拓展)
设备接入平台后,我们通过大屏的对实时和历史数据进行仪表盘、图表等展示监控,同时可展示告警状态
硬件清单
- 树莓派3B+ 1台
- DHT11温湿度传感器 1个
- LED指示灯(普通发光二极管) 2个
方案设计
- 使用树莓派+node-red实现硬件控制,预装Raspian系统的树莓派自带node-red,不需要安装,使用其他操作系统的树莓派可能需要单独安装一下,关于node-red的介绍和安装本教程不做详细介绍,不了解的同学可以自行百度学习
- 在平台创建相应的物模型和物影子,获取设备接入平台需要的MQTT连接信息
- 使用树莓派外接温湿度传感器以30s周期实时采集环境温湿度,并上报到平台
- 设置报警阈值,当温湿度达到设定值后,树莓派外接报警指示灯亮起,可通过微信小程序或控制台远程消除报警状态熄灭告警灯
- 设置数据自动存储到TSDB
- 配置物可视大屏实时显示当前温湿度信息以及历史数据曲线、温湿度超限报警信息
操作步骤
创建物模型和设备影子
物模型配置
首先按如下配置信息在控制台创建一个物模型,物模型中设置了6个属性,分别代表温湿度当前值、温湿度告警指示灯状态、温湿度告警阈值,详细配置如下:
名称:hygrothermoscope
描述:用于天工平台能力演示的通用设备
序号 | 显示名称 | 属性名称 | 数据类型 | 默认值 | 单位 |
---|---|---|---|---|---|
1 | 温度 | temperature | number | 0.00 | ℃ |
2 | 湿度 | humidity | number | 0.00 | %rh |
3 | 温度告警 | temperature_alarm | number | 0 | |
4 | 湿度告警 | humidity_alarm | number | 0 | |
5 | 温度阈值 | temperature_alarm_value | number | 25 | ℃ |
6 | 湿度阈值 | humidity_alarm_value | number | 40 | %rh |
物影子配置
创建完物模型后,为设备创建一个物影子,来获得设备接入天工平台需要的MQTT连接用户名和密码,创建成功后注意保存影子的连接信息,配置信息如下:
名称:demo01
描述:选填
物模型:hygrothermoscope
硬件开发和配置
硬件连接
按下表连接树莓派和传感器、告警指示灯
DHT11电气参数:
- 电源电压:3~5.5V(典型值:5V);
- 温度量程:0~50℃,误差 ±2℃;
- 湿度量程:20~90%RH,误差 ±5%RH;
- 采样周期:大于等于1秒/次。
元器件 | 引脚 | 树莓派GPIO |
---|---|---|
DHT11 | VDD | 5V Power(pin2) |
DATA | GPIO24(pin18) | |
GND | Ground(pin14) | |
温度告警指示灯 | 正极 | GPIO23(pin16) |
负极 | Ground(pin6) | |
湿度告警指示灯 | 正极 | GPIO25(pin22) |
负极 | Ground(pin9) |
连接后的实物图:
程序编写
为了让整个程序更加便于理解和维护,我们将程序的各个模块写成独立node-red流程,每个流程完成独立的功能,node-red的启动可以参考 node-red安装和启动教程
本实践编写完成的node-red流程 下载保存 后,可直接导入自己的设备中体验,只需修改任意MQTT节点中服务端地址、用户名和密码即可,具体方法后边教程有提示。
流程模块 | 描述 |
---|---|
获取传感器数据流程 | 1s周期采集传感器数据并保存在全局变量中 |
获取配置信息流程 | 从云端拉取设备影子作为配置信息,初始化设备 |
上报温湿度数据流程 | 30s周期上报温湿度数据 |
告警触发与上报流程 | 实时监测温湿度变化,达到阈值时触发告警指示灯点亮,并上报当前设备状态 |
接收云端指令流程 | 接收云端下发的温湿度告警阈值配置、熄灭告警指示灯指令 |
获取传感器数据流程
- 莓派实时读取DHT11数据,并存储在全局变量中,后续上报、告警逻辑均读取全局变量中存储的温湿度数据
- 此处特别注意的一点,rpi-dht11节点不是node-red内置的节点,需要单独安装,具体安装方法可参考 DTH11安装方法
- 设置触发器,树莓派每1s对温湿度进行采样更新,并进行实时告警,上报程序每30s上报一次,这样就实现了数据采集和上报分离(采集和上报异步)
-
设置当前温湿度状态function节点代码
global.set('humidity',Number(msg.humidity).toFixed(2)) global.set('temperature',Number(msg.payload).toFixed(2)) return {};
获取配置信息流程
- 树莓派开机联网后,主动从云端下载配置信息,初始化温湿度告警阈值、初始化告警灯状态
-
先检测一下消息发布节点是否就绪,使用get_shadow组装payload,向$baidu/iot/shadow/demo01/get主题发布消息,请求获得设备影子,get_shadow function节点代码
var res={} var parmars={ requestId: new Date().getTime(), } res.payload=parmars return res
- 对$baidu/iot/shadow/demo01/get主题的订阅,对应node-red中的MQTT输出节点,第一次使用时添加该节点到界面内,双击配置信息,会要求先选择mqtt连接配置
- 点击服务端右侧的 编辑 按钮新建mqtt客户端,填写连接信息,服务端地址创建设备时获得的接入地址
- 切换到安全tab下,设置MQTT连接用户名和密码,用户名和密码为创建设备时获得的用户名和密码(特别提醒,下载使用本教程中提供的完整流程时,请务必将此处用户名和密码修改为自己设备的用户名密码)
- 返回页面选中刚刚新建的服务端,设置主题为$baidu/iot/shadow/demo01/get,点击完成即可完成MQTT客户端配置,此后再需要使用MQTT节点时,不需要再次配置连接信息,只需要设置相应的发布或订阅主题即可
- 订阅$baidu/iot/shadow/demo01/get/accepted主题,接收天工返回的设备影子信息,并使用初始化设备状态,function节点代码
global.set('humidity_alarm',0)
global.set('temperature_alarm',0)
global.set('humidity',0)
global.set('temperature',0)
global.set('humidity_alarm_has_reported',false)
global.set('temperature_alarm_has_reported',false)
return {};
- 可同时订阅$baidu/iot/shadow/demo01/update/rejected主题,调试过程中,如设备影子请求失败,会在此接收到消息
上报温湿度数据
- 设备初始化完成之后,我们来实现30s周期上报温湿度信息到云端
-
设置触发器,每30s触发formate函数执行一次,formate函数会从全局变量中获得当前设备记录的温湿度数值,组装设备影子上报消息,向$baidu/iot/shadow/demo01/update主题发布更新设备影子信息,formate function代码
var res={} var parmars={ "requestId": new Date().getTime(), "reported": {} } parmars.reported.randomnum=Math.random(100)*1000 parmars.reported.temperature=global.get('temperature') parmars.reported.humidity=global.get('humidity') res.payload=parmars return res;
- 进一步可以订阅$baidu/iot/shadow/demo01/update/accepted来接收影子更新的结果
告警触发与上报
- 告警是物联网场景中常见的功能,我们使用本流程实现温湿度达到阈值时,设备告警指示灯点亮,同时,设备向云端发送设备当前状态信息
- 设置两个触发器分别监测温湿度值是否达到设置的阈值,触发器以1s周期进行检测,与设备采集传感器数据的周期保持一致
- 以湿度监测为例,触发器以全局变量中的humidity(湿度)值为输入,通过h_alarm_on函数来计算当前值是否达到阈值,通过switch进行判断达到阈值即点亮告警灯,同时通过向$baidu/iot/shadow/demo01/update发布消息,更新设备影子
-
h_alarm_on代码
var res={} var turn_on=0 if(global.get('humidity')>global.get('humidity_alarm_value')){ global.set('humidity_alarm',1) if(global.get('humidity_alarm_has_reported')){ }else{ global.set('humidity_alarm_has_reported',true) turn_on=1 } } res.payload=turn_on return res;
-
formate代码
var res={} var parmars={ "requestId": new Date().getTime(), "reported": {} } parmars.reported.randomnum=Math.random(100)*1000 parmars.reported.temperature=global.get('temperature') parmars.reported.humidity=global.get('humidity') parmars.reported.temperature_alarm=global.get('temperature_alarm') parmars.reported.humidity_alarm=global.get('humidity_alarm') res.payload=parmars return res;
接收云端指令
- 前边两个流程我们实现了数据上行,接着我们编写一个流程来接收云端下发给设备的指令,实现远程控制设备
- 通过天工控制台物影子详情页或调用api接口可以更新设备影子中的‘desired’字段,达到反控设备的目的。物影子在接受到‘desired’字段更新后,会比较'reported'和‘desired’之间的差异,并将diff结果发送到主题'$baidu/iot/shadow/demo01/delta,设备通过订阅该主题即可实时获取云端下发的指令,进行相应的逻辑操作
- 云端可以下发指令设置温湿度阈值、熄灭告警指示灯,使用相应的函数判断云端指令类型进行相应的操作
-
关于设备影子的机制可参考 物影子操作 相关文档
部署和运行
经过上边的流程编写之后,我们将程序部署到树莓派中去,只需要点击页面右上角的部署,node-red会把我们编写的程序自动部署并运行 接着我们就可以通过观察控制台设备影子数据变化验证我们的成果了。
- 观察控制台设备影子数据变化,初始时像这样,设备开始上报数据了
- 简单粗暴的方式,向传感器哈气,当然是用加湿器或电吹风效果更突出,效果是这样,温湿度数值增高,报警灯亮起
远程下发指令
最后我们演示一下如何向设备下发指令,下发指令操作我们使用控制台提供的下发功能,当然你也可以通过调用天工提供的api实现,在我们的demo中设备可以响应的指令有两种,一种是控制告警指示灯熄灭,另一种远程设置告警阈值。
- 设置告警阈值,打开设备影子详情页,点击编辑按钮,设置湿度告警阈值为40
- 点击确定后,刷新影子状态,可查看到湿度告警阈值当前值已更新为40(设备接收到设置指令并设置成功后会上报更新后设备的当前值)
- 熄灭告警指示灯,首先我们通过对DHT11哈气,触发告警指示灯亮起
- 下发指令熄灭告警灯,我们将告警指示灯状态值设置为0下发给设置点击确定后,指示灯熄灭
设置数据自动存储到TSDB
打开demo01物影子详情页,切换到物详情tab,将6个属性全部设置为“上报即存储”,设置之后设备上报的所有数据将自动存储到我们设置的TSDB中
物可视大屏展示
使用物可视大屏将设备数据汇总显示,关于物可视的使用请阅读物可视相关文档,此处我们直接展示本次基于单台设备通过拖拉拽零代码实现的大屏效果,更多效果可以进一步发掘
更多控制方法
此外,你也可以发掘更多的控制方法,比如控制端通过创建MQTT连接,向更新设备影子主题发布包含desired的消息,以下原始控制指令可参考
指令下发topic
$baidu/iot/shadow/demo01/update
设置阈值
{
"requestId":"1234567890",
"desired":{
"humidity_alarm_value":12,
"temperature_alarm_value":24
}
}
消除告警
{
"requestId":"1234567890",
"desired":{
"temperature_alarm":0,
"humidity_alarm":0
}
}
完整node-red流程
复制并粘贴保存为.json文件或 点击下载,将文件导入你的node-red即可使用(一定要记得修改MQTT节点的信息)
[
{
"id": "e0b82240.b53ae",
"type": "tab",
"label": "获取环境温湿度",
"disabled": false,
"info": ""
},
{
"id": "79ed18b7.b0cba8",
"type": "tab",
"label": "获取设备影子",
"disabled": false,
"info": ""
},
{
"id": "fcc59dc.0f9396",
"type": "tab",
"label": "上报设备状态",
"disabled": false,
"info": ""
},
{
"id": "eb9cfc66.b315",
"type": "tab",
"label": "指示灯告警",
"disabled": false,
"info": ""
},
{
"id": "cc69204f.1129b",
"type": "tab",
"label": "接收云端指令",
"disabled": false,
"info": ""
},
{
"id": "876561eb.4dc06",
"type": "mqtt-broker",
"z": "",
"name": "mqtt-demo01",
"broker": "1cb210f148044b6c8ac45382ef0d9e02.mqtt.iot.gz.baidubce.com",
"port": "1883",
"clientid": "demo01",
"usetls": false,
"compatmode": true,
"keepalive": "60",
"cleansession": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"closeTopic": "",
"closeQos": "0",
"closePayload": "",
"willTopic": "",
"willQos": "0",
"willPayload": ""
},
{
"id": "aeaf02d5.9bfb",
"type": "mqtt out",
"z": "79ed18b7.b0cba8",
"name": "",
"topic": "$baidu/iot/shadow/demo01/get",
"qos": "0",
"retain": "",
"broker": "876561eb.4dc06",
"x": 670,
"y": 60,
"wires": []
},
{
"id": "1c4ebe.2fe0c143",
"type": "mqtt in",
"z": "79ed18b7.b0cba8",
"name": "",
"topic": "$baidu/iot/shadow/demo01/get/accepted",
"qos": "0",
"datatype": "json",
"broker": "876561eb.4dc06",
"x": 220,
"y": 160,
"wires": [
[
"32f0f23.b929f0e"
]
]
},
{
"id": "32f0f23.b929f0e",
"type": "function",
"z": "79ed18b7.b0cba8",
"name": "初始化设备",
"func": "\n\nglobal.set('temperature_alarm_value',msg.payload.reported.temperature_alarm_value)\n\nglobal.set('humidity_alarm_value',msg.payload.reported.humidity_alarm_value)\n\nglobal.set('humidity_alarm',0)\n\nglobal.set('temperature_alarm',0)\n\nglobal.set('humidity',0)\n\nglobal.set('temperature',0)\n\nglobal.set('humidity_alarm_has_reported',false)\n\nglobal.set('temperature_alarm_has_reported',false)\n\n\n\nreturn {};\n\n\n",
"outputs": 1,
"noerr": 0,
"x": 520,
"y": 160,
"wires": [
[
"27781181.55b2be"
]
]
},
{
"id": "27781181.55b2be",
"type": "debug",
"z": "79ed18b7.b0cba8",
"name": "获取影子成功",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 740,
"y": 160,
"wires": []
},
{
"id": "ad0d021d.af49f",
"type": "function",
"z": "79ed18b7.b0cba8",
"name": "get_shadow",
"func": "var res={}\n\nvar parmars={\n \"requestId\": new Date().getTime(),\n}\n\nres.payload=parmars\n\nreturn res;",
"outputs": 1,
"noerr": 0,
"x": 370,
"y": 60,
"wires": [
[
"aeaf02d5.9bfb"
]
]
},
{
"id": "1e5c7528.4ac8eb",
"type": "status",
"z": "79ed18b7.b0cba8",
"name": "",
"scope": [
"1c4ebe.2fe0c143"
],
"x": 140,
"y": 60,
"wires": [
[
"ad0d021d.af49f"
]
]
},
{
"id": "55874635.ff36b8",
"type": "inject",
"z": "fcc59dc.0f9396",
"name": "周期上报",
"topic": "",
"payload": "",
"payloadType": "date",
"repeat": "30",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 150,
"y": 260,
"wires": [
[
"464a70e6.efb22",
"b17d0f7c.856ed"
]
]
},
{
"id": "464a70e6.efb22",
"type": "function",
"z": "fcc59dc.0f9396",
"name": "formate",
"func": "var res={}\n\nvar parmars={\n \"requestId\": new Date().getTime(),\n \"reported\": {}\n}\nparmars.reported.randomnum=Math.random(100)*1000\n\nparmars.reported.temperature=global.get('temperature')\n\nparmars.reported.humidity=global.get('humidity')\n\n\nres.payload=parmars\n\nreturn res;",
"outputs": 1,
"noerr": 0,
"x": 380,
"y": 260,
"wires": [
[
"a4e7196e.af6578",
"66b34bbc.208864"
]
]
},
{
"id": "a4e7196e.af6578",
"type": "mqtt out",
"z": "fcc59dc.0f9396",
"name": "",
"topic": "$baidu/iot/shadow/demo01/update",
"qos": "0",
"retain": "",
"broker": "876561eb.4dc06",
"x": 720,
"y": 260,
"wires": []
},
{
"id": "bcdb86b3.317e38",
"type": "rpi-gpio out",
"z": "cc69204f.1129b",
"name": "温度告警灯",
"pin": "16",
"set": true,
"level": "0",
"freq": "",
"out": "out",
"x": 650,
"y": 200,
"wires": []
},
{
"id": "41b5ee5b.2e3fa",
"type": "mqtt out",
"z": "cc69204f.1129b",
"name": "",
"topic": "$baidu/iot/shadow/demo01/update",
"qos": "0",
"retain": "",
"broker": "876561eb.4dc06",
"x": 980,
"y": 320,
"wires": []
},
{
"id": "1b30c52e.29897b",
"type": "function",
"z": "cc69204f.1129b",
"name": "t_alarm_off",
"func": "\nvar res={}\nvar turn_on=0\n\nif(msg.payload.desired.temperature_alarm==1){\n turn_on=1\n}\nres.payload=turn_on\n\nreturn res;",
"outputs": 1,
"noerr": 0,
"x": 390,
"y": 160,
"wires": [
[
"479a6a71.773114"
]
]
},
{
"id": "8a6175a2.3e85a8",
"type": "function",
"z": "cc69204f.1129b",
"name": "h_alarm_off",
"func": "var res={}\nvar turn_on=0\n\nif(msg.payload.desired.humidity_alarm==1){\n turn_on=1\n}\n\n\nres.payload=turn_on\n\nreturn res;",
"outputs": 1,
"noerr": 0,
"x": 390,
"y": 280,
"wires": [
[
"d9c514fd.bd0d88"
]
]
},
{
"id": "4fab39be.a5d838",
"type": "rpi-gpio out",
"z": "cc69204f.1129b",
"name": "湿度告警灯",
"pin": "22",
"set": true,
"level": "0",
"freq": "",
"out": "out",
"x": 650,
"y": 280,
"wires": []
},
{
"id": "67b64145.91291",
"type": "mqtt in",
"z": "cc69204f.1129b",
"name": "",
"topic": "$baidu/iot/shadow/demo01/delta",
"qos": "0",
"datatype": "json",
"broker": "876561eb.4dc06",
"x": 150,
"y": 280,
"wires": [
[
"1b30c52e.29897b",
"8a6175a2.3e85a8",
"c2f39cb9.96667",
"4f0b2611.ff8238"
]
]
},
{
"id": "8b3c3146.b77f2",
"type": "function",
"z": "cc69204f.1129b",
"name": "t_alarm_reported",
"func": "\nvar res={}\nglobal.set('temperature_alarm',0)\nglobal.set('temperature_alarm_has_reported',false)\n\nvar parmars={\n \"requestId\": new Date().getTime(),\n \"reported\": {}\n}\nparmars.reported.randomnum=Math.random(100)*1000\n\nparmars.reported.temperature_alarm=msg.payload==1?1:0\n\n\nres.payload=parmars\n\nreturn res;",
"outputs": 1,
"noerr": 0,
"x": 670,
"y": 160,
"wires": [
[
"41b5ee5b.2e3fa",
"c207e56d.a67738"
]
]
},
{
"id": "67886b16.9d5274",
"type": "function",
"z": "cc69204f.1129b",
"name": "h_alarm_reported",
"func": "\n\nvar res={}\nglobal.set('humidity_alarm',0)\nglobal.set('humidity_alarm_has_reported',false)\nvar parmars={\n \"requestId\": new Date().getTime(),\n \"reported\": {}\n}\nparmars.reported.randomnum=Math.random(100)*1000\n\nparmars.reported.humidity_alarm=msg.payload==1?1:0\n\n\nres.payload=parmars\n\nreturn res;",
"outputs": 1,
"noerr": 0,
"x": 670,
"y": 320,
"wires": [
[
"41b5ee5b.2e3fa",
"c207e56d.a67738"
]
]
},
{
"id": "4ff05547.39024c",
"type": "function",
"z": "cc69204f.1129b",
"name": "set_alarm",
"func": "var parmars={\n \"requestId\": new Date().getTime(),\n \"reported\": {\n temperature_alarm_value:global.get('temperature_alarm_value')||100,\n humidity_alarm_value:global.get('humidity_alarm_value')||100\n }\n}\n\nif(msg.payload.desired.temperature_alarm_value){\n global.set('temperature_alarm_value',msg.payload.desired.temperature_alarm_value)\n parmars.reported.temperature_alarm_value=msg.payload.desired.temperature_alarm_value\n}\n\nif(msg.payload.desired.humidity_alarm_value ){\n global.set('humidity_alarm_value',msg.payload.desired.humidity_alarm_value) \n parmars.reported.humidity_alarm_value=msg.payload.desired.humidity_alarm_value\n}\n\n\nmsg.payload=parmars\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 640,
"y": 420,
"wires": [
[
"41b5ee5b.2e3fa",
"c207e56d.a67738"
]
]
},
{
"id": "d9c514fd.bd0d88",
"type": "switch",
"z": "cc69204f.1129b",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "0",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 410,
"y": 320,
"wires": [
[
"67886b16.9d5274",
"4fab39be.a5d838"
]
]
},
{
"id": "479a6a71.773114",
"type": "switch",
"z": "cc69204f.1129b",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "0",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 410,
"y": 200,
"wires": [
[
"8b3c3146.b77f2",
"bcdb86b3.317e38"
]
]
},
{
"id": "c2f39cb9.96667",
"type": "function",
"z": "cc69204f.1129b",
"name": "if_set_alarm",
"func": "\nvar parmars=msg.payload.desired.hasOwnProperty(\"temperature_alarm_value\")||msg.payload.desired.hasOwnProperty(\"humidity_alarm_value\")\n\nmsg.to_set=parmars\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 390,
"y": 380,
"wires": [
[
"bdaa5c71.ca261"
]
]
},
{
"id": "bdaa5c71.ca261",
"type": "switch",
"z": "cc69204f.1129b",
"name": "",
"property": "to_set",
"propertyType": "msg",
"rules": [
{
"t": "true"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 410,
"y": 420,
"wires": [
[
"4ff05547.39024c"
]
]
},
{
"id": "8b4e4b3d.6d7ae8",
"type": "mqtt in",
"z": "fcc59dc.0f9396",
"name": "",
"topic": "$baidu/iot/shadow/demo01/update/accepted",
"qos": "0",
"datatype": "json",
"broker": "876561eb.4dc06",
"x": 230,
"y": 400,
"wires": [
[
"66b34bbc.208864"
]
]
},
{
"id": "66b34bbc.208864",
"type": "debug",
"z": "fcc59dc.0f9396",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 630,
"y": 400,
"wires": []
},
{
"id": "ca8cd639.9a4258",
"type": "debug",
"z": "79ed18b7.b0cba8",
"name": "获取影子失败",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 540,
"y": 260,
"wires": []
},
{
"id": "a9da906e.29bde",
"type": "mqtt in",
"z": "79ed18b7.b0cba8",
"name": "",
"topic": "$baidu/iot/shadow/demo01/update/rejected",
"qos": "0",
"datatype": "json",
"broker": "876561eb.4dc06",
"x": 230,
"y": 260,
"wires": [
[
"ca8cd639.9a4258"
]
]
},
{
"id": "2981152c.63017a",
"type": "rpi-dht22",
"z": "e0b82240.b53ae",
"name": "读DHT11数据",
"topic": "rpi-dht11",
"dht": "11",
"pintype": "0",
"pin": "18",
"x": 400,
"y": 240,
"wires": [
[
"a2c9546.eeb9ca8",
"b835ff81.33c0c"
]
]
},
{
"id": "a2c9546.eeb9ca8",
"type": "function",
"z": "e0b82240.b53ae",
"name": "设置设备当前温湿度状态",
"func": "\nglobal.set('humidity',Number(msg.humidity).toFixed(2))\nglobal.set('temperature',Number(msg.payload).toFixed(2))\n\nreturn {};",
"outputs": 1,
"noerr": 0,
"x": 630,
"y": 240,
"wires": [
[
"c3c0dca4.3972d"
]
]
},
{
"id": "6662a21c.a9726c",
"type": "inject",
"z": "e0b82240.b53ae",
"name": "周期触发器",
"topic": "",
"payload": "",
"payloadType": "date",
"repeat": "1",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 210,
"y": 240,
"wires": [
[
"2981152c.63017a"
]
]
},
{
"id": "cb542070.5ebac",
"type": "rpi-gpio out",
"z": "eb9cfc66.b315",
"name": "温度告警灯",
"pin": "16",
"set": true,
"level": "0",
"freq": "",
"out": "out",
"x": 790,
"y": 420,
"wires": []
},
{
"id": "aecdb85d.c5d758",
"type": "rpi-gpio out",
"z": "eb9cfc66.b315",
"name": "湿度告警灯",
"pin": "22",
"set": true,
"level": "0",
"freq": "",
"out": "out",
"x": 790,
"y": 240,
"wires": []
},
{
"id": "3da13ab1.337fb6",
"type": "inject",
"z": "eb9cfc66.b315",
"name": "",
"topic": "",
"payload": "humidity",
"payloadType": "global",
"repeat": "1",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 230,
"y": 240,
"wires": [
[
"85ca2d2.6cbc7d"
]
]
},
{
"id": "69c07bf5.efa0c4",
"type": "inject",
"z": "eb9cfc66.b315",
"name": "",
"topic": "",
"payload": "temperature",
"payloadType": "global",
"repeat": "1",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 240,
"y": 420,
"wires": [
[
"72da2f99.47e7b"
]
]
},
{
"id": "65a20d4f.e76724",
"type": "mqtt out",
"z": "eb9cfc66.b315",
"name": "",
"topic": "$baidu/iot/shadow/demo01/update",
"qos": "0",
"retain": "",
"broker": "876561eb.4dc06",
"x": 1060,
"y": 360,
"wires": []
},
{
"id": "72da2f99.47e7b",
"type": "function",
"z": "eb9cfc66.b315",
"name": "t_alarm_on",
"func": "var res={}\nvar turn_on=0\n\n\n\nif(global.get('temperature')>global.get('temperature_alarm_value')){\n\n if(global.get('temperature_alarm_has_reported')){\n\n}else{\n global.set('temperature_alarm_has_reported',true) \n turn_on=1\n}\n}\nres.payload=turn_on\n\nreturn res;",
"outputs": 1,
"noerr": 0,
"x": 450,
"y": 420,
"wires": [
[
"7066ca16.508d64"
]
]
},
{
"id": "85ca2d2.6cbc7d",
"type": "function",
"z": "eb9cfc66.b315",
"name": "h_alarm_on",
"func": "\nvar res={}\nvar turn_on=0\nif(global.get('humidity')>global.get('humidity_alarm_value')){\n global.set('humidity_alarm',1)\n if(global.get('humidity_alarm_has_reported')){\n \n }else{\n global.set('humidity_alarm_has_reported',true)\n turn_on=1\n }\n}\nres.payload=turn_on\nreturn res;",
"outputs": 1,
"noerr": 0,
"x": 450,
"y": 240,
"wires": [
[
"4dd08a6c.87ecc4"
]
]
},
{
"id": "7066ca16.508d64",
"type": "switch",
"z": "eb9cfc66.b315",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "1",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 610,
"y": 420,
"wires": [
[
"cb542070.5ebac",
"c83ff371.eaa0e"
]
]
},
{
"id": "4dd08a6c.87ecc4",
"type": "switch",
"z": "eb9cfc66.b315",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "1",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 610,
"y": 240,
"wires": [
[
"aecdb85d.c5d758",
"c83ff371.eaa0e"
]
]
},
{
"id": "c3c0dca4.3972d",
"type": "debug",
"z": "e0b82240.b53ae",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 850,
"y": 240,
"wires": []
},
{
"id": "c83ff371.eaa0e",
"type": "function",
"z": "eb9cfc66.b315",
"name": "formate",
"func": "var res={}\n\nvar parmars={\n \"requestId\": new Date().getTime(),\n \"reported\": {}\n}\nparmars.reported.randomnum=Math.random(100)*1000\n\nparmars.reported.temperature=global.get('temperature')\n\nparmars.reported.humidity=global.get('humidity')\n\nparmars.reported.temperature_alarm=global.get('temperature_alarm')\n\nparmars.reported.humidity_alarm=global.get('humidity_alarm')\n\n\nres.payload=parmars\n\nreturn res;",
"outputs": 1,
"noerr": 0,
"x": 780,
"y": 340,
"wires": [
[
"65a20d4f.e76724",
"c3d36c20.b83a6"
]
]
},
{
"id": "c3d36c20.b83a6",
"type": "debug",
"z": "eb9cfc66.b315",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"x": 990,
"y": 280,
"wires": []
},
{
"id": "4f0b2611.ff8238",
"type": "debug",
"z": "cc69204f.1129b",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"x": 390,
"y": 520,
"wires": []
},
{
"id": "c207e56d.a67738",
"type": "debug",
"z": "cc69204f.1129b",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"x": 930,
"y": 220,
"wires": []
},
{
"id": "b835ff81.33c0c",
"type": "change",
"z": "e0b82240.b53ae",
"name": "",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "100",
"tot": "jsonata"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 630,
"y": 400,
"wires": [
[
"a490710e.a86f7"
]
]
},
{
"id": "a490710e.a86f7",
"type": "debug",
"z": "e0b82240.b53ae",
"name": "测试change",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 890,
"y": 400,
"wires": []
},
{
"id": "b17d0f7c.856ed",
"type": "change",
"z": "fcc59dc.0f9396",
"name": "组装数据",
"rules": [
{
"t": "set",
"p": "payload.requestId",
"pt": "msg",
"to": "payload",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 380,
"y": 140,
"wires": [
[
"791b173b.086ba8"
]
]
},
{
"id": "791b173b.086ba8",
"type": "debug",
"z": "fcc59dc.0f9396",
"name": "组装数据结果",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"x": 680,
"y": 140,
"wires": []
}
]