@@ -0,0 +1,5 @@ | |||||
.pio | |||||
.vscode/.browse.c_cpp.db* | |||||
.vscode/c_cpp_properties.json | |||||
.vscode/launch.json | |||||
.vscode/ipch |
@@ -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" | |||||
} |
@@ -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" | |||||
] | |||||
} |
@@ -0,0 +1,13 @@ | |||||
{ | |||||
"version": "2.0.0", | |||||
"tasks": [ | |||||
{ | |||||
"type": "PlatformIO", | |||||
"task": "Check", | |||||
"problemMatcher": [ | |||||
"$platformio" | |||||
], | |||||
"label": "PlatformIO: Check" | |||||
} | |||||
] | |||||
} |
@@ -0,0 +1,22 @@ | |||||
#ifndef Delay_h | |||||
#define Delay_h | |||||
#include <Arduino.h> | |||||
#include <time.h> | |||||
#include <stdio.h> | |||||
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 |
@@ -0,0 +1,25 @@ | |||||
#include <Arduino.h> | |||||
#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; |
@@ -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 |
@@ -0,0 +1,37 @@ | |||||
#ifndef Json_h | |||||
#define Json_h | |||||
#include <Arduino.h> | |||||
#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 |
@@ -0,0 +1,30 @@ | |||||
#include <Arduino.h> | |||||
#include "ModbusRtu.h" | |||||
#include "MqttHelper.h" | |||||
#include "Json.h" | |||||
#include "Global.h" | |||||
#include <ArduinoQueue.h> | |||||
#include <cJSON.h> | |||||
#include <FreeRTOS.h> | |||||
#define MAXITEMS 1000 | |||||
#define MAXMEMORY 1000 | |||||
/** | |||||
* @brief 主设备 | |||||
* | |||||
*/ | |||||
class MainDevice | |||||
{ | |||||
private: | |||||
TaskHandle_t MqttTest; | |||||
public: | |||||
MainDevice(/* args */); | |||||
~MainDevice(); | |||||
void Init(); | |||||
void Start(); | |||||
}; | |||||
extern MainDevice _mainDevice; |
@@ -0,0 +1,31 @@ | |||||
#ifndef ModbusRtu_h | |||||
#define ModbusRtu_h | |||||
#include <Arduino.h> | |||||
#include <ModbusMaster.h> | |||||
#include "VoltageDevice.h" | |||||
#include <math.h> | |||||
#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 |
@@ -0,0 +1,44 @@ | |||||
#ifndef MqttHelper_h | |||||
#define MqttHelper_h | |||||
#include <Arduino.h> | |||||
#include <WiFi.h> | |||||
#include <PubSubClient.h> | |||||
#include <MQTT.h> | |||||
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 |
@@ -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 |
@@ -0,0 +1,33 @@ | |||||
#ifndef VoltageDevice_h | |||||
#define VoltageDevice_h | |||||
#include <Arduino.h> | |||||
#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 |
@@ -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 <Foo.h> | |||||
#include <Bar.h> | |||||
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 |
@@ -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 |
@@ -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; | |||||
} |
@@ -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; |
@@ -0,0 +1,5 @@ | |||||
#include "Global.h" | |||||
DeviceData deviceModel[AISLE]; | |||||
DeviceData objDeviceData; | |||||
float Voltage = 0.0; | |||||
float Current[AISLE]; |
@@ -0,0 +1,84 @@ | |||||
#include "Json.h" | |||||
#include <cJSON.h> | |||||
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; |
@@ -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 | |||||
} | |||||
] | |||||
} | |||||
} |
@@ -0,0 +1,69 @@ | |||||
#include "MainDevice.h" | |||||
MainDevice::MainDevice(/* args */) | |||||
{ | |||||
} | |||||
MainDevice::~MainDevice() | |||||
{ | |||||
} | |||||
ArduinoQueue<String> 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; |
@@ -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; |
@@ -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; |
@@ -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; |
@@ -0,0 +1,27 @@ | |||||
// #include <Arduino.h> | |||||
#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); | |||||
} |
@@ -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 |