commit cabf29dd5133c8ce340222c76ff10509e0599f3f Author: 如意 彭 <2417589739@qq.com> Date: Mon Aug 15 10:31:30 2022 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/.vscode/arduino.json b/.vscode/arduino.json new file mode 100644 index 0000000..9dd1002 --- /dev/null +++ b/.vscode/arduino.json @@ -0,0 +1,6 @@ +{ + "configuration": "FlashFreq=80,UploadSpeed=115200,DebugLevel=none", + "board": "esp32:esp32:esp32doit-devkit-v1", + "port": "COM9", + "sketch": "d:\\HBL\\Arduino\\test.ino" +} \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..38680ca --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,13 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "PlatformIO", + "task": "Check", + "problemMatcher": [ + "$platformio" + ], + "label": "PlatformIO: Check" + } + ] +} \ No newline at end of file diff --git a/Image/Esp32.png b/Image/Esp32.png new file mode 100644 index 0000000..795a57f Binary files /dev/null and b/Image/Esp32.png differ diff --git a/include/Delay.h b/include/Delay.h new file mode 100644 index 0000000..b89f3d7 --- /dev/null +++ b/include/Delay.h @@ -0,0 +1,22 @@ +#ifndef Delay_h +#define Delay_h + +#include +#include +#include + +class Delay +{ +private: + time_t start = 0, end = 0; + float cost = 0; + bool flag = false; + bool EN; + +public: + Delay(); + ~Delay(); + bool Start(bool IN, int PT); +}; + +#endif diff --git a/include/ElectricityDevice.h b/include/ElectricityDevice.h new file mode 100644 index 0000000..3dafdb1 --- /dev/null +++ b/include/ElectricityDevice.h @@ -0,0 +1,25 @@ +#include +#include "ModbusRtu.h" +#include "MqttHelper.h" +#include "Json.h" +#include "Global.h" + +/** + * @brief 电力设备 + * + */ +class ElectricityDevice +{ +private: + const byte interruptPin = 21; + + +public: + ElectricityDevice(/* args */); + ~ElectricityDevice(); + + void Init(); + void Start(); +}; + +extern ElectricityDevice _electricityDevice; diff --git a/include/Global.h b/include/Global.h new file mode 100644 index 0000000..5e81888 --- /dev/null +++ b/include/Global.h @@ -0,0 +1,19 @@ +#define AISLE 8 //采集设备通道数 +#ifndef _GLOBAL_H +#define _GLOBAL_H +struct DeviceData +{ + float Voltage; //电压 + float Current; //电流 + float Power; //功率 + float Energy; //电能 +}; + +extern struct DeviceData objDeviceData; + +extern float Voltage; + +extern float Current[AISLE]; + +extern DeviceData deviceModel[AISLE]; +#endif \ No newline at end of file diff --git a/include/Json.h b/include/Json.h new file mode 100644 index 0000000..6423df6 --- /dev/null +++ b/include/Json.h @@ -0,0 +1,37 @@ + +#ifndef Json_h +#define Json_h + +#include +#include "Global.h" + +class Json +{ +private: +public: + Json(/* args */); + ~Json(); + + /** + * @brief 设备状态Json数据上报 + * + */ + String StatusDataReport(); + + /** + * @brief 电能数据josn封装 + * + * @return String + */ + String PowerHarvesting(); + + /** + * @brief 解析获取到的电能数据 + * + * @param str + */ + void ParseJson(String str); +}; + +extern Json myJson; +#endif \ No newline at end of file diff --git a/include/MainDevice.h b/include/MainDevice.h new file mode 100644 index 0000000..5b28670 --- /dev/null +++ b/include/MainDevice.h @@ -0,0 +1,30 @@ +#include +#include "ModbusRtu.h" +#include "MqttHelper.h" +#include "Json.h" +#include "Global.h" +#include +#include +#include + +#define MAXITEMS 1000 +#define MAXMEMORY 1000 + +/** + * @brief 主设备 + * + */ +class MainDevice +{ +private: + TaskHandle_t MqttTest; + +public: + MainDevice(/* args */); + ~MainDevice(); + + void Init(); + void Start(); +}; + +extern MainDevice _mainDevice; diff --git a/include/ModbusRtu.h b/include/ModbusRtu.h new file mode 100644 index 0000000..f9b1ce1 --- /dev/null +++ b/include/ModbusRtu.h @@ -0,0 +1,31 @@ +#ifndef ModbusRtu_h +#define ModbusRtu_h + +#include +#include +#include "VoltageDevice.h" +#include +#include "Global.h" + +#define RE 22 +#define DE 23 +#define Status 2 +// #define AISLE 8 //采集设备通道数 + +class ModbusRtu +{ +private: + ModbusMaster myMaster; + +public: + ModbusRtu(/* args */); + ~ModbusRtu(); + + void Init(); + void Start(); + void Test(); +}; + +extern ModbusRtu myRtu; + +#endif \ No newline at end of file diff --git a/include/MqttHelper.h b/include/MqttHelper.h new file mode 100644 index 0000000..0c58254 --- /dev/null +++ b/include/MqttHelper.h @@ -0,0 +1,44 @@ +#ifndef MqttHelper_h +#define MqttHelper_h + +#include +#include +#include +#include + + +class MqttHelper +{ +private: + const char *id = "HBL1"; + const char *psw = "bpa.1qaz@WSX"; + const char *mqttServer = "10.2.1.21"; + const int mqttPort = 1883; //服务器TCP协议的端口号 + const char *mqttUser = "emqx_u_block"; //登录服务器所需的用户名 + const char *mqttPsw = "emqx_p_admin8765490789"; //密码 + const char *HeartbeatTopic = "UP/ENERGY_POWER/BUSINESS/0"; + + // const char *id = "pert"; + // const char *psw = "12345678"; + // const char *mqttServer = "111.9.47.105"; + // const int mqttPort = 18883; //服务器TCP协议的端口号 + // const char *mqttUser = "admin"; //登录服务器所需的用户名 + // const char *mqttPsw = "admin8765490789"; //密码 + // const char *HeartbeatTopic = "UP/ENERGY_POWER/BUSINESS/0"; + String clientId; + +public: + MqttHelper(/* args */); + ~MqttHelper(); + + + + void Init(); + void Loop(); + void publish(String message); + void ReConnect(); +}; + +extern MqttHelper _mqttHelper; + +#endif diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/include/VoltageDevice.h b/include/VoltageDevice.h new file mode 100644 index 0000000..95d3f37 --- /dev/null +++ b/include/VoltageDevice.h @@ -0,0 +1,33 @@ +#ifndef VoltageDevice_h +#define VoltageDevice_h + +#include +#include "Delay.h" + +class VoltageDevice +{ +private: + byte data[25]; + +public: + VoltageDevice(/* args */); + ~VoltageDevice(); + + /** + *@brief 通过串口读取设备数据 + */ + bool ReadData(); + + /** + * @brief 字节数组转换成浮点数 + * + * @param len 字节长度 + * @param Index 起始字节索引 + * @param bl 转换倍率 + * @return float + */ + float DataConvert(int len, int Index, int bl = 1); +}; + +extern VoltageDevice MyVd; +#endif \ No newline at end of file diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..6ab4fa4 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,21 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32doit-devkit-v1] +platform = espressif32 +board = esp32doit-devkit-v1 +framework = arduino +lib_ldf_mode = deep+ +lib_deps = + 4-20ma/ModbusMaster@^2.0.1 + khoih-prog/ESPAsync_WiFiManager@^1.12.2 + knolleary/PubSubClient@^2.8 + einararnason/ArduinoQueue@^1.2.5 + 256dpi/MQTT@^2.5.0 diff --git a/src/Delay.cpp b/src/Delay.cpp new file mode 100644 index 0000000..c353fc0 --- /dev/null +++ b/src/Delay.cpp @@ -0,0 +1,38 @@ +#include "Delay.h" + +Delay::Delay() +{ +} + +Delay::~Delay() +{ +} + +/** + * @brief 定时器 + * + * @param IN 定时器触发条件 + * @param PT 定时器时间设置 单位s + * @return true 到达定时时间 + * @return false 未到定时时间 + */ +bool Delay::Start(bool IN, int PT) +{ + EN = IN; + if (EN && cost < PT) + { + if (!flag) + { + time(&start); + flag = true; + } + time(&end); + cost = difftime(end, start); + } + else + { + cost = 0; + flag = false; + } + return cost >= PT; +} \ No newline at end of file diff --git a/src/ElectricityDevice.cpp b/src/ElectricityDevice.cpp new file mode 100644 index 0000000..0d7b001 --- /dev/null +++ b/src/ElectricityDevice.cpp @@ -0,0 +1,49 @@ +#include "ElectricityDevice.h" + +ElectricityDevice::ElectricityDevice(/* args */) +{ +} + +ElectricityDevice::~ElectricityDevice() +{ +} + +bool IsSend = false; + +void DataInit() +{ + for (size_t i = 0; i < AISLE; i++) + { + deviceModel[i].Current = 0.0; + deviceModel[i].Energy = 0.0; + deviceModel[i].Power = 0.0; + deviceModel[i].Voltage = 0.0; + Current[i] = 0; + } +} + +void blink() +{ + IsSend = digitalRead(21) == 1; +} + +void ElectricityDevice::Init() +{ + Serial.begin(115200); // Lora 模块通讯串口 + pinMode(interruptPin, INPUT_PULLDOWN); + attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE); + myRtu.Init(); + DataInit(); +} + +void ElectricityDevice::Start() +{ + myRtu.Start(); + IsSend = true; + String SendData = "A" + myJson.PowerHarvesting() + "B"; + Serial.print(SendData); + while (IsSend) + delay(1); +} + +ElectricityDevice _electricityDevice; \ No newline at end of file diff --git a/src/Global.cpp b/src/Global.cpp new file mode 100644 index 0000000..b37fcfb --- /dev/null +++ b/src/Global.cpp @@ -0,0 +1,5 @@ +#include "Global.h" +DeviceData deviceModel[AISLE]; +DeviceData objDeviceData; +float Voltage = 0.0; +float Current[AISLE]; \ No newline at end of file diff --git a/src/Json.cpp b/src/Json.cpp new file mode 100644 index 0000000..dfd7ffb --- /dev/null +++ b/src/Json.cpp @@ -0,0 +1,84 @@ +#include "Json.h" +#include + +Json::Json(/* args */) +{ +} + +Json::~Json() {} + +// json 数据封装 带数组数据 +String Json::StatusDataReport() +{ + cJSON *mainJson = cJSON_CreateObject(); //创建主体对象 + cJSON *message = cJSON_CreateObject(); //创建消息体对象 + cJSON *arrayData = cJSON_CreateArray(); //创建数组对象 + + cJSON_AddStringToObject(mainJson, "MessageId", "256"); + cJSON_AddStringToObject(mainJson, "MessageVersion", "24"); + cJSON_AddStringToObject(mainJson, "ClientId", "1"); + cJSON_AddStringToObject(mainJson, "ClientType", "20"); + cJSON_AddStringToObject(mainJson, "Timestamp", __TIME__); + cJSON_AddStringToObject(message, "Timestamp", "0"); + + for (size_t i = 0; i < AISLE; i++) + { + cJSON *Data = cJSON_CreateObject(); //创建消息体里面的数据对象 + cJSON_AddItemToArray(arrayData, Data); + cJSON_AddStringToObject(Data, "Channel", String(i + 1).c_str()); + cJSON_AddStringToObject(Data, "Current", String(Current[i]).c_str()); + cJSON_AddStringToObject(Data, "Voltage", String(Voltage).c_str()); + cJSON_AddStringToObject(Data, "Power", String(Current[i] * Voltage).c_str()); + cJSON_AddStringToObject(Data, "Energy", String(deviceModel[i].Energy).c_str()); + } + + cJSON_AddItemToObject(message, "Datas", arrayData); + cJSON_AddItemToObject(mainJson, "Message", message); + char *date = cJSON_Print(mainJson); + String jsondata(date); + cJSON_free((void *)date); // 释放cJSON_Print ()分配出来的内存空间 + cJSON_Delete(mainJson); // 释放cJSON_CreateObject ()分配出来的内存空间 + return jsondata; +} + +String Json::PowerHarvesting() +{ + cJSON *mainJson = cJSON_CreateObject(); + cJSON_AddStringToObject(mainJson, "DeviceType", "Electricity"); + cJSON_AddStringToObject(mainJson, "Voltage", String(Voltage).c_str()); + for (size_t i = 0; i < AISLE; i++) + { + cJSON_AddStringToObject(mainJson, ("Current" + String(i + 1)).c_str(), String(Current[i]).c_str()); + } + char *date = cJSON_Print(mainJson); + String jsondata(date); + cJSON_free((void *)date); // 释放cJSON_Print ()分配出来的内存空间 + cJSON_Delete(mainJson); // 释放cJSON_CreateObject ()分配出来的内存空间 + return jsondata; +} + +void Json::ParseJson(String str) +{ + cJSON *mainJson = cJSON_Parse(str.c_str()); + if (mainJson != NULL) + { + String DeviceType = cJSON_GetObjectItem(mainJson, "DeviceType")->valuestring; + if (DeviceType == "Electricity") //电力设备 + { + Voltage = String(cJSON_GetObjectItem(mainJson, "Voltage")->valuestring).toFloat(); + for (size_t i = 0; i < AISLE; i++) + { + String ResultValue(cJSON_GetObjectItem(mainJson, ("Current" + String(i + 1)).c_str())->valuestring); + Current[i] = ResultValue.toFloat(); + } + } + else if (DeviceType == "Gas") //燃气设备 + { + } + else if (DeviceType == "Water") //用水设备 + { + } + } +} + +Json myJson; diff --git a/src/JsonDemo.json b/src/JsonDemo.json new file mode 100644 index 0000000..37da9db --- /dev/null +++ b/src/JsonDemo.json @@ -0,0 +1,19 @@ +{ + "MessageId": 257, + "MessageVersion": 24, + "ClientId": 1, + "ClientType": 20, + "Timestamp": "2022-08-03T17:06:31.3024375+08:00", + "Message": { + "Timestamp": 0, + "Datas": [ + { + "Channel": 0, + "Current": 0.0, + "Voltage": 0.0, + "Power": 0.0, + "Energy": 0.0 + } + ] + } +} \ No newline at end of file diff --git a/src/MainDevice.cpp b/src/MainDevice.cpp new file mode 100644 index 0000000..40dd9f0 --- /dev/null +++ b/src/MainDevice.cpp @@ -0,0 +1,69 @@ +#include "MainDevice.h" + +MainDevice::MainDevice(/* args */) +{ +} + +MainDevice::~MainDevice() +{ +} + +ArduinoQueue MyQueue(MAXITEMS, MAXMEMORY); + +void TaskMqttPublish(void *pvParameters) +{ + while (true) + { + while (MyQueue.itemCount() > 0) + { + String res = MyQueue.dequeue(); + myJson.ParseJson(res); + _mqttHelper.publish(myJson.StatusDataReport()); + _mqttHelper.Loop(); + vTaskDelay(1); + } + _mqttHelper.Loop(); + vTaskDelay(10); + } +} + +void MainDevice::Init() +{ + Serial2.begin(115200); // lora 模块通讯串口 + Serial.begin(115200); //消息日志串口 + pinMode(2, OUTPUT); + _mqttHelper.Init(); + digitalWrite(2, 1); + xTaskCreatePinnedToCore(TaskMqttPublish, "MqttHelt", 4096, NULL, 1, &MqttTest, 0); +} + +void MainDevice::Start() +{ + digitalWrite(2, 0); + String res; + Delay mydelay; + bool StartRevice = false; + while (true) + { + if (Serial2.available() > 0) + { + char resRead = (char)Serial2.read(); + if (StartRevice && resRead == 'B') + { + MyQueue.enqueue(res); + digitalWrite(2, 1); + return; + } + if (StartRevice) + res += resRead; + if (resRead == 'A') + StartRevice = true; + } + if (mydelay.Start(true, 2)) + { + return; + } + } +} + +MainDevice _mainDevice; \ No newline at end of file diff --git a/src/ModbusRtu.cpp b/src/ModbusRtu.cpp new file mode 100644 index 0000000..9f9254b --- /dev/null +++ b/src/ModbusRtu.cpp @@ -0,0 +1,101 @@ +#include "ModbusRtu.h" + +ModbusRtu::ModbusRtu(/* args */) +{ +} + +ModbusRtu::~ModbusRtu() +{ +} + +void preTransmission() +{ + digitalWrite(RE, 1); + digitalWrite(DE, 1); +} + +void posTransmission() +{ + digitalWrite(RE, 0); + digitalWrite(DE, 0); +} + +float UshorsToFloat(uint16_t Word1, uint16_t word2) +{ + byte Udata[4]; + Udata[3] = (byte)(Word1 >> 8); + Udata[2] = (byte)(Word1); + Udata[1] = (byte)(word2 >> 8); + Udata[0] = (byte)(word2); + float f; + union change + { + float d; + unsigned char dat[4]; + } r1; + + r1.dat[0] = Udata[0]; + r1.dat[1] = Udata[1]; + r1.dat[2] = Udata[2]; + r1.dat[3] = Udata[3]; + f = r1.d; + return f; +} + +void ModbusRtu::Init() +{ + pinMode(RE, OUTPUT); + pinMode(DE, OUTPUT); + pinMode(Status, OUTPUT); + posTransmission(); + Serial2.begin(9600); //电压采集模块串口 和 电流采集模块的串口 + myMaster.begin(1, Serial2); + myMaster.preTransmission(preTransmission); + myMaster.postTransmission(posTransmission); +} + +void ModbusRtu::Start() +{ + digitalWrite(Status, 0); + preTransmission(); + bool result = MyVd.ReadData(); + if (result) + // Serial.println("电压获取成功"); + digitalWrite(Status, 1); + // else + // Serial.println("电压获取失败"); + // float Voltage = MyVd.DataConvert(2, 3, 100); //电压 + Voltage = MyVd.DataConvert(2, 3, 100); + uint8_t res = myMaster.readHoldingRegisters(32, 16); + if (res == myMaster.ku8MBSuccess) + { + // Serial.print("读取寄存器:"); + for (size_t i = 0; i < 8; i++) + { + deviceModel[i].Current = UshorsToFloat(myMaster.getResponseBuffer(i * 2), myMaster.getResponseBuffer(i * 2 + 1)); + deviceModel[i].Voltage = Voltage; + deviceModel[i].Power = deviceModel[i].Current * Voltage; + deviceModel[i].Energy = deviceModel[i].Power * 0; //电能公式 W = UIT 电压 * 电流 * 时间 + + Current[i] = deviceModel[i].Current; + + // Serial.print("电流:"); + // Serial.println(deviceModel[i].Current); + + // Serial.print("电压:"); + // Serial.println(deviceModel[i].Voltage); + + // Serial.print("功率:"); + // Serial.println(deviceModel[i].Power); + + // Serial.print("电能:"); + // Serial.println(deviceModel[i].Energy); + } + } + else + { + // Serial.println("Modbus rtu 读取失败"); + } +} + +ModbusRtu myRtu; diff --git a/src/MqttHelper.cpp b/src/MqttHelper.cpp new file mode 100644 index 0000000..925faa8 --- /dev/null +++ b/src/MqttHelper.cpp @@ -0,0 +1,158 @@ +#include "MqttHelper.h" + +WiFiClient espClient; //实例WiFiClient对象 +PubSubClient myClient(espClient); //实例PubSubClient对象,espClient做参数 + +MQTTClient client(2048); + +MqttHelper::MqttHelper(/* args */) +{ +} + +MqttHelper::~MqttHelper() +{ +} + +void callback(char *topic, byte *payload, unsigned int length) +{ + Serial.print("来自订阅的主题:"); //串口打印:来自订阅的主题: + Serial.println(topic); //串口打印订阅的主题 + Serial.print("信息:"); //串口打印:信息: + for (int i = 0; i < length; i++) //使用循环打印接收到的信息 + { + Serial.print((char)payload[i]); + } + Serial.println(); + Serial.println("-----------------------"); +} + +void MqttHelper::Init() +{ + while (WiFi.status() != WL_CONNECTED) + { //判断wifi是否连接,请确保你所连接的wifi联通了互联网 + delay(3000); + WiFi.begin(id, psw); //连接wifi + Serial.println("正在连接wifi..."); + } + Serial.println("WIFI 已连接!"); + + myClient.setServer(mqttServer, mqttPort); //设置服务器地址,端口 + myClient.setCallback(callback); //设定回调方式,当ESP32收到订阅消息时会调用此方法 + + clientId = "ESP32Client-"; + clientId += String(random(0xffff), HEX); //生成随机客户端id + + //测试MQTT连接 + client.begin(mqttServer, mqttPort, espClient); + + Serial.println("正连接至MQTT服务器..."); + while (!client.connect(clientId.c_str(), mqttUser, mqttPsw)) + { + Serial.print("."); + delay(2000); + } + Serial.println("MQTT 已连接!"); + + // while (!myClient.connected()) + // { //判断是否连接到服务器 + // Serial.println("正连接至MQTT服务器..."); + // if (myClient.connect(clientId.c_str(), mqttUser, mqttPsw)) + // { + // Serial.println("MQTT 已连接!"); + // } + // else + // { + // Serial.println("连接失败"); + // Serial.println(myClient.state()); //重连函数 + // delay(2000); + // } + // } + // myClient.subscribe("Down/ENERGY_POWER/BUSINESS/0"); //订阅名为ESP32的主题 + + Serial.println("已订阅主题,等待消息..."); +} + +void MqttHelper::ReConnect() +{ + // myClient.unsubscribe("UP/ENERGY_POWER/BUSINESS/0"); + // myClient.disconnect(); + Serial.println("开始重连"); + while (!client.connect(clientId.c_str(), mqttUser, mqttPsw)) + { + Serial.print("."); + delay(2000); + } + Serial.println("MQTT 重连成功!"); + + // while (!myClient.connected()) + // { //判断是否连接到服务器 + // Serial.println("正连接至MQTT服务器..."); + // if (myClient.connect(clientId.c_str(), mqttUser, mqttPsw)) + // { + // Serial.println("MQTT 已连接!"); + // } + // else + // { + // Serial.println("连接失败"); + // Serial.println(myClient.state()); + // delay(2000); + // } + // } + // myClient.subscribe("Down/ENERGY_POWER/BUSINESS/0"); //订阅名为ESP32的主题 + // Serial.println("已订阅主题,等待消息..."); +} + +/** + * @brief MQTT 发布数据 + * + * @param message 需要发布的数据 + * 这个库只能发布很短的消息信息,需要拆分消息发送 + */ +void MqttHelper::publish(String message) +{ + if (!client.connected()) + ReConnect(); + bool res = client.publish(HeartbeatTopic, message.c_str()); + if (res) + Serial.println("数据发布成功"); + else + Serial.println("-------------------------------数-据-发-布-失-败-------------------------------"); + + // message.trim(); + // message.replace(" ", ""); + // if (!myClient.connected()) + // ReConnect(); + // int cut = 128; //要拆分发送的实际大小 + // int json_str_len = message.length(); //总数据长度 + // if (json_str_len > cut) + // { + // //开始发送长文件参数分别为 主题,长度,是否持续 + // myClient.beginPublish(HeartbeatTopic, json_str_len, true); + // int count = json_str_len / cut; + // for (int i = 0; i < (count - 1); i++) + // { + // size_t WriteSizeof = myClient.print(message.substring(i * cut, (i * cut + cut))); + // if (WriteSizeof <= 0) + // { + // myClient.disconnect(); + // return; + // } + // } + // myClient.print(message.substring(cut * (count - 1))); + // myClient.endPublish(); //结束发送文本 + // } + // else + // { + // myClient.publish(HeartbeatTopic, message.c_str()); + // } + // Serial.println("MQTT 消息发布"); +} + +void MqttHelper::Loop() +{ + // myClient.loop(); //回旋接收函数 等待服务器返回的数据 + + client.loop(); +} + +MqttHelper _mqttHelper; diff --git a/src/VoltageDevice.cpp b/src/VoltageDevice.cpp new file mode 100644 index 0000000..186b2d1 --- /dev/null +++ b/src/VoltageDevice.cpp @@ -0,0 +1,56 @@ +#include "VoltageDevice.h" + +VoltageDevice::VoltageDevice(/* args */) +{ +} + +VoltageDevice::~VoltageDevice() +{ +} + +bool VoltageDevice::ReadData() +{ + for (size_t i = 0; i < sizeof(data); i++) + data[i] = 0; + Delay myDelay; //定时器 + bool IsRun = true; + int count = 0; + byte read[8] = {0x01, 0x03, 0x00, 0x48, 0x00, 0x0A, 0x45, 0xDB}; + Serial2.write(read, sizeof(read)); + // Serial.println("写入数据:0x01, 0x03, 0x00, 0x48, 0x00, 0x0A, 0x45, 0xDB"); + while (IsRun) + { + if (Serial2.available() > 0 && count < sizeof(data)) + { + data[count] = Serial2.read(); + count++; + } + if (count >= sizeof(data)) + return true; + if (myDelay.Start(IsRun, 2)) + return false; + } +} + +float VoltageDevice::DataConvert(int len, int Index, int bl) +{ + byte dt[len]; + int tempIndex; + for (size_t i = 0; i < len; i++) + { + tempIndex = len + Index - 1 - i; + if (tempIndex >= 0 && tempIndex < sizeof(data)) + { + dt[i] = data[len + Index - 1 - i]; + } + } + + int Temp = 0; + for (size_t i = 0; i < sizeof(dt); i++) + { + Temp += (int)(dt[i] << (i * 8)); + } + return (float)(Temp / bl); +} + +VoltageDevice MyVd; diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..5df69a9 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,27 @@ +// #include +#include "ElectricityDevice.h" +#include "MainDevice.h" + +//电力设备程序 +// void setup() +// { +// _electricityDevice.Init(); //电力设备程序 +// } + +// void loop() +// { +// _electricityDevice.Start(); //电力设备程序 +// delay(1000); +// } + +//主设备程序 +void setup() +{ + _mainDevice.Init(); //主设备程序 +} + +void loop() +{ + _mainDevice.Start(); //主设备程序 + delay(100); +} diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html