Files
FastBee/sdk/Arduino/FastBeeArduino/User.cpp
kerwincui 5539c1b6af 更新
2024-03-17 14:59:23 +08:00

256 lines
8.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*********************************************************************
* function 用户自定义功能
* board: esp8266 core for arduino v3.0.2
* library PubSubClient2.8.0 & ArduinoJson6.19.1 & OneButton2.0.4
* source: https://gitee.com/kerwincui/wumei-smart
* copyright: FastBee and kerwincui all rights reserved.
********************************************************************/
#include "User.h"
#define BUTTON 14 // 按键引脚
#define RELAY 12 // 继电器引脚
OneButton button;
// 按钮单击事件
static void buttonClick();
// 按钮双击事件
static void buttonDoubleClick();
// 按钮长按事件
static void buttonLongPress();
// 初始化用户配置
void initUser() {
// 初始化按键为低电平,并添加单击、双击、长按事件
button = OneButton(BUTTON, true, true);
button.attachClick(buttonClick);
button.attachDoubleClick(buttonDoubleClick);
button.attachLongPressStart(buttonLongPress);
}
// Mqtt回调
void mqttCallback(char *topic, byte *payload, unsigned int length) {
blink();
printMsg("接收数据:");
String data = "";
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
data += (char)payload[i];
}
if (strcmp(topic, (prefix + sOtaTopic).c_str()) == 0) {
printMsg("订阅到设备升级指令...");
StaticJsonDocument<256> doc;
DeserializationError error = deserializeJson(doc, payload);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
String newVersion = doc["version"];
String downloadUrl = doc["downloadUrl"];
printMsg("固件版本:" + newVersion);
printMsg("下载地址:" + downloadUrl);
} else if (strcmp(topic, (prefix + sInfoTopic).c_str()) == 0) {
printMsg("订阅到设备信息...");
// 发布设备信息
publishInfo();
} else if (strcmp(topic, (prefix + sNtpTopic).c_str()) == 0) {
printMsg("订阅到NTP时间...");
StaticJsonDocument<256> doc;
DeserializationError error = deserializeJson(doc, payload);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
// 计算设备当前时间:(${serverRecvTime} + ${serverSendTime} + ${deviceRecvTime} - ${deviceSendTime}) / 2
float deviceSendTime = doc["deviceSendTime"];
float serverSendTime = doc["serverSendTime"];
float serverRecvTime = doc["serverRecvTime"];
float deviceRecvTime = millis();
float now = (serverSendTime + serverRecvTime + deviceRecvTime - deviceSendTime) / 2;
printMsg("当前时间:" + String(now, 0));
} else if (strcmp(topic, (prefix + sPropertyTopic).c_str()) == 0 || strcmp(topic, (prefix + sPropertyOnline).c_str()) == 0) {
printMsg("订阅到属性指令...");
processProperty(data);
} else if (strcmp(topic, (prefix + sFunctionTopic).c_str()) == 0 || strcmp(topic, (prefix + sFunctionOnline).c_str()) == 0) {
printMsg("订阅到功能指令...");
processFunction(data);
} else if (strcmp(topic, (prefix + sMonitorTopic).c_str()) == 0) {
printMsg("订阅到实时监测指令...");
StaticJsonDocument<128> doc;
DeserializationError error = deserializeJson(doc, payload);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
monitorCount = doc["count"];
monitorInterval = doc["interval"];
}
}
// 随机生成监测值
String randomPropertyData() {
// 匹配云端定义的监测数据,随机数代替监测值
float randFloat = 0;
int randInt = 0;
StaticJsonDocument<1024> doc;
JsonObject objTmeperature = doc.createNestedObject();
objTmeperature["id"] = "light_current";
randFloat = random(1000, 3000);
objTmeperature["value"] = (String)(randFloat / 100);
objTmeperature["remark"] = (String)millis();
JsonObject objHumidity = doc.createNestedObject();
objHumidity["id"] = "humidity";
randFloat = random(3000, 6000);
objHumidity["value"] = (String)(randFloat / 100);
objHumidity["remark"] = (String)millis();
JsonObject objCo2 = doc.createNestedObject();
objCo2["id"] = "co2";
randInt = random(400, 1000);
objCo2["value"] = (String)(randInt);
objCo2["remark"] = (String)millis();
JsonObject objBrightness = doc.createNestedObject();
objBrightness["id"] = "brightness";
randInt = random(1000, 10000);
objBrightness["value"] = (String)(randInt);
objBrightness["remark"] = (String)millis();
printMsg("模拟监测数据值:");
serializeJson(doc, Serial);
String output;
serializeJson(doc, output);
return output;
}
// 物模型-属性处理
void processProperty(String msg) {
StaticJsonDocument<1024> doc;
DeserializationError error = deserializeJson(doc, msg);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
for (JsonObject object : doc.as<JsonArray>()) {
// 匹配云端定义的属性(不包含属性中的监测数据)
const char *id = object["id"];
const char *value = object["value"];
printMsg((String)id + "" + (String)value);
}
// 最后发布属性,服务端订阅存储(重要)
publishProperty(msg);
}
// 物模型-功能处理
void processFunction(String msg) {
StaticJsonDocument<1024> doc;
DeserializationError error = deserializeJson(doc, msg);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
for (JsonObject object : doc.as<JsonArray>()) {
// 匹配云端定义的功能
const char *id = object["id"];
const char *value = object["value"];
if (strcmp(id, "light_switch") == 0) {
printMsg("开关 switch" + (String)value);
if (strcmp(value, "1") == 0) {
// 打开继电器
relayStatus(true);
} else if (strcmp(value, "0") == 0) {
// 关闭继电器
relayStatus(false);
}
} else if (strcmp(id, "gear") == 0) {
printMsg("档位 gear" + (String)value);
} else if (strcmp(id, "light_color") == 0) {
printMsg("灯光颜色 light_color" + (String)value);
} else if (strcmp(id, "message") == 0) {
printMsg("屏显消息 message" + (String)value);
} else if (strcmp(id, "report_monitor") == 0) {
int number = atoi(value);
number > 10 ? number = 10 : number;
for (int i = 0; i < number; i++) {
Serial.println(number);
String msg = randomPropertyData();
printMsg("订阅到上报监测数据指令,上报数据:");
printMsg(msg);
publishProperty(msg);
delay(1000);
}
}
}
// 最后发布功能,服务端订阅存储(重要)
publishFunction(msg);
}
// 物模型-事件上传
void processEvent() {
// 匹配云端的事件
StaticJsonDocument<512> doc;
JsonObject objTmeperature = doc.createNestedObject();
objTmeperature["id"] = "height_temperature";
objTmeperature["value"] = "40";
objTmeperature["remark"] = "温度过高警告";
JsonObject objException = doc.createNestedObject();
objException["id"] = "exception";
objException["value"] = "异常消息消息内容XXXXXXXX";
objException["remark"] = "设备发生错误";
printMsg("发布事件:");
serializeJson(doc, Serial);
String output;
serializeJson(doc, output);
// 最后发布功能,服务端订阅存储(重要)
publishEvent(output);
}
//打开继电器A
void relayStatus(bool status) {
pinMode(RELAY, OUTPUT);
if (status) {
digitalWrite(RELAY, HIGH);
} else {
digitalWrite(RELAY, LOW);
}
}
// 按钮单击事件
static void buttonClick() {
printMsg("检测到按键单击,打开继电器");
relayStatus(true);
// 匹配云端定义的开关,格式如:[{"id":"switch","value":"1"}]
String msg = "[{\"id\":\"switch\",\"value\":\"1\"}]";
publishProperty(msg);
}
// 按钮双击事件
static void buttonDoubleClick() {
printMsg("检测到按键双击,关闭继电器");
relayStatus(false);
// 匹配云端定义的开关,格式如:[{"id":"switch","value":"0"}]
String msg = "[{\"id\":\"switch\",\"value\":\"0\"}]";
publishProperty(msg);
}
// 按钮长按事件,进入配网模式
static void buttonLongPress() {
printMsg("检测到按键长按");
if (isApMode) {
printMsg("设备重启...");
ESP.restart();
} else {
printMsg("开始AP配网");
startApConfig();
}
}