mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-17 16:36:03 +08:00
新增Arduino固件-待完善
This commit is contained in:
164
sdk/Arduino/WumeiArduino/Apconfig.cpp
Normal file
164
sdk/Arduino/WumeiArduino/Apconfig.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
// /***********************************************************
|
||||
// * function: 设备配网
|
||||
// * board: esp8266 core for arduino v3.0.2
|
||||
// * library: PubSubClient2.8.0 & ArduinoJson6.19.1
|
||||
// * source: https://github.com/kerwincui/wumei-smart
|
||||
// ***********************************************************/
|
||||
|
||||
// #include <ESP8266WiFi.h>
|
||||
// #include <ESP8266WebServer.h>
|
||||
|
||||
// String randomName="wumei-device"+(String)random(1000);
|
||||
// const char *ap_ssid =randomName.c_str();
|
||||
// const char *ap_password = ""; //开放式网络
|
||||
|
||||
// char sta_ssid[32] = {0};
|
||||
// char sta_password[64] = {0};
|
||||
// char sta_user_id[32] = {0};
|
||||
|
||||
// IPAddress local_IP(192, 168, 4, 1);
|
||||
// IPAddress gateway(192, 168, 4, 1);
|
||||
// IPAddress subnet(255, 255, 255, 0);
|
||||
|
||||
// void initApConfig();
|
||||
// void initWebServer();
|
||||
// void handleConfig();
|
||||
// void handleStatus();
|
||||
// void handleNotFound();
|
||||
|
||||
// ESP8266WebServer server(80);
|
||||
|
||||
// // void setup(void)
|
||||
// // {
|
||||
// // //打开串行端口:
|
||||
// // Serial.begin(115200);
|
||||
// // // AP模式
|
||||
// // initApConfig();
|
||||
// // // web服务
|
||||
// // initWebServer();
|
||||
// // }
|
||||
|
||||
// // void loop(void)
|
||||
// // {
|
||||
// // // Web服务端
|
||||
// // server.handleClient();
|
||||
// // }
|
||||
|
||||
// /**
|
||||
// * AP模式
|
||||
// */
|
||||
// void initApConfig()
|
||||
// {
|
||||
// WiFi.mode(WIFI_AP_STA);
|
||||
// WiFi.softAPConfig(local_IP, gateway, subnet);
|
||||
// WiFi.softAP(ap_ssid, ap_password);
|
||||
// printMsg("已启动AP配网,IP地址:" + WiFi.softAPIP().toString()+", 热点名称:"+(String)ap_ssid);
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 初始化webserver配置
|
||||
// */
|
||||
// void initWebServer()
|
||||
// {
|
||||
// server.on("/status", HTTP_GET, handleStatus);
|
||||
// server.on("/config", HTTP_POST, handleConfig);
|
||||
// server.onNotFound(handleNotFound);
|
||||
// server.enableCORS(true);
|
||||
// server.begin();
|
||||
// printMsg("HTTP服务已启动");
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 连接WIFI
|
||||
// */
|
||||
// void connectWifi()
|
||||
// {
|
||||
// printMsg("连接WIFI");
|
||||
// WiFi.begin(sta_ssid, sta_password);
|
||||
// int cnt = 0;
|
||||
// while (WiFi.status() != WL_CONNECTED)
|
||||
// {
|
||||
// delay(500);
|
||||
// cnt++;
|
||||
// Serial.print(".");
|
||||
// if (cnt >= 30)
|
||||
// {
|
||||
// printMsg("设备连接WIFI超时,请重新配网");
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// server.close();
|
||||
// WiFi.softAPdisconnect(false);
|
||||
// printMsg("Http服务和热点已关闭,设备已连接WIFI");
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 检测设备状态
|
||||
// */
|
||||
// void handleStatus(){
|
||||
// server.send(200, "text/plain;charset=utf-8", "AP配网已准备就绪");
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 配网:下发配置信息
|
||||
// */
|
||||
// void handleConfig()
|
||||
// {
|
||||
// printMsg("进入配网......");
|
||||
// // wifi名称、wifi密码、用户编号
|
||||
// if (server.hasArg("SSID") && server.hasArg("password") && server.hasArg("userId"))
|
||||
// {
|
||||
// strcpy(sta_ssid, server.arg("SSID").c_str());
|
||||
// strcpy(sta_password, server.arg("password").c_str());
|
||||
// strcpy(sta_user_id, server.arg("userId").c_str());
|
||||
// printMsg("收到WIFI名称:" + (String)sta_ssid);
|
||||
// printMsg("收到WIFI密码:" + (String)sta_password);
|
||||
// printMsg("收到用户编号:" + (String)sta_user_id);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// printMsg("配网必须传递用户编号、WIFI名称和WIFI密码,配网失败");
|
||||
// server.send(500, "text/plain;charset=utf-8", "配网必须传递用户编号、WIFI名称和WIFI密码,配网失败");
|
||||
// return;
|
||||
// }
|
||||
// // 可选字段
|
||||
// if (server.hasArg("deviceNum"))
|
||||
// {
|
||||
// printMsg("收到设备编号:" + server.arg("deviceNum"));
|
||||
// }
|
||||
// if (server.hasArg("extra"))
|
||||
// {
|
||||
// printMsg("收到补充信息:" + server.arg("extra"));
|
||||
// }
|
||||
// // TODO 可增加设备连接WIFI测试
|
||||
|
||||
// server.send(200, "text/plain;charset=utf-8", "设备已更新WIFI配置,开始连接WIFI...");
|
||||
// connectWifi();
|
||||
// }
|
||||
|
||||
// void handleNotFound()
|
||||
// {
|
||||
// printMsg("进入预检请求或请求地址找不到");
|
||||
// if (server.method() == HTTP_OPTIONS)
|
||||
// {
|
||||
// // 处理浏览器跨域问题
|
||||
// server.sendHeader("Access-Control-Max-Age", "10000");
|
||||
// server.sendHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS");
|
||||
// server.sendHeader("Access-Control-Allow-Headers", "*");
|
||||
// server.send(204);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// server.send(404, "text/plain;charset=utf-8", "请求的地址找不到或无法访问");
|
||||
// }
|
||||
// }
|
||||
|
||||
// //打印提示信息
|
||||
// void printMsg(String msg)
|
||||
// {
|
||||
// Serial.print("\r\n[");
|
||||
// Serial.print(millis());
|
||||
// Serial.print("ms]");
|
||||
// Serial.print(msg);
|
||||
// }
|
||||
|
||||
15
sdk/Arduino/WumeiArduino/Apconfig.h
Normal file
15
sdk/Arduino/WumeiArduino/Apconfig.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/***********************************************************
|
||||
* function: 设备配网
|
||||
* board: esp8266 core for arduino v3.0.2
|
||||
* library: PubSubClient2.8.0 & ArduinoJson6.19.1
|
||||
* source: https://github.com/kerwincui/wumei-smart
|
||||
***********************************************************/
|
||||
|
||||
#ifndef _APCONFIG_H
|
||||
#define _APCONFIG_H
|
||||
|
||||
#include "Base64.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
|
||||
#endif
|
||||
182
sdk/Arduino/WumeiArduino/Auth.cpp
Normal file
182
sdk/Arduino/WumeiArduino/Auth.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
/***********************************************************
|
||||
* function: 设备认证
|
||||
* board: esp8266 core for arduino v3.0.2
|
||||
* library: PubSubClient2.8.0 & ArduinoJson6.19.1
|
||||
* source: https://github.com/kerwincui/wumei-smart
|
||||
***********************************************************/
|
||||
|
||||
#include "Auth.h"
|
||||
|
||||
/*
|
||||
* 连接MQTT,加密认证
|
||||
*/
|
||||
void connectMqtt()
|
||||
{
|
||||
printMsg("连接Mqtt服务器...");
|
||||
mqttClient.setClient(wifiClient);
|
||||
mqttClient.setServer(mqttHost, mqttPort);
|
||||
mqttClient.setBufferSize(1024);
|
||||
mqttClient.setKeepAlive(5);
|
||||
// 设置Mqtt回调函数
|
||||
mqttClient.setCallback(mqttCallback);
|
||||
|
||||
// 生成mqtt加密密码
|
||||
String aesPassword = generationAESPwd();
|
||||
// 连接 设备mqtt客户端Id格式为:认证类型(E=加密、S=简单) & 设备编号 & 产品ID & 用户ID
|
||||
String clientId = "E&" + deviceNum + "&" + productId + "&" + userId;
|
||||
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("订阅主题完成");
|
||||
// 发布设备信息,设备上电都需要发布一次
|
||||
publishInfo();
|
||||
}
|
||||
else
|
||||
{
|
||||
printMsg("连接失败, rc=");
|
||||
Serial.print(mqttClient.state());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 生成加密密码
|
||||
*/
|
||||
String generationAESPwd()
|
||||
{
|
||||
// 获取NTP时间
|
||||
String jsonTime = getTime();
|
||||
StaticJsonDocument<128> doc;
|
||||
DeserializationError error = deserializeJson(doc, jsonTime);
|
||||
if (error)
|
||||
{
|
||||
printMsg("Json解析失败:");
|
||||
Serial.print(error.f_str());
|
||||
return "";
|
||||
}
|
||||
// 获取NTP时间=(设备发送消息时间 + 服务器接收消息时间 + 服务器发送消息时间 - 设备接收时间 最后除于2 )
|
||||
float deviceSendTime = doc["deviceSendTime"];
|
||||
float serverSendTime = doc["serverSendTime"];
|
||||
float serverRecvTime = doc["serverRecvTime"];
|
||||
float deviceRecvTime = millis();
|
||||
float now = (serverSendTime + serverRecvTime + deviceRecvTime - deviceSendTime) / 2;
|
||||
// 过期时间 = 当前时间 + 1小时
|
||||
float expireTime = now + 1 * 60 * 60 * 1000;
|
||||
// 加密认证,密码格式为:mqtt密码 & 过期时间 & 授权码(可选),如果产品启用了授权码就必须加上
|
||||
String password = "";
|
||||
if (authCode == "")
|
||||
{
|
||||
password = (String)mqttPwd + "&" + String(expireTime, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
password = (String)mqttPwd + "&" + String(expireTime, 0) + "&" + authCode;
|
||||
}
|
||||
// 密码加密
|
||||
printMsg("密码(未加密):" + password);
|
||||
String encryptPassword = encrypt(password, mqttSecret, wumei_iv);
|
||||
printMsg("密码(已加密):" + encryptPassword);
|
||||
return encryptPassword;
|
||||
}
|
||||
|
||||
/*
|
||||
* 通过HTTP获取NTP时间
|
||||
*/
|
||||
String getTime()
|
||||
{
|
||||
while (WiFi.status() == WL_CONNECTED)
|
||||
{
|
||||
HTTPClient http;
|
||||
printMsg("获取时间...");
|
||||
if (http.begin(wifiClient, (ntpServer + (String)millis()).c_str()))
|
||||
{
|
||||
// 发送请求
|
||||
int httpCode = http.GET();
|
||||
if (httpCode > 0)
|
||||
{
|
||||
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY)
|
||||
{
|
||||
printMsg("获取时间成功,data:");
|
||||
Serial.print(http.getString());
|
||||
return http.getString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printMsg("获取时间失败,error:");
|
||||
Serial.printf(http.errorToString(httpCode).c_str());
|
||||
}
|
||||
http.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
printMsg("连接Http失败");
|
||||
}
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AES加密 (AES-CBC-128-pkcs5padding)
|
||||
*/
|
||||
String encrypt(String plain_data, char *wumei_key, char *wumei_iv)
|
||||
{
|
||||
int i;
|
||||
// pkcs7padding填充 Block Size : 16
|
||||
int len = plain_data.length();
|
||||
int n_blocks = len / 16 + 1;
|
||||
uint8_t n_padding = n_blocks * 16 - len;
|
||||
uint8_t data[n_blocks * 16];
|
||||
memcpy(data, plain_data.c_str(), len);
|
||||
for (i = len; i < n_blocks * 16; i++)
|
||||
{
|
||||
data[i] = n_padding;
|
||||
}
|
||||
uint8_t key[16], iv[16];
|
||||
memcpy(key, wumei_key, 16);
|
||||
memcpy(iv, wumei_iv, 16);
|
||||
// 加密
|
||||
br_aes_big_cbcenc_keys encCtx;
|
||||
br_aes_big_cbcenc_init(&encCtx, key, 16);
|
||||
br_aes_big_cbcenc_run(&encCtx, iv, data, n_blocks * 16);
|
||||
// Base64编码
|
||||
len = n_blocks * 16;
|
||||
char encoded_data[base64_enc_len(len)];
|
||||
base64_encode(encoded_data, (char *)data, len);
|
||||
return String(encoded_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* AES解密 (AES-CBC-128-pkcs5padding)
|
||||
*/
|
||||
String decrypt(String encoded_data_str, char *wumei_key, char *wumei_iv)
|
||||
{
|
||||
int input_len = encoded_data_str.length();
|
||||
char *encoded_data = const_cast<char *>(encoded_data_str.c_str());
|
||||
int len = base64_dec_len(encoded_data, input_len);
|
||||
uint8_t data[len];
|
||||
base64_decode((char *)data, encoded_data, input_len);
|
||||
uint8_t key[16], iv[16];
|
||||
memcpy(key, wumei_key, 16);
|
||||
memcpy(iv, wumei_iv, 16);
|
||||
int n_blocks = len / 16;
|
||||
br_aes_big_cbcdec_keys decCtx;
|
||||
br_aes_big_cbcdec_init(&decCtx, key, 16);
|
||||
br_aes_big_cbcdec_run(&decCtx, iv, data, n_blocks * 16);
|
||||
// PKCS#7 Padding 填充
|
||||
uint8_t n_padding = data[n_blocks * 16 - 1];
|
||||
len = n_blocks * 16 - n_padding;
|
||||
char plain_data[len + 1];
|
||||
memcpy(plain_data, data, len);
|
||||
plain_data[len] = '\0';
|
||||
return String(plain_data);
|
||||
}
|
||||
28
sdk/Arduino/WumeiArduino/Auth.h
Normal file
28
sdk/Arduino/WumeiArduino/Auth.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/***********************************************************
|
||||
* function: 设备认证
|
||||
* board: esp8266 core for arduino v3.0.2
|
||||
* library: PubSubClient2.8.0 & ArduinoJson6.19.1
|
||||
* source: https://github.com/kerwincui/wumei-smart
|
||||
***********************************************************/
|
||||
|
||||
#ifndef _AUTH9_H
|
||||
#define _AUTH9_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Mqtt.h"
|
||||
#include "Base64.h"
|
||||
#include <Ethernet.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
|
||||
// 连接mqtt, AES加密认证
|
||||
void connectMqtt();
|
||||
// 生成加密密码
|
||||
String generationAESPwd();
|
||||
// 获取时间
|
||||
String getTime();
|
||||
// AES加密
|
||||
String encrypt(String plain_data,char *wumei_key,char *wumei_iv);
|
||||
// AES解密
|
||||
String decrypt(String encoded_data_str,char *wumei_key,char *wumei_iv);
|
||||
|
||||
#endif
|
||||
137
sdk/Arduino/WumeiArduino/Base64.cpp
Normal file
137
sdk/Arduino/WumeiArduino/Base64.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
#include "Base64.h"
|
||||
|
||||
#if (defined(__AVR__))
|
||||
#include <avr\pgmspace.h>
|
||||
#else
|
||||
#include <pgmspace.h>
|
||||
#endif
|
||||
|
||||
const char PROGMEM b64_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"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 unsigned char b64_lookup(char c);
|
||||
|
||||
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--) {
|
||||
a3[i++] = *(input++);
|
||||
if(i == 3) {
|
||||
a3_to_a4(a4, a3);
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
output[encLen++] = pgm_read_byte(&b64_alphabet[a4[i]]);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(i) {
|
||||
for(j = i; j < 3; j++) {
|
||||
a3[j] = '\0';
|
||||
}
|
||||
|
||||
a3_to_a4(a4, a3);
|
||||
|
||||
for(j = 0; j < i + 1; j++) {
|
||||
output[encLen++] = pgm_read_byte(&b64_alphabet[a4[j]]);
|
||||
}
|
||||
|
||||
while((i++ < 3)) {
|
||||
output[encLen++] = '=';
|
||||
}
|
||||
}
|
||||
output[encLen] = '\0';
|
||||
return encLen;
|
||||
}
|
||||
|
||||
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 == '=') {
|
||||
break;
|
||||
}
|
||||
|
||||
a4[i++] = *(input++);
|
||||
if (i == 4) {
|
||||
for (i = 0; i <4; i++) {
|
||||
a4[i] = b64_lookup(a4[i]);
|
||||
}
|
||||
|
||||
a4_to_a3(a3,a4);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
output[decLen++] = a3[i];
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i) {
|
||||
for (j = i; j < 4; j++) {
|
||||
a4[j] = '\0';
|
||||
}
|
||||
|
||||
for (j = 0; j <4; j++) {
|
||||
a4[j] = b64_lookup(a4[j]);
|
||||
}
|
||||
|
||||
a4_to_a3(a3,a4);
|
||||
|
||||
for (j = 0; j < i - 1; j++) {
|
||||
output[decLen++] = a3[j];
|
||||
}
|
||||
}
|
||||
output[decLen] = '\0';
|
||||
return decLen;
|
||||
}
|
||||
|
||||
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 i = 0;
|
||||
int numEq = 0;
|
||||
for(i = inputLen - 1; input[i] == '='; i--) {
|
||||
numEq++;
|
||||
}
|
||||
|
||||
return ((6 * inputLen) / 8) - numEq;
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
return -1;
|
||||
}
|
||||
79
sdk/Arduino/WumeiArduino/Base64.h
Normal file
79
sdk/Arduino/WumeiArduino/Base64.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Adam Rudd.
|
||||
* See LICENSE for more information
|
||||
*/
|
||||
#ifndef _BASE64_H
|
||||
#define _BASE64_H
|
||||
|
||||
/* b64_alphabet:
|
||||
* Description: Base64 alphabet table, a mapping between integers
|
||||
* and base64 digits
|
||||
* Notes: This is an extern here but is defined in Base64.c
|
||||
*/
|
||||
extern const char b64_alphabet[];
|
||||
|
||||
/* base64_encode:
|
||||
* Description:
|
||||
* Encode a string of characters as base64
|
||||
* Parameters:
|
||||
* output: the output buffer for the encoding, stores the encoded string
|
||||
* input: the input buffer for the encoding, stores the binary to be encoded
|
||||
* inputLen: the length of the input buffer, in bytes
|
||||
* Return value:
|
||||
* Returns the length of the encoded string
|
||||
* Requirements:
|
||||
* 1. output must not be null or empty
|
||||
* 2. input must not be null
|
||||
* 3. inputLen must be greater than or equal to 0
|
||||
*/
|
||||
int base64_encode(char *output, char *input, int inputLen);
|
||||
|
||||
/* base64_decode:
|
||||
* Description:
|
||||
* Decode a base64 encoded string into bytes
|
||||
* Parameters:
|
||||
* output: the output buffer for the decoding,
|
||||
* stores the decoded binary
|
||||
* input: the input buffer for the decoding,
|
||||
* stores the base64 string to be decoded
|
||||
* inputLen: the length of the input buffer, in bytes
|
||||
* Return value:
|
||||
* Returns the length of the decoded string
|
||||
* Requirements:
|
||||
* 1. output must not be null or empty
|
||||
* 2. input must not be null
|
||||
* 3. inputLen must be greater than or equal to 0
|
||||
*/
|
||||
int base64_decode(char *output, char *input, int inputLen);
|
||||
|
||||
/* base64_enc_len:
|
||||
* Description:
|
||||
* Returns the length of a base64 encoded string whose decoded
|
||||
* form is inputLen bytes long
|
||||
* Parameters:
|
||||
* inputLen: the length of the decoded string
|
||||
* Return value:
|
||||
* The length of a base64 encoded string whose decoded form
|
||||
* is inputLen bytes long
|
||||
* Requirements:
|
||||
* None
|
||||
*/
|
||||
int base64_enc_len(int inputLen);
|
||||
|
||||
/* base64_dec_len:
|
||||
* Description:
|
||||
* Returns the length of the decoded form of a
|
||||
* base64 encoded string
|
||||
* Parameters:
|
||||
* input: the base64 encoded string to be measured
|
||||
* inputLen: the length of the base64 encoded string
|
||||
* Return value:
|
||||
* Returns the length of the decoded form of a
|
||||
* base64 encoded string
|
||||
* Requirements:
|
||||
* 1. input must not be null
|
||||
* 2. input must be greater than or equal to zero
|
||||
*/
|
||||
int base64_dec_len(char *input, int inputLen);
|
||||
|
||||
#endif // _BASE64_H
|
||||
120
sdk/Arduino/WumeiArduino/Common.cpp
Normal file
120
sdk/Arduino/WumeiArduino/Common.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/***********************************************************
|
||||
* function: 设备交互
|
||||
* board: esp8266 core for arduino v3.0.2
|
||||
* library: PubSubClient2.8.0 & ArduinoJson6.19.1
|
||||
* source: https://github.com/kerwincui/wumei-smart
|
||||
***********************************************************/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
WiFiClient wifiClient;
|
||||
PubSubClient mqttClient;
|
||||
float rssi = 0;
|
||||
char wumei_iv[17] = "wumei-smart-open";
|
||||
int monitorCount = 0;
|
||||
long monitorInterval = 1000;
|
||||
|
||||
//==================================== 这是需要配置的项 ===============================
|
||||
// Wifi配置
|
||||
char *wifiSsid = "wumei";
|
||||
char *wifiPwd = "wumei-smart";
|
||||
|
||||
// 设备信息配置
|
||||
String deviceNum = "D6329VL548866";
|
||||
String userId = "1";
|
||||
String productId = "41";
|
||||
float firmwareVersion = 1.0;
|
||||
// 经度和纬度可选,如果产品使用设备定位,则必须传
|
||||
float latitude=0;
|
||||
float longitude=0;
|
||||
|
||||
// Mqtt配置
|
||||
char *mqttHost = "wumei.live";
|
||||
int mqttPort = 1883;
|
||||
char *mqttUserName = "wumei-smart";
|
||||
char *mqttPwd = "PHYFED93WSFF1DAS";
|
||||
char mqttSecret[17] = "K2V5DE28XNUU3497";
|
||||
// 产品启用授权码,则授权码不能为空
|
||||
String authCode="";
|
||||
|
||||
// NTP地址(用于获取时间,修改为自己部署项目的接口地址)
|
||||
String ntpServer = "http://wumei.live:8080/iot/tool/ntp?deviceSendTime=";
|
||||
|
||||
|
||||
// 连接wifi
|
||||
void connectWifi()
|
||||
{
|
||||
printMsg("连接 ");
|
||||
Serial.print(wifiSsid);
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(wifiSsid, wifiPwd);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
printMsg("WiFi连接成功");
|
||||
printMsg("IP地址: ");
|
||||
Serial.print(WiFi.localIP());
|
||||
}
|
||||
|
||||
// 随机生成监测值
|
||||
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)
|
||||
{
|
||||
Serial.print("\r\n[");
|
||||
Serial.print(millis());
|
||||
Serial.print("ms]");
|
||||
Serial.print(msg);
|
||||
}
|
||||
|
||||
// 控制指示灯闪烁
|
||||
void blink()
|
||||
{
|
||||
printMsg("指示灯闪烁...");
|
||||
int led=15;
|
||||
pinMode(led, OUTPUT);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
digitalWrite(led, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(led, LOW);
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
50
sdk/Arduino/WumeiArduino/Common.h
Normal file
50
sdk/Arduino/WumeiArduino/Common.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/***********************************************************
|
||||
* function: 设备交互
|
||||
* board: esp8266 core for arduino v3.0.2
|
||||
* library: PubSubClient2.8.0 & ArduinoJson6.19.1
|
||||
* source: https://github.com/kerwincui/wumei-smart
|
||||
***********************************************************/
|
||||
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
|
||||
#include "Base64.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <Ethernet.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
#include <PubSubClient.h> // 版本2.8.0
|
||||
#include <ArduinoJson.h> // 版本6.19.1
|
||||
|
||||
extern WiFiClient wifiClient;
|
||||
extern PubSubClient mqttClient;
|
||||
|
||||
extern String deviceNum ; // 设备编号(重要,同时是Mqtt的clientId)
|
||||
extern String userId; // 用户ID
|
||||
extern String productId; // 产品ID
|
||||
extern float rssi; // 信号强度(信号极好4格[-55— 0],信号好3格[-70— -55],信号一般2格[-85— -70],信号差1格[-100— -85])
|
||||
extern float firmwareVersion; // 固件版本
|
||||
extern float latitude; // 设备精度
|
||||
extern float longitude; // 设备维度
|
||||
extern char *wifiSsid; // WIFI的SSID
|
||||
extern char *wifiPwd; // WIFI的密码
|
||||
extern char *mqttHost; // Mqtt消息服务器地址
|
||||
extern int mqttPort; // Mqtt消息服务器端口
|
||||
extern char *mqttUserName; // Mqtt消息服务器账号
|
||||
extern char *mqttPwd; // Mqtt消息服务器密码
|
||||
extern char mqttSecret[17]; // Mqtt秘钥,16位
|
||||
extern char wumei_iv[17]; // AES加密偏移量,固定值16位
|
||||
extern String authCode; // 产品授权码,产品未启用时为空字符串
|
||||
extern String ntpServer; // NTP服务地址,用于获取当前时间
|
||||
extern int monitorCount; // 发布监测数据的最大次数
|
||||
extern long monitorInterval; // 发布监测数据的间隔,默认1000毫秒
|
||||
|
||||
// 连接WIFI
|
||||
void connectWifi();
|
||||
// 随机生成监测值
|
||||
String randomPropertyData();
|
||||
//打印提示信息
|
||||
void printMsg(String tips);
|
||||
// 控制指示灯闪烁
|
||||
void blink();
|
||||
|
||||
#endif
|
||||
250
sdk/Arduino/WumeiArduino/Mqtt.cpp
Normal file
250
sdk/Arduino/WumeiArduino/Mqtt.cpp
Normal file
@@ -0,0 +1,250 @@
|
||||
/***********************************************************
|
||||
* function: 设备交互
|
||||
* board: esp8266 core for arduino v3.0.2
|
||||
* library: PubSubClient2.8.0 & ArduinoJson6.19.1
|
||||
* source: https://github.com/kerwincui/wumei-smart
|
||||
***********************************************************/
|
||||
|
||||
#include "Mqtt.h"
|
||||
|
||||
// 订阅的主题
|
||||
String prefix = "/" + productId + "/" + 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";
|
||||
// 发布的主题
|
||||
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 processProperty(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"];
|
||||
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"];
|
||||
}
|
||||
}
|
||||
|
||||
// 1.发布设备信息
|
||||
void publishInfo()
|
||||
{
|
||||
StaticJsonDocument<256> doc;
|
||||
doc["rssi"] = WiFi.RSSI();
|
||||
doc["firmwareVersion"] = firmwareVersion;
|
||||
doc["status"] = 3; // (1-未激活,2-禁用,3-在线,4-离线)
|
||||
doc["userId"] = (String)userId;
|
||||
doc["longitude"] = longitude; //经度 可选
|
||||
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";
|
||||
|
||||
printMsg("发布设备信息:");
|
||||
serializeJson(doc, Serial);
|
||||
String output;
|
||||
serializeJson(doc, output);
|
||||
mqttClient.publish(pInfoTopic.c_str(), output.c_str());
|
||||
}
|
||||
|
||||
// 2.发布时钟同步信,用于获取当前时间(可选)
|
||||
void publishNtp()
|
||||
{
|
||||
StaticJsonDocument<128> doc;
|
||||
doc["deviceSendTime"] = millis();
|
||||
|
||||
printMsg("发布NTP信息:");
|
||||
serializeJson(doc, Serial);
|
||||
String output;
|
||||
serializeJson(doc, output);
|
||||
mqttClient.publish(pNtpTopic.c_str(), output.c_str());
|
||||
}
|
||||
|
||||
// 3.发布属性
|
||||
void publishProperty(String msg)
|
||||
{
|
||||
printMsg("发布属性:" + msg);
|
||||
mqttClient.publish(pPropertyTopic.c_str(), msg.c_str());
|
||||
}
|
||||
|
||||
// 4.发布功能
|
||||
void publishFunction(String msg)
|
||||
{
|
||||
printMsg("发布功能:" + msg);
|
||||
mqttClient.publish(pFunctionTopic.c_str(), msg.c_str());
|
||||
}
|
||||
|
||||
// 5.发布事件
|
||||
void publishEvent()
|
||||
{
|
||||
// 匹配云端的事件
|
||||
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);
|
||||
mqttClient.publish(pEventTopic.c_str(), output.c_str());
|
||||
}
|
||||
|
||||
// 6.发布实时监测数据
|
||||
void publishMonitor()
|
||||
{
|
||||
String msg=randomPropertyData();
|
||||
// 发布为实时监测数据,不会存储
|
||||
printMsg("发布实时监测数据:"+msg);
|
||||
mqttClient.publish(pMonitorTopic.c_str(), msg.c_str());
|
||||
}
|
||||
55
sdk/Arduino/WumeiArduino/Mqtt.h
Normal file
55
sdk/Arduino/WumeiArduino/Mqtt.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/***********************************************************
|
||||
* function: 设备交互
|
||||
* board: esp8266 core for arduino v3.0.2
|
||||
* library: PubSubClient2.8.0 & ArduinoJson6.19.1
|
||||
* source: https://github.com/kerwincui/wumei-smart
|
||||
***********************************************************/
|
||||
|
||||
#ifndef _MQTT_H
|
||||
#define _MQTT_H
|
||||
|
||||
#include "Common.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <Ethernet.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
#include <PubSubClient.h> // 版本2.8.0
|
||||
#include <ArduinoJson.h> // 版本6.19.1
|
||||
|
||||
// 订阅的主题
|
||||
extern String sInfoTopic; // 订阅设备信息
|
||||
extern String sOtaTopic; // 订阅OTA升级
|
||||
extern String sNtpTopic; // 订阅NTP时间
|
||||
extern String sPropertyTopic; // 订阅属性
|
||||
extern String sFunctionTopic; // 订阅功能
|
||||
extern String sPropertyOnline; // 订阅属性-在线模式
|
||||
extern String sFunctionOnline; // 订阅功能-在线模式
|
||||
extern String sMonitorTopic; // 订阅实时监测
|
||||
// 发布的主题
|
||||
extern String pInfoTopic; // 发布设备信息
|
||||
extern String pNtpTopic; // 发布NTP时间
|
||||
extern String pPropertyTopic; // 发布属性
|
||||
extern String pFunctionTopic; // 发布功能
|
||||
extern String pMonitorTopic; // 发布实时监测数据
|
||||
extern String pEventTopic; // 发布事件
|
||||
|
||||
// 发布设备信息
|
||||
void publishInfo();
|
||||
// 发布时钟同步信息
|
||||
void publishNtp();
|
||||
// 发布事件
|
||||
void publishEvent();
|
||||
// 发布实时监测数据
|
||||
void publishMonitor();
|
||||
// 发布属性
|
||||
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
|
||||
93
sdk/Arduino/WumeiArduino/WumeiArduino.ino
Normal file
93
sdk/Arduino/WumeiArduino/WumeiArduino.ino
Normal file
@@ -0,0 +1,93 @@
|
||||
/***********************************************************
|
||||
* function: 程序入口
|
||||
* board: esp8266 core for arduino v3.0.2
|
||||
* library: PubSubClient2.8.0 & ArduinoJson6.19.1
|
||||
* source: https://github.com/kerwincui/wumei-smart
|
||||
***********************************************************/
|
||||
|
||||
#include "Common.h"
|
||||
#include "Auth.h"
|
||||
#include "Mqtt.h"
|
||||
|
||||
long lastMqttConn; // 上次mqtt连接时间
|
||||
long lastPublishMonitor; // 上次发布监测数据时间
|
||||
long lastPublishSimulateData; // 上次发布测试数据时间
|
||||
|
||||
/**
|
||||
* 启动
|
||||
*/
|
||||
void setup()
|
||||
{
|
||||
//打开串行端口:
|
||||
Serial.begin(115200);
|
||||
printMsg("wumei smart device starting...");
|
||||
// 连接Wifi
|
||||
connectWifi();
|
||||
// 连接Mqtt
|
||||
connectMqtt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环执行
|
||||
*/
|
||||
void loop()
|
||||
{
|
||||
// Wifi重连
|
||||
wifiReconnectionClient();
|
||||
// 发布实时监测数据
|
||||
publicMonitorClient();
|
||||
// 发布模拟数据,测试用
|
||||
publishSimulateDataClient();
|
||||
}
|
||||
|
||||
/*
|
||||
* Wifi掉线重连
|
||||
*/
|
||||
void wifiReconnectionClient()
|
||||
{
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
connectWifi();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 发布实时监测数据(非阻塞、间隔默认1秒)
|
||||
*/
|
||||
void publicMonitorClient()
|
||||
{
|
||||
if (WiFi.status() == WL_CONNECTED && monitorCount > 0)
|
||||
{
|
||||
long now = millis();
|
||||
if (now - lastPublishMonitor > monitorInterval)
|
||||
{
|
||||
lastPublishMonitor = now;
|
||||
monitorCount--;
|
||||
publishMonitor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 发布模拟数据(非阻塞、仅用于测试,间隔60秒)
|
||||
*/
|
||||
void publishSimulateDataClient()
|
||||
{
|
||||
if (WiFi.status() == WL_CONNECTED)
|
||||
{
|
||||
long now = millis();
|
||||
if (now - lastPublishSimulateData > 60000)
|
||||
{
|
||||
lastPublishSimulateData = now;
|
||||
printMsg("执行定时上报");
|
||||
// 发布事件
|
||||
publishEvent();
|
||||
// 发布时钟同步
|
||||
publishNtp();
|
||||
|
||||
// 发布属性(监测值)
|
||||
String msg = randomPropertyData();
|
||||
publishProperty(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user