Alexey Zholtikov afaf9b5e8f Version 1.2
Added encrypting messages.
Web interface minor redesign.
Main code minor refactoring.
2023-01-22 14:03:34 +03:00

292 lines
8.4 KiB
C++

#include "ArduinoJson.h"
#include "ArduinoOTA.h"
#include "ESPAsyncWebServer.h"
#include "ZHNetwork.h"
#include "ZHConfig.h"
void onConfirmReceiving(const uint8_t *target, const uint16_t id, 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.2"};
String espnowNetName{"DEFAULT"};
String deviceName = "ESP-NOW window " + String(ESP.getChipId(), HEX);
uint8_t deviceClass{HABSDC_WINDOW};
String sensorStatus{""};
String batteryStatus{""};
char receivedBytes[128]{0};
uint8_t counter{0};
uint8_t 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 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();
json["state"] = sensorStatus;
json["battery"] = batteryStatus;
myNet.begin(espnowNetName.c_str());
// myNet.setCryptKey("VERY_LONG_CRYPT_KEY"); // If encryption is used, the key must be set same of all another ESP-NOW devices in network.
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.mode(WIFI_AP);
WiFi.softAP(("ESP-NOW window " + String(ESP.getChipId(), HEX)).c_str(), "12345678", 1, 0);
setupWebServer();
ArduinoOTA.begin();
}
if (receivedBytes[3] == 0x08)
{
if (receivedBytes[7] == 0x01)
{
if (receivedBytes[17] == 0x02)
{
json["battery"] = "HIGH";
batteryStatus = "HIGH";
}
if (receivedBytes[17] == 0x01)
{
json["battery"] = "MID";
batteryStatus = "MID";
}
if (receivedBytes[17] == 0x00)
{
json["battery"] = "LOW";
batteryStatus = "LOW";
}
dataReceived = false;
saveConfig();
serializeJsonPretty(json, outgoingData.message);
memcpy(&temp, &outgoingData, sizeof(esp_now_payload_data_t));
myNet.sendBroadcastMessage(temp);
semaphore = true;
}
if (receivedBytes[7] == 0x02)
{
if (receivedBytes[17] == 0x01)
{
json["state"] = "OPEN";
sensorStatus = "OPEN";
}
if (receivedBytes[17] == 0x00)
{
json["state"] = "CLOSED";
sensorStatus = "CLOSED";
}
dataReceived = false;
saveConfig();
serializeJsonPretty(json, outgoingData.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 uint16_t id, const bool status)
{
if (semaphore)
{
Serial.write(confirmationMessage, sizeof(confirmationMessage));
Serial.flush();
}
}
void loadConfig()
{
if (!SPIFFS.exists("/config.json"))
saveConfig();
File file = SPIFFS.open("/config.json", "r");
String jsonFile = file.readString();
StaticJsonDocument<1024> json;
deserializeJson(json, jsonFile);
espnowNetName = json["espnowNetName"].as<String>();
deviceName = json["deviceName"].as<String>();
deviceClass = json["deviceClass"];
sensorStatus = json["sensorStatus"].as<String>();
batteryStatus = json["batteryStatus"].as<String>();
file.close();
}
void saveConfig()
{
StaticJsonDocument<1024> json;
json["firmware"] = firmware;
json["espnowNetName"] = espnowNetName;
json["deviceName"] = deviceName;
json["deviceClass"] = deviceClass;
json["sensorStatus"] = sensorStatus;
json["batteryStatus"] = batteryStatus;
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)
{
deviceName = request->getParam("deviceName")->value();
deviceClass = request->getParam("deviceClass")->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"] = deviceName;
json["unit"] = 1;
json["type"] = HACT_BINARY_SENSOR;
json["class"] = deviceClass;
json["template"] = "state";
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"] = deviceName + " battery";
json["unit"] = 2;
json["type"] = HACT_BINARY_SENSOR;
json["class"] = HABSDC_BATTERY;
json["template"] = "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);
}