mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-17 16:36:03 +08:00
固件优化
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*********************************************************************
|
||||
* function: 程序入口
|
||||
* function: 设备AP配网
|
||||
* 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
|
||||
@@ -65,9 +65,9 @@ void handleConfig()
|
||||
if (server.hasArg("SSID") && server.hasArg("password") && server.hasArg("userId"))
|
||||
{
|
||||
// 分配空间
|
||||
wifiSsid=(char *)malloc(32*sizeof(char));
|
||||
wifiPwd=(char *)malloc(64*sizeof(char));
|
||||
userId=(char *)malloc(16*sizeof(char));
|
||||
wifiSsid = (char *)malloc(32 * sizeof(char));
|
||||
wifiPwd = (char *)malloc(64 * sizeof(char));
|
||||
userId = (char *)malloc(16 * sizeof(char));
|
||||
strcpy(config.stassid, server.arg("SSID").c_str());
|
||||
strcpy(wifiSsid, server.arg("SSID").c_str());
|
||||
strcpy(config.stapsw, server.arg("password").c_str());
|
||||
@@ -88,14 +88,14 @@ void handleConfig()
|
||||
// 可选字段
|
||||
if (server.hasArg("deviceNum"))
|
||||
{
|
||||
deviceNum=(char *)malloc(32*sizeof(char));
|
||||
deviceNum = (char *)malloc(32 * sizeof(char));
|
||||
strcpy(config.deviceNum, server.arg("deviceNum").c_str());
|
||||
strcpy(deviceNum, server.arg("deviceNum").c_str());
|
||||
printMsg("收到设备编号:" + server.arg("deviceNum"));
|
||||
}
|
||||
if (server.hasArg("authCode"))
|
||||
{
|
||||
authCode=(char *)malloc(32*sizeof(char));
|
||||
authCode = (char *)malloc(32 * sizeof(char));
|
||||
strcpy(config.authCode, server.arg("authCode").c_str());
|
||||
strcpy(authCode, server.arg("authCode").c_str());
|
||||
printMsg("收到产品授权码:" + server.arg("authCode"));
|
||||
@@ -105,7 +105,8 @@ void handleConfig()
|
||||
printMsg("收到补充信息:" + server.arg("extra"));
|
||||
}
|
||||
server.send(200, "text/plain;charset=utf-8", "设备已更新WIFI配置,开始连接WIFI...");
|
||||
|
||||
// 统一设置Mqtt消息主题前缀
|
||||
prefix = "/" + (String)productId + "/" + (String)deviceNum;
|
||||
// 存储配置
|
||||
saveConfig(config);
|
||||
// 连接Wifi
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************************
|
||||
* function: 程序入口
|
||||
* function: 设备AP配网
|
||||
* 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
|
||||
@@ -9,7 +9,7 @@
|
||||
#ifndef _APCONFIG_H
|
||||
#define _APCONFIG_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Config.h"
|
||||
#include <ESP8266WebServer.h>
|
||||
|
||||
extern ESP8266WebServer server;
|
||||
@@ -18,7 +18,7 @@ extern ESP8266WebServer server;
|
||||
void startApConfig();
|
||||
// 启动Web服务
|
||||
void startWebServer();
|
||||
// 配网处理接口
|
||||
// 配网接口
|
||||
void handleConfig();
|
||||
// 检测设备接口
|
||||
void handleStatus();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************************
|
||||
* function: 程序入口
|
||||
* 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
|
||||
@@ -25,21 +25,13 @@ void connectMqtt()
|
||||
String aesPassword = generationAESPwd();
|
||||
// 连接 设备mqtt客户端Id格式为:认证类型(E=加密、S=简单) & 设备编号 & 产品ID & 用户ID
|
||||
String clientId = "E&" + (String)deviceNum + "&" + (String)productId + "&" + (String)userId;
|
||||
printMsg("客户端ID:"+clientId);
|
||||
printMsg("客户端ID:" + clientId);
|
||||
bool connectResult = mqttClient.connect(clientId.c_str(), mqttUserName, aesPassword.c_str());
|
||||
if (connectResult)
|
||||
{
|
||||
printMsg("连接Mqtt成功");
|
||||
// 订阅(OTA、NTP、属性、功能、实时监测、信息)
|
||||
mqttClient.subscribe(sInfoTopic.c_str(), 1);
|
||||
mqttClient.subscribe(sOtaTopic.c_str(), 1);
|
||||
mqttClient.subscribe(sNtpTopic.c_str(), 1);
|
||||
mqttClient.subscribe(sPropertyTopic.c_str(), 1);
|
||||
mqttClient.subscribe(sFunctionTopic.c_str(), 1);
|
||||
mqttClient.subscribe(sPropertyOnline.c_str(), 1);
|
||||
mqttClient.subscribe(sFunctionOnline.c_str(), 1);
|
||||
mqttClient.subscribe(sMonitorTopic.c_str(), 1);
|
||||
printMsg("订阅主题完成");
|
||||
// 订阅系统主题
|
||||
subscribeTopic();
|
||||
// 发布设备信息,设备上电都需要发布一次
|
||||
publishInfo();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************************
|
||||
* function: 程序入口
|
||||
* 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
|
||||
@@ -9,7 +9,8 @@
|
||||
#ifndef _AUTH_H
|
||||
#define _AUTH_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Config.h"
|
||||
#include "User.h"
|
||||
#include "Mqtt.h"
|
||||
#include <Ethernet.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
@@ -21,8 +22,8 @@ String generationAESPwd();
|
||||
// 获取时间
|
||||
String getTime();
|
||||
// AES加密
|
||||
String encrypt(String plain_data,char *wumei_key,char *wumei_iv);
|
||||
String encrypt(String plain_data, char *wumei_key, char *wumei_iv);
|
||||
// AES解密
|
||||
String decrypt(String encoded_data_str,char *wumei_key,char *wumei_iv);
|
||||
String decrypt(String encoded_data_str, char *wumei_key, char *wumei_iv);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
/*********************************************************************
|
||||
* function: Base64编码和解码
|
||||
* 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: Copyright (c) 2013 Adam Rudd.
|
||||
********************************************************************/
|
||||
|
||||
#include "Base64.h"
|
||||
|
||||
#if (defined(__AVR__))
|
||||
@@ -11,22 +19,26 @@ const char PROGMEM b64_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789+/";
|
||||
|
||||
/* 'Private' declarations */
|
||||
inline void a3_to_a4(unsigned char * a4, unsigned char * a3);
|
||||
inline void a4_to_a3(unsigned char * a3, unsigned char * a4);
|
||||
inline void a3_to_a4(unsigned char *a4, unsigned char *a3);
|
||||
inline void a4_to_a3(unsigned char *a3, unsigned char *a4);
|
||||
inline unsigned char b64_lookup(char c);
|
||||
|
||||
int base64_encode(char *output, char *input, int inputLen) {
|
||||
int base64_encode(char *output, char *input, int inputLen)
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
int encLen = 0;
|
||||
unsigned char a3[3];
|
||||
unsigned char a4[4];
|
||||
|
||||
while(inputLen--) {
|
||||
while (inputLen--)
|
||||
{
|
||||
a3[i++] = *(input++);
|
||||
if(i == 3) {
|
||||
if (i == 3)
|
||||
{
|
||||
a3_to_a4(a4, a3);
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
output[encLen++] = pgm_read_byte(&b64_alphabet[a4[i]]);
|
||||
}
|
||||
|
||||
@@ -34,18 +46,22 @@ int base64_encode(char *output, char *input, int inputLen) {
|
||||
}
|
||||
}
|
||||
|
||||
if(i) {
|
||||
for(j = i; j < 3; j++) {
|
||||
if (i)
|
||||
{
|
||||
for (j = i; j < 3; j++)
|
||||
{
|
||||
a3[j] = '\0';
|
||||
}
|
||||
|
||||
a3_to_a4(a4, a3);
|
||||
|
||||
for(j = 0; j < i + 1; j++) {
|
||||
for (j = 0; j < i + 1; j++)
|
||||
{
|
||||
output[encLen++] = pgm_read_byte(&b64_alphabet[a4[j]]);
|
||||
}
|
||||
|
||||
while((i++ < 3)) {
|
||||
while ((i++ < 3))
|
||||
{
|
||||
output[encLen++] = '=';
|
||||
}
|
||||
}
|
||||
@@ -53,45 +69,54 @@ int base64_encode(char *output, char *input, int inputLen) {
|
||||
return encLen;
|
||||
}
|
||||
|
||||
int base64_decode(char * output, char * input, int inputLen) {
|
||||
int base64_decode(char *output, char *input, int inputLen)
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
int decLen = 0;
|
||||
unsigned char a3[3];
|
||||
unsigned char a4[4];
|
||||
|
||||
|
||||
while (inputLen--) {
|
||||
if(*input == '=') {
|
||||
while (inputLen--)
|
||||
{
|
||||
if (*input == '=')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
a4[i++] = *(input++);
|
||||
if (i == 4) {
|
||||
for (i = 0; i <4; i++) {
|
||||
if (i == 4)
|
||||
{
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
a4[i] = b64_lookup(a4[i]);
|
||||
}
|
||||
|
||||
a4_to_a3(a3,a4);
|
||||
a4_to_a3(a3, a4);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
output[decLen++] = a3[i];
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i) {
|
||||
for (j = i; j < 4; j++) {
|
||||
if (i)
|
||||
{
|
||||
for (j = i; j < 4; j++)
|
||||
{
|
||||
a4[j] = '\0';
|
||||
}
|
||||
|
||||
for (j = 0; j <4; j++) {
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
a4[j] = b64_lookup(a4[j]);
|
||||
}
|
||||
|
||||
a4_to_a3(a3,a4);
|
||||
a4_to_a3(a3, a4);
|
||||
|
||||
for (j = 0; j < i - 1; j++) {
|
||||
for (j = 0; j < i - 1; j++)
|
||||
{
|
||||
output[decLen++] = a3[j];
|
||||
}
|
||||
}
|
||||
@@ -99,39 +124,50 @@ int base64_decode(char * output, char * input, int inputLen) {
|
||||
return decLen;
|
||||
}
|
||||
|
||||
int base64_enc_len(int plainLen) {
|
||||
int base64_enc_len(int plainLen)
|
||||
{
|
||||
int n = plainLen;
|
||||
return (n + 2 - ((n + 2) % 3)) / 3 * 4;
|
||||
}
|
||||
|
||||
int base64_dec_len(char * input, int inputLen) {
|
||||
int base64_dec_len(char *input, int inputLen)
|
||||
{
|
||||
int i = 0;
|
||||
int numEq = 0;
|
||||
for(i = inputLen - 1; input[i] == '='; i--) {
|
||||
for (i = inputLen - 1; input[i] == '='; i--)
|
||||
{
|
||||
numEq++;
|
||||
}
|
||||
|
||||
return ((6 * inputLen) / 8) - numEq;
|
||||
}
|
||||
|
||||
inline void a3_to_a4(unsigned char * a4, unsigned char * a3) {
|
||||
inline void a3_to_a4(unsigned char *a4, unsigned char *a3)
|
||||
{
|
||||
a4[0] = (a3[0] & 0xfc) >> 2;
|
||||
a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
|
||||
a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
|
||||
a4[3] = (a3[2] & 0x3f);
|
||||
}
|
||||
|
||||
inline void a4_to_a3(unsigned char * a3, unsigned char * a4) {
|
||||
inline void a4_to_a3(unsigned char *a3, unsigned char *a4)
|
||||
{
|
||||
a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);
|
||||
a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2);
|
||||
a3[2] = ((a4[2] & 0x3) << 6) + a4[3];
|
||||
}
|
||||
|
||||
inline unsigned char b64_lookup(char c) {
|
||||
if(c >='A' && c <='Z') return c - 'A';
|
||||
if(c >='a' && c <='z') return c - 71;
|
||||
if(c >='0' && c <='9') return c + 4;
|
||||
if(c == '+') return 62;
|
||||
if(c == '/') return 63;
|
||||
inline unsigned char b64_lookup(char c)
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return c - 'A';
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return c - 71;
|
||||
if (c >= '0' && c <= '9')
|
||||
return c + 4;
|
||||
if (c == '+')
|
||||
return 62;
|
||||
if (c == '/')
|
||||
return 63;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Adam Rudd.
|
||||
* See LICENSE for more information
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
* function: Base64编码和解码
|
||||
* 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: Copyright (c) 2013 Adam Rudd.
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _BASE64_H
|
||||
#define _BASE64_H
|
||||
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
/*********************************************************************
|
||||
* function: 程序入口
|
||||
* 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: wumei-smart and kerwincui all rights reserved.
|
||||
********************************************************************/
|
||||
|
||||
#include "Common.h"
|
||||
#define BUTTON 14 // 按键引脚
|
||||
#define LED 15 // LED灯引脚
|
||||
#include "Config.h"
|
||||
#define LED 15 // LED指示灯引脚
|
||||
|
||||
WiFiClient wifiClient;
|
||||
PubSubClient mqttClient;
|
||||
OneButton button;
|
||||
// 按钮单击事件
|
||||
static void buttonClick();
|
||||
// 按钮双击事件
|
||||
static void buttonDoubleClick();
|
||||
// 按钮长按事件
|
||||
static void buttonLongPress();
|
||||
|
||||
float rssi = 0;
|
||||
char wumei_iv[17] = "wumei-smart-open";
|
||||
@@ -26,6 +18,24 @@ int monitorCount = 0;
|
||||
long monitorInterval = 1000;
|
||||
bool isApMode = false;
|
||||
|
||||
// Mqtt订阅的主题,前缀格式为: /productId/devicenumber
|
||||
String prefix = "";
|
||||
String sInfoTopic = "/info/get";
|
||||
String sOtaTopic = "/ota/get";
|
||||
String sNtpTopic = "/ntp/get";
|
||||
String sPropertyTopic = "/property/get";
|
||||
String sFunctionTopic = "/function/get";
|
||||
String sPropertyOnline = "/property-online/get";
|
||||
String sFunctionOnline = "/function-online/get";
|
||||
String sMonitorTopic = "/monitor/get";
|
||||
// Mqtt发布的主题
|
||||
String pInfoTopic = "/info/post";
|
||||
String pNtpTopic = "/ntp/post";
|
||||
String pPropertyTopic = "/property/post";
|
||||
String pFunctionTopic = "/function/post";
|
||||
String pMonitorTopic = "/monitor/post";
|
||||
String pEventTopic = "/event/post";
|
||||
|
||||
/********************************** begin 可配置的项 **********************************/
|
||||
// wifi信息
|
||||
char *wifiSsid = "";
|
||||
@@ -54,81 +64,20 @@ String ntpServer = "http://wumei.live:8080/iot/tool/ntp?deviceSendTime=";
|
||||
|
||||
/********************************** end 可配置的项 **********************************/
|
||||
|
||||
// Mqtt订阅的主题
|
||||
String prefix = "/" + (String)productId + "/" + (String)deviceNum;
|
||||
String sInfoTopic = prefix + "/info/get";
|
||||
String sOtaTopic = prefix + "/ota/get";
|
||||
String sNtpTopic = prefix + "/ntp/get";
|
||||
String sPropertyTopic = prefix + "/property/get";
|
||||
String sFunctionTopic = prefix + "/function/get";
|
||||
String sPropertyOnline = prefix + "/property-online/get";
|
||||
String sFunctionOnline = prefix + "/function-online/get";
|
||||
String sMonitorTopic = prefix + "/monitor/get";
|
||||
// Mqtt发布的主题
|
||||
String pInfoTopic = prefix + "/info/post";
|
||||
String pNtpTopic = prefix + "/ntp/post";
|
||||
String pPropertyTopic = prefix + "/property/post";
|
||||
String pFunctionTopic = prefix + "/function/post";
|
||||
String pMonitorTopic = prefix + "/monitor/post";
|
||||
String pEventTopic = prefix + "/event/post";
|
||||
|
||||
// 初始化项目
|
||||
void initWumeiSmart()
|
||||
{
|
||||
//打开串行端口:
|
||||
Serial.begin(115200);
|
||||
printMsg("wumei smart device starting...");
|
||||
|
||||
// 初始化按键为低电平,并添加单击、双击、长按事件
|
||||
button = OneButton(BUTTON, true, true);
|
||||
button.attachClick(buttonClick);
|
||||
button.attachDoubleClick(buttonDoubleClick);
|
||||
button.attachLongPressStart(buttonLongPress);
|
||||
|
||||
// 加载配置
|
||||
loadConfig();
|
||||
}
|
||||
|
||||
// 按钮单击事件
|
||||
static void buttonClick()
|
||||
{
|
||||
printMsg("检测到按键单击");
|
||||
ledStatus(true);
|
||||
}
|
||||
|
||||
// 按钮双击事件
|
||||
static void buttonDoubleClick()
|
||||
{
|
||||
printMsg("检测到按键双击");
|
||||
ledStatus(false);
|
||||
}
|
||||
|
||||
// 按钮长按事件,进入配网模式
|
||||
static void buttonLongPress()
|
||||
{
|
||||
if (isApMode)
|
||||
{
|
||||
printMsg("设备重启...");
|
||||
ESP.restart();
|
||||
}
|
||||
else
|
||||
{
|
||||
printMsg("开始AP配网");
|
||||
startApConfig();
|
||||
}
|
||||
}
|
||||
|
||||
// 连接wifi
|
||||
void connectWifi()
|
||||
{
|
||||
if (isApMode)
|
||||
{
|
||||
// 关闭AP配网模式
|
||||
isApMode = false;
|
||||
printMsg("连接Wifi... ");
|
||||
server.stop();
|
||||
ledStatus(false);
|
||||
}
|
||||
printMsg("连接Wifi: ");
|
||||
Serial.print(wifiSsid);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(wifiSsid, wifiPwd);
|
||||
// 关闭AP配网模式
|
||||
server.stop();
|
||||
ledStatus(false);
|
||||
}
|
||||
|
||||
// 存储配置
|
||||
@@ -165,28 +114,35 @@ void loadConfig()
|
||||
// wifi名称
|
||||
if (strlen(config.stassid) != 0)
|
||||
{
|
||||
wifiSsid = (char *)malloc(32 * sizeof(char));
|
||||
strcpy(wifiSsid, config.stassid);
|
||||
}
|
||||
// wifi密码
|
||||
if (strlen(config.stapsw) != 0)
|
||||
{
|
||||
wifiPwd = (char *)malloc(64 * sizeof(char));
|
||||
strcpy(wifiPwd, config.stapsw);
|
||||
}
|
||||
// 设备编号
|
||||
if (strlen(config.deviceNum) != 0)
|
||||
{
|
||||
deviceNum = (char *)malloc(32 * sizeof(char));
|
||||
strcpy(deviceNum, config.deviceNum);
|
||||
}
|
||||
// 用户编号
|
||||
if (strlen(config.userId) != 0)
|
||||
{
|
||||
userId = (char *)malloc(16 * sizeof(char));
|
||||
strcpy(userId, config.userId);
|
||||
}
|
||||
// 授权码
|
||||
if (strlen(config.authCode) != 0)
|
||||
{
|
||||
authCode = (char *)malloc(32 * sizeof(char));
|
||||
strcpy(authCode, config.authCode);
|
||||
}
|
||||
// 统一设置Mqtt消息主题前缀
|
||||
prefix = "/" + (String)productId + "/" + (String)deviceNum;
|
||||
}
|
||||
|
||||
// 清空配置
|
||||
@@ -200,44 +156,6 @@ void clearConfig()
|
||||
EEPROM.end();
|
||||
}
|
||||
|
||||
// 随机生成监测值
|
||||
String randomPropertyData()
|
||||
{
|
||||
// 匹配云端定义的监测数据,随机数代替监测结果
|
||||
float randFloat = 0;
|
||||
int randInt = 0;
|
||||
StaticJsonDocument<1024> doc;
|
||||
JsonObject objTmeperature = doc.createNestedObject();
|
||||
objTmeperature["id"] = "temperature";
|
||||
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 printMsg(String msg)
|
||||
{
|
||||
@@ -264,6 +182,7 @@ void blink()
|
||||
// 控制指示灯状态
|
||||
void ledStatus(bool status)
|
||||
{
|
||||
printMsg("更改指示灯状态");
|
||||
pinMode(LED, OUTPUT);
|
||||
if (status)
|
||||
{
|
||||
@@ -1,13 +1,13 @@
|
||||
/*********************************************************************
|
||||
* function: 程序入口
|
||||
* 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: wumei-smart and kerwincui all rights reserved.
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
#include "Apconfig.h"
|
||||
#include "Base64.h"
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <EEPROM.h>
|
||||
#include <PubSubClient.h> // 版本2.8.0
|
||||
#include <ArduinoJson.h> // 版本6.19.1
|
||||
#include <OneButton.h> // 版本2.0.4
|
||||
|
||||
// 存储的配置类型结构
|
||||
struct config_type
|
||||
@@ -30,9 +29,9 @@ struct config_type
|
||||
|
||||
extern WiFiClient wifiClient;
|
||||
extern PubSubClient mqttClient;
|
||||
extern OneButton button;
|
||||
|
||||
extern char *deviceNum ; // 设备编号(重要,同时是Mqtt的clientId)
|
||||
// 全局变量
|
||||
extern char *deviceNum; // 设备编号(重要,同时是Mqtt的clientId)
|
||||
extern char *userId; // 用户ID
|
||||
extern char *productId; // 产品ID
|
||||
extern float rssi; // 信号强度(信号极好4格[-55— 0],信号好3格[-70— -55],信号一般2格[-85— -70],信号差1格[-100— -85])
|
||||
@@ -53,8 +52,8 @@ extern int monitorCount; // 发布监测数据的最大次数
|
||||
extern long monitorInterval; // 发布监测数据的间隔,默认1000毫秒
|
||||
extern bool isApMode; // 是否进入AP配网模式
|
||||
|
||||
|
||||
// 订阅的主题
|
||||
extern String prefix; // Mqtt消息主题前缀
|
||||
extern String sInfoTopic; // 订阅设备信息
|
||||
extern String sOtaTopic; // 订阅OTA升级
|
||||
extern String sNtpTopic; // 订阅NTP时间
|
||||
@@ -71,8 +70,6 @@ extern String pFunctionTopic; // 发布功能
|
||||
extern String pMonitorTopic; // 发布实时监测数据
|
||||
extern String pEventTopic; // 发布事件
|
||||
|
||||
// 初始化项目
|
||||
void initWumeiSmart();
|
||||
// 连接WIFI
|
||||
void connectWifi();
|
||||
// 加载配置
|
||||
@@ -81,14 +78,11 @@ void loadConfig();
|
||||
void saveConfig(config_type config);
|
||||
// 清空配置
|
||||
void clearConfig();
|
||||
// 随机生成监测值
|
||||
String randomPropertyData();
|
||||
//打印提示信息
|
||||
void printMsg(String tips);
|
||||
void printMsg(String msg);
|
||||
// 控制指示灯闪烁
|
||||
void blink();
|
||||
// 控制指示灯状态
|
||||
void ledStatus(bool status);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************************
|
||||
* function: 程序入口
|
||||
* 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
|
||||
@@ -8,145 +8,18 @@
|
||||
|
||||
#include "Mqtt.h"
|
||||
|
||||
// 物模型-属性处理
|
||||
void processProperty(String payload)
|
||||
// 订阅系统主题
|
||||
void subscribeTopic()
|
||||
{
|
||||
StaticJsonDocument<1024> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload);
|
||||
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(payload);
|
||||
}
|
||||
|
||||
// 物模型-功能处理
|
||||
void processFunction(String payload)
|
||||
{
|
||||
StaticJsonDocument<1024> doc;
|
||||
DeserializationError error = deserializeJson(doc, payload);
|
||||
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, "switch") == 0)
|
||||
{
|
||||
printMsg("开关 switch:" + (String) value);
|
||||
}
|
||||
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){
|
||||
String msg=randomPropertyData();
|
||||
printMsg("订阅到上报监测数据指令,上报数据:");
|
||||
printMsg(msg);
|
||||
publishProperty(msg);
|
||||
}
|
||||
}
|
||||
// 最后发布功能,服务端订阅存储(重要)
|
||||
publishFunction(payload);
|
||||
}
|
||||
|
||||
// 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, 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, sInfoTopic.c_str()) == 0)
|
||||
{
|
||||
printMsg("订阅到设备信息...");
|
||||
// 发布设备信息
|
||||
publishInfo();
|
||||
}
|
||||
else if (strcmp(topic, 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, sPropertyTopic.c_str()) == 0 || strcmp(topic, sPropertyOnline.c_str()) == 0)
|
||||
{
|
||||
printMsg("订阅到属性指令...");
|
||||
processProperty(data);
|
||||
}
|
||||
else if (strcmp(topic, sFunctionTopic.c_str()) == 0 || strcmp(topic, sFunctionOnline.c_str()) == 0)
|
||||
{
|
||||
printMsg("订阅到功能指令...");
|
||||
processFunction(data);
|
||||
}
|
||||
else if (strcmp(topic, 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"];
|
||||
}
|
||||
mqttClient.subscribe((prefix + sInfoTopic).c_str(), 1);
|
||||
mqttClient.subscribe((prefix + sOtaTopic).c_str(), 1);
|
||||
mqttClient.subscribe((prefix + sNtpTopic).c_str(), 1);
|
||||
mqttClient.subscribe((prefix + sPropertyTopic).c_str(), 1);
|
||||
mqttClient.subscribe((prefix + sFunctionTopic).c_str(), 1);
|
||||
mqttClient.subscribe((prefix + sPropertyOnline).c_str(), 1);
|
||||
mqttClient.subscribe((prefix + sFunctionOnline).c_str(), 1);
|
||||
mqttClient.subscribe((prefix + sMonitorTopic).c_str(), 1);
|
||||
printMsg("订阅主题完成");
|
||||
}
|
||||
|
||||
// 1.发布设备信息
|
||||
@@ -161,18 +34,18 @@ void publishInfo()
|
||||
doc["latitude"] = latitude; // 纬度 可选
|
||||
// 设备摘要,可选(自定义配置信息)
|
||||
JsonObject summary = doc.createNestedObject("summary");
|
||||
summary["name"]="wumei-smart";
|
||||
summary["chip"]="esp8266";
|
||||
summary["author"]="kerwincui";
|
||||
summary["version"]=1.6;
|
||||
summary["create"]="2022-06-06";
|
||||
summary["name"] = "wumei-smart";
|
||||
summary["chip"] = "esp8266";
|
||||
summary["author"] = "kerwincui";
|
||||
summary["version"] = 1.6;
|
||||
summary["create"] = "2022-06-06";
|
||||
|
||||
printMsg("发布设备信息:");
|
||||
serializeJson(doc, Serial);
|
||||
String output;
|
||||
serializeJson(doc, output);
|
||||
printMsg("主题为:" + pPropertyTopic);
|
||||
mqttClient.publish(pInfoTopic.c_str(), output.c_str());
|
||||
printMsg("主题为:" + prefix + pInfoTopic);
|
||||
mqttClient.publish((prefix + pInfoTopic).c_str(), output.c_str());
|
||||
}
|
||||
|
||||
// 2.发布时钟同步信,用于获取当前时间(可选)
|
||||
@@ -180,60 +53,42 @@ void publishNtp()
|
||||
{
|
||||
StaticJsonDocument<128> doc;
|
||||
doc["deviceSendTime"] = millis();
|
||||
|
||||
printMsg("发布NTP信息:");
|
||||
printMsg("发布主题:" + prefix + pNtpTopic);
|
||||
printMsg("信息:");
|
||||
serializeJson(doc, Serial);
|
||||
String output;
|
||||
serializeJson(doc, output);
|
||||
printMsg("主题为:" + pPropertyTopic);
|
||||
mqttClient.publish(pNtpTopic.c_str(), output.c_str());
|
||||
mqttClient.publish((prefix + pNtpTopic).c_str(), output.c_str());
|
||||
}
|
||||
|
||||
// 3.发布属性
|
||||
void publishProperty(String msg)
|
||||
{
|
||||
printMsg("发布属性:" + msg);
|
||||
printMsg("主题为:" + pPropertyTopic);
|
||||
mqttClient.publish(pPropertyTopic.c_str(), msg.c_str());
|
||||
printMsg("发布属性:" + prefix + pPropertyTopic);
|
||||
printMsg("消息:" + msg);
|
||||
mqttClient.publish((prefix + pPropertyTopic).c_str(), msg.c_str());
|
||||
}
|
||||
|
||||
// 4.发布功能
|
||||
void publishFunction(String msg)
|
||||
{
|
||||
printMsg("发布功能:" + msg);
|
||||
printMsg("主题为:" + pPropertyTopic);
|
||||
mqttClient.publish(pFunctionTopic.c_str(), msg.c_str());
|
||||
printMsg("发布功能:" + prefix + pFunctionTopic);
|
||||
printMsg("消息:" + msg);
|
||||
mqttClient.publish((prefix + pFunctionTopic).c_str(), msg.c_str());
|
||||
}
|
||||
|
||||
// 5.发布事件
|
||||
void publishEvent()
|
||||
void publishEvent(String msg)
|
||||
{
|
||||
// 匹配云端的事件
|
||||
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);
|
||||
printMsg("主题为:" + pPropertyTopic);
|
||||
mqttClient.publish(pEventTopic.c_str(), output.c_str());
|
||||
printMsg("发布事件:" + prefix + pEventTopic);
|
||||
printMsg("消息:" + msg);
|
||||
mqttClient.publish((prefix + pEventTopic).c_str(), msg.c_str());
|
||||
}
|
||||
|
||||
// 6.发布实时监测数据
|
||||
void publishMonitor()
|
||||
void publishMonitor(String msg)
|
||||
{
|
||||
String msg=randomPropertyData();
|
||||
// 发布为实时监测数据,不会存储
|
||||
printMsg("发布实时监测数据:"+msg);
|
||||
printMsg("主题为:" + pPropertyTopic);
|
||||
mqttClient.publish(pMonitorTopic.c_str(), msg.c_str());
|
||||
// 发布实时监测数据(不会存储,需要实时存储则发布为属性)
|
||||
printMsg("发布实时监测消息:" + msg);
|
||||
mqttClient.publish((prefix + pMonitorTopic).c_str(), msg.c_str());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*********************************************************************
|
||||
* function: 程序入口
|
||||
* 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
|
||||
@@ -9,26 +9,21 @@
|
||||
#ifndef _MQTT_H
|
||||
#define _MQTT_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Config.h"
|
||||
|
||||
// 订阅系统主题
|
||||
void subscribeTopic();
|
||||
// 发布设备信息
|
||||
void publishInfo();
|
||||
// 发布时钟同步信息
|
||||
void publishNtp();
|
||||
// 发布事件
|
||||
void publishEvent();
|
||||
// 发布实时监测数据
|
||||
void publishMonitor();
|
||||
void publishEvent(String msg);
|
||||
// 发布实时监测数据(不会存储,需要实时存储则发布属性)
|
||||
void publishMonitor(String msg);
|
||||
// 发布属性
|
||||
void publishProperty(String msg);
|
||||
// 发布功能
|
||||
void publishFunction(String msg);
|
||||
|
||||
// Mqtt回调
|
||||
void mqttCallback(char *topic, byte *payload, unsigned int length);
|
||||
// 属性处理
|
||||
void processProperty(String payload);
|
||||
// 功能处理
|
||||
void processFunction(String payload);
|
||||
|
||||
#endif
|
||||
|
||||
296
sdk/Arduino/WumeiArduino/User.cpp
Normal file
296
sdk/Arduino/WumeiArduino/User.cpp
Normal file
@@ -0,0 +1,296 @@
|
||||
/*********************************************************************
|
||||
* 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: wumei-smart 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"] = "temperature";
|
||||
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, "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)
|
||||
{
|
||||
String msg = randomPropertyData();
|
||||
printMsg("订阅到上报监测数据指令,上报数据:");
|
||||
printMsg(msg);
|
||||
publishProperty(msg);
|
||||
}
|
||||
}
|
||||
// 最后发布功能,服务端订阅存储(重要)
|
||||
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();
|
||||
}
|
||||
}
|
||||
33
sdk/Arduino/WumeiArduino/User.h
Normal file
33
sdk/Arduino/WumeiArduino/User.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*********************************************************************
|
||||
* 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: wumei-smart and kerwincui all rights reserved.
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _USER_H
|
||||
#define _USER_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "Mqtt.h"
|
||||
#include <OneButton.h> // 版本2.0.4
|
||||
|
||||
extern OneButton button;
|
||||
|
||||
// 初始化用户配置
|
||||
void initUser();
|
||||
// Mqtt回调
|
||||
void mqttCallback(char *topic, byte *payload, unsigned int length);
|
||||
// 属性处理(物模型)
|
||||
void processProperty(String msg);
|
||||
// 功能处理(物模型)
|
||||
void processFunction(String msg);
|
||||
// 事件处理(无模型)
|
||||
void processEvent();
|
||||
// 模拟监测值
|
||||
String randomPropertyData();
|
||||
// 控制继电器状态
|
||||
void relayStatus(bool status);
|
||||
|
||||
#endif
|
||||
@@ -6,9 +6,10 @@
|
||||
* copyright: wumei-smart and kerwincui all rights reserved.
|
||||
********************************************************************/
|
||||
|
||||
#include "Common.h"
|
||||
#include "Config.h"
|
||||
#include "Auth.h"
|
||||
#include "Apconfig.h"
|
||||
#include "User.h"
|
||||
|
||||
long lastWifiConn; // 上次wifi连接时间
|
||||
long lastMqttConn; // 上次mqtt连接时间
|
||||
@@ -20,20 +21,24 @@ long lastPublishSimulateData; // 上次发布测试数据时间
|
||||
*/
|
||||
void setup()
|
||||
{
|
||||
clearConfig();
|
||||
// 初始化配置
|
||||
initWumeiSmart();
|
||||
//打开串行端口:
|
||||
Serial.begin(115200);
|
||||
printMsg("wumei smart device starting...");
|
||||
// 加载配置
|
||||
loadConfig();
|
||||
// 初始化用户配置
|
||||
initUser();
|
||||
|
||||
if(strcmp(wifiSsid, "") == 0){
|
||||
if (strcmp(wifiSsid, "") == 0)
|
||||
{
|
||||
// 启动配网
|
||||
startApConfig();
|
||||
}else{
|
||||
}
|
||||
else
|
||||
{
|
||||
// 连接Wifi
|
||||
connectWifi();
|
||||
// 连接Mqtt(加密认证)
|
||||
connectMqtt();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,27 +58,24 @@ void loop()
|
||||
{
|
||||
// Wifi重连
|
||||
wifiReconnectionClient();
|
||||
|
||||
// Mqtt重连
|
||||
// Mqtt连接
|
||||
mqttReconnectionClient();
|
||||
|
||||
// 发布实时监测数据
|
||||
publicMonitorClient();
|
||||
|
||||
// 发布模拟数据,测试用
|
||||
publishSimulateDataClient();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wifi掉线重连(非阻塞,间隔10s)
|
||||
* Wifi掉线重连(非阻塞,间隔5s)
|
||||
*/
|
||||
void wifiReconnectionClient()
|
||||
{
|
||||
long now = millis();
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
if (now - lastWifiConn > 10000)
|
||||
if (now - lastWifiConn > 5000)
|
||||
{
|
||||
lastWifiConn = now;
|
||||
WiFi.reconnect();
|
||||
@@ -82,7 +84,7 @@ void wifiReconnectionClient()
|
||||
}
|
||||
|
||||
/*
|
||||
* mqtt掉线重连(非阻塞、间隔30s)
|
||||
* mqtt连接(非阻塞、间隔5s)
|
||||
*/
|
||||
void mqttReconnectionClient()
|
||||
{
|
||||
@@ -91,7 +93,7 @@ void mqttReconnectionClient()
|
||||
long now = millis();
|
||||
if (!mqttClient.connected())
|
||||
{
|
||||
if (now - lastMqttConn > 30000)
|
||||
if (now - lastMqttConn > 5000)
|
||||
{
|
||||
lastMqttConn = now;
|
||||
connectMqtt();
|
||||
@@ -116,7 +118,8 @@ void publicMonitorClient()
|
||||
{
|
||||
lastPublishMonitor = now;
|
||||
monitorCount--;
|
||||
publishMonitor();
|
||||
String msg = randomPropertyData();
|
||||
publishMonitor(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,7 +137,7 @@ void publishSimulateDataClient()
|
||||
lastPublishSimulateData = now;
|
||||
printMsg("执行定时上报");
|
||||
// 发布事件
|
||||
publishEvent();
|
||||
processEvent();
|
||||
// 发布时钟同步
|
||||
publishNtp();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user