逻辑
目前看来有些逻辑在thingsboard(tb)上不容易实现,所以放到设备端处理
设备端上报的报文
1 2 3 |
{"distance": 89.06, "onceTime": 0, "playTime": 0, "restTime": 36056} 距离,单次时长,总时长,休息时长 |
设备上报这4个数据给tb,返回rpc(D5、D6、D7引脚的状态)指令
tb规则链还未编写,回调函数中休息时间的处理还有问题
设备端代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
#include <ESP8266WiFi.h> #include <PubSubClient.h> #include <ArduinoJson.h> <em>// 设置wifi信息</em> const char* ssid = "****"; const char* password = "********"; const char* mqttServer = "www.weishadian.com"; <em>// 建立wifi和mqtt对象</em> WiFiClient wifiClient; PubSubClient mqttClient(wifiClient); const char* client_ID = "any20211128145527"; <em>// id可以任意</em> const char* mqttUserName = "*********"; <em>// 设备令牌,token</em> const char* mqttPassword = ""; <em>// 密码为空</em> char dataTemplate[] = "{\"distance\": %.2f, \"onceTime\": %d, \"playTime\": %d, \"restTime\": %d}"; <em>// 简单信息模板</em> char attrData[] = "{\"deviceName\": \"boyPC\"}"; <em>// 简单信息模板</em> char postData[100]; <em>// 报文</em> <em>// 主题</em> char topic[] = "v1/devices/me/telemetry"; <em>// 发布遥测数据的主题</em> <em>//char attrTopic[] = "v1/devices/me/attributes"; // 发布属性的主题</em> <em>//char attrResponse[] = "v1/devices/me/attributes/response/+"; // 发布属性需订阅的主题</em> char rpcTopic[] = "v1/devices/me/rpc/request/+"; <em>// rpc主题</em> <em>// 超声波引脚</em> #define trigPin D1 #define echoPin D2 <em>// rgb灯引脚</em> #define r D5 #define g D6 #define b D7 <em>// 声明时间和距离的变量</em> float duration; float distance; float lastDistance = 0; <em>// 记录时间</em> int beginTime = 0; <em>// 开始时间</em> int restBegin = 0; <em>// 开始休息</em> int onceTime = 0; <em>// 单次时长</em> int playTime = 0; <em>// 总时长</em> int restTime = 0; <em>// 休息时长</em> <em>// 状态</em> int r_val = 0; int g_val = 0; int b_val = 0; DynamicJsonDocument doc(200); <em>// 服务器报文存储</em> void setup(){ pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(r, OUTPUT); pinMode(g, OUTPUT); pinMode(b, OUTPUT); Serial.begin(9600); wifiAndMqtt(); } void loop(){ <em>// 检查MQTT连接状态</em> if (!mqttClient.connected()) { WiFi.disconnect(); <em>// 断开wifi</em> Serial.println("掉线啦!5秒后尝试重新连接..."); delay(5000); wifiAndMqtt(); Serial.println("重新连接成功!"); } <em>// 处理信息以及心跳</em> mqttClient.loop(); ranging(); <em>// 测距</em> if ((lastDistance > 50 && distance < 50) || (lastDistance < 50 && distance > 50)){ <em>// 位置改变</em> tbPublish(); <em>// 上报数据</em> } if (g_val == 1024){ onceTime = millis() - beginTime; if ((onceTime > 3600000) || (playTime+onceTime > 14400000)){ <em>// 单次1或总长4超时</em> tbPublish(); <em>// 上报数据</em> } }else{ restTime = millis() - restBegin; if (restTime > 900000){ <em>// 休息15分钟</em> tbPublish(); <em>// 上报数据</em> } } delay(1000); } <em>// 超声波测距函数</em> void ranging(){ <em>// 这里不需要返回值,因为使用的都是全局变量</em> <em>// 清除trig的任务,防止trig处于高电平状态</em> digitalWrite(trigPin, LOW); delayMicroseconds(2); <em>// 拉高trig发射一个持续10微秒的超声波</em> digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); <em>// 读取echo的检测HIGH脉冲信号,返回持续时间,单位是微秒</em> duration = pulseIn(echoPin, HIGH); <em>// 计算距离,设置声速为0.034262 cm/s</em> distance= duration*0.034262/2.0; } <em>// 收到信息后的回调函数</em> void receiveCallback(char* topic, byte* payload, unsigned int length) { Serial.print("报文 ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(""); Serial.print("报文长度(Bytes) "); Serial.println(length); <em>// 反序列化报文</em> deserializeJson(doc, payload); r_val = doc["params"]["D5"].as<int>(); g_val = doc["params"]["D6"].as<int>(); b_val = doc["params"]["D7"].as<int>(); if (g_val == 1024){ beginTime = millis(); <em>// 开始计时</em> restTime = 0; <em>// 清空休息时间</em> restBegin = 0; <em>// 清空开始休息计时</em> }else{ playTime = playTime + onceTime; <em>// 总时长</em> restBegin = millis(); <em>// 开始休息计时</em> onceTime = 0; <em>// 清空单次时长</em> } analogWrite(r, r_val); analogWrite(g, g_val); analogWrite(b, b_val); <em>// // 截取request主题的id,添加给response主题</em> <em>// char reTopic[50] = "v1/devices/me/rpc/response/"; // RPC应答主题</em> <em>// for (int i; i < strlen(topic); i++){</em> <em>// if (i >= 26){</em> <em>// reTopic[i+1] = topic[i]; // RPC应答主题后面加上id</em> <em>// } </em> <em>// }</em> <em>// ledStatus = !ledStatus;</em> <em>// snprintf(postStatus, 50, statusTemplate, ledStatus);</em> <em>// // 发布应答报文,确认连接 </em> <em>// mqttClient.publish(reTopic, (uint8_t *)postStatus, strlen(postStatus));</em> <em>// // 发布属性报文,更新led indicator状态</em> <em>// mqttClient.publish(topic3, (uint8_t *)postStatus, strlen(postStatus));</em> <em>//</em> <em>// digitalWrite(LED_BUILTIN, !ledStatus); // 改变LED状态</em> } <em>// wifi和mqtt连接</em> void wifiAndMqtt(){ <em>//设置为无线终端模式</em> WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); <em>// 连接WiFi</em> <em>//等待WiFi连接,成功连接后输出成功信息</em> while (WiFi.status() != WL_CONNECTED) { delay(1000); } <em>// 设置MQTT服务器和端口号</em> mqttClient.setServer(mqttServer, 1883); <em>// 明文模式</em> mqttClient.setCallback(receiveCallback); <em>// 收到报文的回调函数</em> mqttClient.connect(client_ID, mqttUserName, mqttPassword); <em>// 连接mqtt服务器</em> while (!mqttClient.connected()){ delay(1000); } <em>// mqttClient.subscribe(attrResponse, 0); // 订阅主题</em> mqttClient.subscribe(rpcTopic, 0); <em>// 订阅主题</em> <em>// mqttClient.publish(attrTopic, (uint8_t *)attrData, strlen(attrData)); // 发送属性报文</em> } <em>// 发送报文</em> void tbPublish(){ lastDistance = distance; snprintf(postData, 100, dataTemplate, distance, onceTime, playTime, restTime); <em>// 格式化报文</em> Serial.println(postData); Serial.print("上报数据!"); Serial.println(distance); mqttClient.publish(topic, (uint8_t *)postData, strlen(postData)); } |
近期评论