2023-01-07 10:48:36 +03:00

266 lines
7.8 KiB
C++

#include "ArduinoJson.h"
#include "ArduinoOTA.h"
#include "ESPAsyncWebServer.h"
#include "ZHNetwork.h"
#include "ZHConfig.h"
void onConfirmReceiving(const uint8_t *target, const bool status);
void loadConfig(void);
void saveConfig(void);
void setupWebServer(void);
void sendSensorConfigMessage(void);
void sendBatteryConfigMessage(void);
void sendAttributesMessage(void);
const String firmware{"1.0"};
String espnowNetName{"DEFAULT"};
String deviceSensorName{"ESP-NOW window sensor"};
uint8_t deviceSensorClass{HABSDC_WINDOW};
String deviceBatteryName{"ESP-NOW window sensor battery"};
char receivedBytes[128]{0};
byte counter{0};
byte messageLenght{0};
bool dataReceiving{false};
bool dataReceived{false};
bool semaphore{false};
esp_now_payload_data_t outgoingData{ENDT_SENSOR, ENPT_STATE};
StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
char buffer[sizeof(esp_now_payload_data_t::message)]{0};
char temp[sizeof(esp_now_payload_data_t)]{0};
const char initialMessage[] = {0x55, 0xAA, 0x00, 0x01, 0x00, 0x00, 0x00};
const char connectedMessage[] = {0x55, 0xAA, 0x00, 0x02, 0x00, 0x01, 0x04, 0x06};
const char settingMessage[] = {0x55, 0xAA, 0x00, 0x03, 0x00, 0x00, 0x02};
const char confirmationMessage[] = {0x55, 0xAA, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08};
ZHNetwork myNet;
AsyncWebServer webServer(80);
void setup()
{
Serial.begin(9600);
SPIFFS.begin();
loadConfig();
myNet.begin(espnowNetName.c_str());
myNet.setOnConfirmReceivingCallback(onConfirmReceiving);
sendSensorConfigMessage();
sendBatteryConfigMessage();
sendAttributesMessage();
Serial.write(initialMessage, sizeof(initialMessage));
Serial.flush();
}
void loop()
{
if (Serial.available() > 0 && !dataReceived)
{
char receivedByte[1];
Serial.readBytes(receivedByte, 1);
if (receivedByte[0] == 0x55)
{
dataReceiving = true;
receivedBytes[counter++] = receivedByte[0];
return;
}
if (dataReceiving)
{
if (counter == 5)
messageLenght = 6 + int(receivedByte[0]);
if (counter == messageLenght)
{
receivedBytes[counter] = receivedByte[0];
counter = 0;
dataReceiving = false;
dataReceived = true;
return;
}
receivedBytes[counter++] = receivedByte[0];
}
}
if (dataReceived)
{
if (receivedBytes[3] == 0x01)
{
Serial.write(connectedMessage, sizeof(connectedMessage));
Serial.flush();
dataReceived = false;
}
if (receivedBytes[3] == 0x02)
dataReceived = false;
if (receivedBytes[3] == 0x03)
{
Serial.write(settingMessage, sizeof(settingMessage));
Serial.flush();
Serial.end();
dataReceived = false;
WiFi.softAP(("ESP-NOW Window " + myNet.getNodeMac()).c_str(), "12345678", 1, 0);
setupWebServer();
ArduinoOTA.begin();
}
if (receivedBytes[3] == 0x08)
{
if (receivedBytes[7] == 0x01)
{
if (receivedBytes[17] == 0x02)
json["battery"] = "HIGH";
if (receivedBytes[17] == 0x01)
json["battery"] = "MID";
if (receivedBytes[17] == 0x00)
json["battery"] = "LOW";
dataReceived = false;
Serial.write(confirmationMessage, sizeof(confirmationMessage));
Serial.flush();
}
if (receivedBytes[7] == 0x02)
{
if (receivedBytes[17] == 0x01)
json["state"] = "OPEN";
if (receivedBytes[17] == 0x00)
json["state"] = "CLOSED";
dataReceived = false;
serializeJsonPretty(json, buffer);
memcpy(outgoingData.message, buffer, sizeof(esp_now_payload_data_t::message));
memcpy(temp, &outgoingData, sizeof(esp_now_payload_data_t));
myNet.sendBroadcastMessage(temp);
semaphore = true;
}
}
}
myNet.maintenance();
ArduinoOTA.handle();
}
void onConfirmReceiving(const uint8_t *target, const bool status)
{
if (semaphore)
{
Serial.write(confirmationMessage, sizeof(confirmationMessage));
Serial.flush();
ESP.deepSleep(0);
}
}
void loadConfig()
{
if (!SPIFFS.exists("/config.json"))
saveConfig();
File file = SPIFFS.open("/config.json", "r");
String jsonFile = file.readString();
StaticJsonDocument<512> json;
deserializeJson(json, jsonFile);
espnowNetName = json["espnowNetName"].as<String>();
deviceSensorName = json["deviceSensorName"].as<String>();
deviceBatteryName = json["deviceBatteryName"].as<String>();
deviceSensorClass = json["deviceSensorClass"];
file.close();
}
void saveConfig()
{
StaticJsonDocument<512> json;
json["firmware"] = firmware;
json["espnowNetName"] = espnowNetName;
json["deviceSensorName"] = deviceSensorName;
json["deviceBatteryName"] = deviceBatteryName;
json["deviceSensorClass"] = deviceSensorClass;
json["system"] = "empty";
File file = SPIFFS.open("/config.json", "w");
serializeJsonPretty(json, file);
file.close();
}
void setupWebServer()
{
webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(SPIFFS, "/index.htm"); });
webServer.on("/setting", HTTP_GET, [](AsyncWebServerRequest *request)
{
deviceSensorName = request->getParam("deviceSensorName")->value();
deviceBatteryName = request->getParam("deviceBatteryName")->value();
deviceSensorClass = request->getParam("deviceSensorClass")->value().toInt();
espnowNetName = request->getParam("espnowNetName")->value();
request->send(200);
saveConfig(); });
webServer.on("/restart", HTTP_GET, [](AsyncWebServerRequest *request)
{
request->send(200);
ESP.restart(); });
webServer.onNotFound([](AsyncWebServerRequest *request)
{
if (SPIFFS.exists(request->url()))
request->send(SPIFFS, request->url());
else
{
request->send(404, "text/plain", "File Not Found");
} });
webServer.begin();
}
void sendSensorConfigMessage()
{
esp_now_payload_data_t outgoingData{ENDT_SENSOR, ENPT_CONFIG};
StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
json["name"] = deviceSensorName;
json["unit"] = 1;
json["type"] = HACT_BINARY_SENSOR;
json["class"] = deviceSensorClass;
json["payload_on"] = "OPEN";
json["payload_off"] = "CLOSED";
char buffer[sizeof(esp_now_payload_data_t::message)]{0};
serializeJsonPretty(json, buffer);
memcpy(outgoingData.message, buffer, sizeof(esp_now_payload_data_t::message));
char temp[sizeof(esp_now_payload_data_t)]{0};
memcpy(&temp, &outgoingData, sizeof(esp_now_payload_data_t));
myNet.sendBroadcastMessage(temp);
}
void sendBatteryConfigMessage()
{
esp_now_payload_data_t outgoingData{ENDT_SENSOR, ENPT_CONFIG};
StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
json["name"] = deviceBatteryName;
json["unit"] = 2;
json["type"] = HACT_BINARY_SENSOR;
json["class"] = HABSDC_BATTERY;
json["payload_on"] = "MID";
json["payload_off"] = "HIGH";
char buffer[sizeof(esp_now_payload_data_t::message)]{0};
serializeJsonPretty(json, buffer);
memcpy(outgoingData.message, buffer, sizeof(esp_now_payload_data_t::message));
char temp[sizeof(esp_now_payload_data_t)]{0};
memcpy(&temp, &outgoingData, sizeof(esp_now_payload_data_t));
myNet.sendBroadcastMessage(temp);
}
void sendAttributesMessage()
{
esp_now_payload_data_t outgoingData{ENDT_SENSOR, ENPT_ATTRIBUTES};
StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
json["Type"] = "ESP-NOW Window Sensor";
json["MCU"] = "ESP8266";
json["MAC"] = myNet.getNodeMac();
json["Firmware"] = firmware;
json["Library"] = myNet.getFirmwareVersion();
char buffer[sizeof(esp_now_payload_data_t::message)]{0};
serializeJsonPretty(json, buffer);
memcpy(outgoingData.message, buffer, sizeof(esp_now_payload_data_t::message));
char temp[sizeof(esp_now_payload_data_t)]{0};
memcpy(temp, &outgoingData, sizeof(esp_now_payload_data_t));
myNet.sendBroadcastMessage(temp);
}