Compare commits

..

No commits in common. "main" and "v1.42" have entirely different histories.
main ... v1.42

4 changed files with 235 additions and 244 deletions

View File

@ -10,7 +10,7 @@ function createXmlHttpObject() {
function load() { function load() {
if (xmlHttp.readyState == 0 || xmlHttp.readyState == 4) { if (xmlHttp.readyState == 0 || xmlHttp.readyState == 4) {
xmlHttp.open('GET', '/config', true); xmlHttp.open('PUT', '/config.json', true);
xmlHttp.send(null); xmlHttp.send(null);
xmlHttp.onload = function () { xmlHttp.onload = function () {
jsonResponse = JSON.parse(xmlHttp.responseText); jsonResponse = JSON.parse(xmlHttp.responseText);
@ -52,14 +52,14 @@ function sendRequest(submit, server) {
function saveSetting(submit) { function saveSetting(submit) {
server = "/setting?ssid=" + getValue('ssid') + "&password=" + encodeURIComponent(getValue('password')) server = "/setting?ssid=" + getValue('ssid') + "&password=" + encodeURIComponent(getValue('password'))
+ "&mqttHostName=" + getValue('mqttHostName') + "&mqttHostPort=" + getValue('mqttHostPort') + "&host=" + getValue('mqttHostName') + "&port=" + getValue('mqttHostPort')
+ "&mqttUserLogin=" + getValue('mqttUserLogin') + "&mqttUserPassword=" + encodeURIComponent(getValue('mqttUserPassword')) + "&login=" + getValue('mqttUserLogin') + "&pass=" + encodeURIComponent(getValue('mqttUserPassword'))
+ "&topicPrefix=" + getValue('topicPrefix') + "&prefix=" + getValue('topicPrefix')
+ "&deviceName=" + getValue('deviceName') + "&name=" + getValue('deviceName')
+ "&espnowNetName=" + getValue('espnowNetName') + "&net=" + getValue('espnowNetName')
+ "&workMode=" + getSelectValue('workModeSelect') + "&mode=" + getSelectValue('workModeSelect')
+ "&ntpHostName=" + getValue('ntpHostName') + "&ntp=" + getValue('ntpHostName')
+ "&gmtOffset=" + getValue('gmtOffset'); + "&zone=" + getValue('gmtOffset');
sendRequest(submit, server); sendRequest(submit, server);
alert("Please restart device for changes apply."); alert("Please restart device for changes apply.");
} }

View File

@ -2,7 +2,6 @@
platform = espressif8266 platform = espressif8266
board = esp12e board = esp12e
framework = arduino framework = arduino
build_flags = -D PIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK305
board_build.filesystem = littlefs board_build.filesystem = littlefs
lib_deps = lib_deps =
https://github.com/aZholtikov/ZHNetwork https://github.com/aZholtikov/ZHNetwork
@ -17,7 +16,6 @@ lib_deps =
platform = espressif8266 platform = espressif8266
board = esp12e board = esp12e
framework = arduino framework = arduino
build_flags = -D PIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK305
board_build.filesystem = littlefs board_build.filesystem = littlefs
upload_port = 192.168.4.1 upload_port = 192.168.4.1
upload_protocol = espota upload_protocol = espota

View File

@ -4,7 +4,6 @@
#include "Ethernet.h" // https://github.com/arduino-libraries/Ethernet #include "Ethernet.h" // https://github.com/arduino-libraries/Ethernet
#include "PubSubClient.h" #include "PubSubClient.h"
#include "LittleFS.h" #include "LittleFS.h"
#include "EEPROM.h"
#include "Ticker.h" #include "Ticker.h"
#include "NTPClient.h" #include "NTPClient.h"
#include "ZHNetwork.h" #include "ZHNetwork.h"
@ -16,6 +15,13 @@
#include "ESP32SSDP.h" #include "ESP32SSDP.h"
#endif #endif
typedef enum : uint8_t
{
ESP_NOW,
ESP_NOW_WIFI,
ESP_NOW_LAN
} work_mode_t;
void onEspnowMessage(const char *data, const uint8_t *sender); void onEspnowMessage(const char *data, const uint8_t *sender);
void onMqttMessage(char *topic, byte *payload, unsigned int length); void onMqttMessage(char *topic, byte *payload, unsigned int length);
@ -36,37 +42,31 @@ void checkMqttAvailability(void);
void mqttPublish(const char *topic, const char *payload, bool retained); void mqttPublish(const char *topic, const char *payload, bool retained);
typedef enum : uint8_t const String firmware{"1.42"};
{
ESP_NOW, String espnowNetName{"DEFAULT"};
ESP_NOW_WIFI,
ESP_NOW_LAN uint8_t workMode{ESP_NOW};
} work_mode_t;
struct deviceConfig
{
#if defined(ESP8266) #if defined(ESP8266)
String deviceName = "ESP-NOW gateway " + String(ESP.getChipId(), HEX); String deviceName = "ESP-NOW gateway " + String(ESP.getChipId(), HEX);
#endif #endif
#if defined(ESP32) #if defined(ESP32)
String deviceName = "ESP-NOW gateway " + String(ESP.getEfuseMac(), HEX); String deviceName = "ESP-NOW gateway " + String(ESP.getEfuseMac(), HEX);
#endif #endif
String espnowNetName{"DEFAULT"};
uint8_t workMode{ESP_NOW};
String ssid{"SSID"}; String ssid{"SSID"};
String password{"PASSWORD"}; String password{"PASSWORD"};
String mqttHostName{"MQTT"}; String mqttHostName{"MQTT"};
uint16_t mqttHostPort{1883}; uint16_t mqttHostPort{1883};
String mqttUserLogin{""}; String mqttUserLogin{""};
String mqttUserPassword{""}; String mqttUserPassword{""};
String topicPrefix{"homeassistant"}; String topicPrefix{"homeassistant"};
const char *mqttUserID{"ESP32"};
String ntpHostName{"NTP"}; String ntpHostName{"NTP"};
uint16_t gmtOffset{10800}; uint16_t gmtOffset{10800};
} config;
const String firmware{"1.6"};
const char *mqttUserID{"ESP"};
uint8_t w5500Mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // Change it if necessary. uint8_t w5500Mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // Change it if necessary.
@ -82,8 +82,8 @@ PubSubClient mqttWifiClient(wifiClient);
WiFiUDP udpWiFiClient; WiFiUDP udpWiFiClient;
EthernetUDP udpEthClient; EthernetUDP udpEthClient;
NTPClient ntpWiFiClient(udpWiFiClient, config.ntpHostName.c_str(), config.gmtOffset); NTPClient ntpWiFiClient(udpWiFiClient, ntpHostName.c_str(), gmtOffset);
NTPClient ntpEthClient(udpEthClient, config.ntpHostName.c_str(), config.gmtOffset); NTPClient ntpEthClient(udpEthClient, ntpHostName.c_str(), gmtOffset);
Ticker mqttAvailabilityCheckTimer; Ticker mqttAvailabilityCheckTimer;
bool mqttAvailabilityCheckTimerSemaphore{true}; bool mqttAvailabilityCheckTimerSemaphore{true};
@ -109,13 +109,13 @@ void setup()
loadConfig(); loadConfig();
if (config.workMode == ESP_NOW_LAN) if (workMode == ESP_NOW_LAN)
{ {
Ethernet.init(5); Ethernet.init(5);
Ethernet.begin(w5500Mac); Ethernet.begin(w5500Mac);
} }
if (config.workMode == ESP_NOW_WIFI) if (workMode == ESP_NOW_WIFI)
{ {
#if defined(ESP8266) #if defined(ESP8266)
WiFi.setSleepMode(WIFI_NONE_SLEEP); WiFi.setSleepMode(WIFI_NONE_SLEEP);
@ -128,9 +128,9 @@ void setup()
WiFi.setAutoReconnect(true); WiFi.setAutoReconnect(true);
} }
myNet.begin(config.espnowNetName.c_str(), true); myNet.begin(espnowNetName.c_str(), true);
if (config.workMode) if (workMode)
{ {
// 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.setCryptKey("VERY_LONG_CRYPT_KEY"); // If encryption is used, the key must be set same of all another ESP-NOW devices in network.
myNet.setOnBroadcastReceivingCallback(onEspnowMessage); myNet.setOnBroadcastReceivingCallback(onEspnowMessage);
@ -144,7 +144,7 @@ void setup()
WiFi.softAP(("ESP-NOW gateway " + String(ESP.getEfuseMac(), HEX)).c_str(), "12345678"); WiFi.softAP(("ESP-NOW gateway " + String(ESP.getEfuseMac(), HEX)).c_str(), "12345678");
#endif #endif
if (config.workMode == ESP_NOW_WIFI) if (workMode == ESP_NOW_WIFI)
{ {
uint8_t scan = WiFi.scanNetworks(false, false); uint8_t scan = WiFi.scanNetworks(false, false);
String name; String name;
@ -161,24 +161,24 @@ void setup()
#if defined(ESP32) #if defined(ESP32)
WiFi.getNetworkInfo(i, name, encryption, rssi, bssid, channel); WiFi.getNetworkInfo(i, name, encryption, rssi, bssid, channel);
#endif #endif
if (name == config.ssid) if (name == ssid)
WiFi.begin(config.ssid.c_str(), config.password.c_str()); WiFi.begin(ssid.c_str(), password.c_str());
} }
} }
if (config.workMode == ESP_NOW_WIFI) if (workMode == ESP_NOW_WIFI)
{ {
ntpWiFiClient.begin(); ntpWiFiClient.begin();
mqttWifiClient.setBufferSize(2048); mqttWifiClient.setBufferSize(2048);
mqttWifiClient.setServer(config.mqttHostName.c_str(), config.mqttHostPort); mqttWifiClient.setServer(mqttHostName.c_str(), mqttHostPort);
mqttWifiClient.setCallback(onMqttMessage); mqttWifiClient.setCallback(onMqttMessage);
} }
if (config.workMode == ESP_NOW_LAN) if (workMode == ESP_NOW_LAN)
{ {
ntpEthClient.begin(); ntpEthClient.begin();
mqttEthClient.setBufferSize(2048); mqttEthClient.setBufferSize(2048);
mqttEthClient.setServer(config.mqttHostName.c_str(), config.mqttHostPort); mqttEthClient.setServer(mqttHostName.c_str(), mqttHostPort);
mqttEthClient.setCallback(onMqttMessage); mqttEthClient.setCallback(onMqttMessage);
} }
@ -193,15 +193,15 @@ void setup()
void loop() void loop()
{ {
if (mqttAvailabilityCheckTimerSemaphore)
checkMqttAvailability();
if (keepAliveMessageTimerSemaphore) if (keepAliveMessageTimerSemaphore)
sendKeepAliveMessage(); sendKeepAliveMessage();
if (attributesMessageTimerSemaphore) if (attributesMessageTimerSemaphore)
sendAttributesMessage(); sendAttributesMessage();
if (config.workMode == ESP_NOW_WIFI) if (mqttAvailabilityCheckTimerSemaphore)
checkMqttAvailability();
if (workMode == ESP_NOW_WIFI)
mqttWifiClient.loop(); mqttWifiClient.loop();
if (config.workMode == ESP_NOW_LAN) if (workMode == ESP_NOW_LAN)
mqttEthClient.loop(); mqttEthClient.loop();
myNet.maintenance(); myNet.maintenance();
ArduinoOTA.handle(); ArduinoOTA.handle();
@ -214,187 +214,180 @@ void onEspnowMessage(const char *data, const uint8_t *sender)
esp_now_payload_data_t incomingData; esp_now_payload_data_t incomingData;
memcpy(&incomingData, data, sizeof(esp_now_payload_data_t)); memcpy(&incomingData, data, sizeof(esp_now_payload_data_t));
if (incomingData.payloadsType == ENPT_ATTRIBUTES) if (incomingData.payloadsType == ENPT_ATTRIBUTES)
mqttPublish((config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/" + getValueName(incomingData.payloadsType)).c_str(), incomingData.message, true); mqttPublish((topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/" + getValueName(incomingData.payloadsType)).c_str(), incomingData.message, true);
if (incomingData.payloadsType == ENPT_KEEP_ALIVE) if (incomingData.payloadsType == ENPT_KEEP_ALIVE)
mqttPublish((config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/" + getValueName(incomingData.payloadsType)).c_str(), "online", true); mqttPublish((topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/" + getValueName(incomingData.payloadsType)).c_str(), "online", true);
if (incomingData.payloadsType == ENPT_STATE) if (incomingData.payloadsType == ENPT_STATE)
mqttPublish((config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/" + getValueName(incomingData.payloadsType)).c_str(), incomingData.message, true); mqttPublish((topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/" + getValueName(incomingData.payloadsType)).c_str(), incomingData.message, true);
if (incomingData.payloadsType == ENPT_CONFIG) if (incomingData.payloadsType == ENPT_CONFIG)
{ {
if (incomingData.deviceType == ENDT_SWITCH) if (incomingData.deviceType == ENDT_SWITCH)
{ {
esp_now_payload_data_t configData; esp_now_payload_data_t configData;
memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message)); memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
DynamicJsonDocument json(sizeof(esp_now_payload_data_t::message)); StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
deserializeJson(json, configData.message); deserializeJson(json, configData.message);
uint8_t unit = json[MCMT_DEVICE_UNIT].as<uint8_t>(); uint8_t unit = json["unit"].as<uint8_t>();
DynamicJsonDocument jsonConfig(2048); // Same as PubSubClient buffer size. StaticJsonDocument<2048> jsonConfig;
jsonConfig["platform"] = "mqtt"; jsonConfig["platform"] = "mqtt";
jsonConfig["name"] = json[MCMT_DEVICE_NAME]; jsonConfig["name"] = json["name"];
jsonConfig["unique_id"] = myNet.macToString(sender) + "-" + unit; jsonConfig["unique_id"] = myNet.macToString(sender) + "-" + unit;
jsonConfig["device_class"] = getValueName(json[MCMT_DEVICE_CLASS].as<ha_switch_device_class_t>()); jsonConfig["device_class"] = getValueName(json["class"].as<ha_switch_device_class_t>());
jsonConfig["state_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state"; jsonConfig["state_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state";
jsonConfig["value_template"] = "{{ value_json." + json[MCMT_VALUE_TEMPLATE].as<String>() + " }}"; jsonConfig["value_template"] = "{{ value_json." + json["template"].as<String>() + " }}";
jsonConfig["command_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/set"; jsonConfig["command_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/set";
jsonConfig["json_attributes_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/attributes"; jsonConfig["json_attributes_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/attributes";
jsonConfig["availability_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/status"; jsonConfig["availability_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/status";
if (json[MCMT_PAYLOAD_ON]) jsonConfig["payload_on"] = json["payload_on"];
jsonConfig["payload_on"] = json[MCMT_PAYLOAD_ON]; jsonConfig["payload_off"] = json["payload_off"];
if (json[MCMT_PAYLOAD_OFF])
jsonConfig["payload_off"] = json[MCMT_PAYLOAD_OFF];
jsonConfig["optimistic"] = "false"; jsonConfig["optimistic"] = "false";
jsonConfig["retain"] = "true"; jsonConfig["retain"] = "true";
char buffer[2048]{0}; char buffer[2048]{0};
serializeJsonPretty(jsonConfig, buffer); serializeJsonPretty(jsonConfig, buffer);
mqttPublish((config.topicPrefix + "/" + getValueName(json[MCMT_COMPONENT_TYPE].as<ha_component_type_t>()) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true); mqttPublish((topicPrefix + "/" + getValueName(json["type"].as<ha_component_type_t>()) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
} }
if (incomingData.deviceType == ENDT_LED) if (incomingData.deviceType == ENDT_LED)
{ {
esp_now_payload_data_t configData; esp_now_payload_data_t configData;
memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message)); memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
DynamicJsonDocument json(sizeof(esp_now_payload_data_t::message)); StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
deserializeJson(json, configData.message); deserializeJson(json, configData.message);
uint8_t unit = json[MCMT_DEVICE_UNIT].as<uint8_t>(); uint8_t unit = json["unit"].as<uint8_t>();
esp_now_led_type_t ledClass = json[MCMT_DEVICE_CLASS]; esp_now_led_type_t ledClass = json["class"];
DynamicJsonDocument jsonConfig(2048); // Same as PubSubClient buffer size. StaticJsonDocument<2048> jsonConfig;
jsonConfig["platform"] = "mqtt"; jsonConfig["platform"] = "mqtt";
jsonConfig["name"] = json[MCMT_DEVICE_NAME]; jsonConfig["name"] = json["name"];
jsonConfig["unique_id"] = myNet.macToString(sender) + "-" + unit; jsonConfig["unique_id"] = myNet.macToString(sender) + "-" + unit;
jsonConfig["state_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state"; jsonConfig["state_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state";
jsonConfig["state_value_template"] = "{{ value_json.state }}"; jsonConfig["state_value_template"] = "{{ value_json.state }}";
jsonConfig["command_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/set"; jsonConfig["command_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/set";
jsonConfig["brightness_state_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state"; jsonConfig["brightness_state_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state";
jsonConfig["brightness_value_template"] = "{{ value_json.brightness }}"; jsonConfig["brightness_value_template"] = "{{ value_json.brightness }}";
jsonConfig["brightness_command_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/brightness"; jsonConfig["brightness_command_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/brightness";
if (ledClass == ENLT_RGB || ledClass == ENLT_RGBW || ledClass == ENLT_RGBWW) if (ledClass == ENLT_RGB || ledClass == ENLT_RGBW || ledClass == ENLT_RGBWW)
{ {
jsonConfig["rgb_state_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state"; jsonConfig["rgb_state_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state";
jsonConfig["rgb_value_template"] = "{{ value_json.rgb | join(',') }}"; jsonConfig["rgb_value_template"] = "{{ value_json.rgb | join(',') }}";
jsonConfig["rgb_command_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/rgb"; jsonConfig["rgb_command_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/rgb";
} }
if (ledClass == ENLT_WW || ledClass == ENLT_RGBWW) if (ledClass == ENLT_WW || ledClass == ENLT_RGBWW)
{ {
jsonConfig["color_temp_state_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state"; jsonConfig["color_temp_state_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state";
jsonConfig["color_temp_value_template"] = "{{ value_json.temperature }}"; jsonConfig["color_temp_value_template"] = "{{ value_json.temperature }}";
jsonConfig["color_temp_command_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/temperature"; jsonConfig["color_temp_command_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/temperature";
} }
jsonConfig["json_attributes_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/attributes"; jsonConfig["json_attributes_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/attributes";
jsonConfig["availability_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/status"; jsonConfig["availability_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/status";
if (json[MCMT_PAYLOAD_ON]) jsonConfig["payload_on"] = json["payload_on"];
jsonConfig["payload_on"] = json[MCMT_PAYLOAD_ON]; jsonConfig["payload_off"] = json["payload_off"];
if (json[MCMT_PAYLOAD_OFF])
jsonConfig["payload_off"] = json[MCMT_PAYLOAD_OFF];
jsonConfig["optimistic"] = "false"; jsonConfig["optimistic"] = "false";
jsonConfig["retain"] = "true"; jsonConfig["retain"] = "true";
char buffer[2048]{0}; char buffer[2048]{0};
serializeJsonPretty(jsonConfig, buffer); serializeJsonPretty(jsonConfig, buffer);
mqttPublish((config.topicPrefix + "/" + getValueName(json[MCMT_COMPONENT_TYPE].as<ha_component_type_t>()) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true); mqttPublish((topicPrefix + "/" + getValueName(json["type"].as<ha_component_type_t>()) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
} }
if (incomingData.deviceType == ENDT_SENSOR) if (incomingData.deviceType == ENDT_SENSOR)
{ {
esp_now_payload_data_t configData; esp_now_payload_data_t configData;
memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message)); memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
DynamicJsonDocument json(sizeof(esp_now_payload_data_t::message)); StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
deserializeJson(json, configData.message); deserializeJson(json, configData.message);
uint8_t unit = json[MCMT_DEVICE_UNIT].as<uint8_t>(); uint8_t unit = json["unit"].as<uint8_t>();
ha_component_type_t type = json[MCMT_COMPONENT_TYPE].as<ha_component_type_t>(); ha_component_type_t type = json["type"].as<ha_component_type_t>();
DynamicJsonDocument jsonConfig(2048); // Same as PubSubClient buffer size. StaticJsonDocument<2048> jsonConfig;
jsonConfig["platform"] = "mqtt"; jsonConfig["platform"] = "mqtt";
jsonConfig["name"] = json[MCMT_DEVICE_NAME]; jsonConfig["name"] = json["name"];
jsonConfig["unique_id"] = myNet.macToString(sender) + "-" + unit; jsonConfig["unique_id"] = myNet.macToString(sender) + "-" + unit;
jsonConfig["state_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state"; jsonConfig["state_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state";
jsonConfig["value_template"] = "{{ value_json." + json[MCMT_VALUE_TEMPLATE].as<String>() + " }}"; jsonConfig["value_template"] = "{{ value_json." + json["template"].as<String>() + " }}";
jsonConfig["json_attributes_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/attributes"; jsonConfig["json_attributes_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/attributes";
jsonConfig["force_update"] = "true"; jsonConfig["force_update"] = "true";
jsonConfig["retain"] = "true"; jsonConfig["retain"] = "true";
if (type == HACT_SENSOR) if (type == HACT_SENSOR)
{ jsonConfig["device_class"] = getValueName(json["class"].as<ha_sensor_device_class_t>());
jsonConfig["device_class"] = getValueName(json[MCMT_DEVICE_CLASS].as<ha_sensor_device_class_t>());
jsonConfig["unit_of_measurement"] = json[MCMT_UNIT_OF_MEASUREMENT];
}
if (type == HACT_BINARY_SENSOR) if (type == HACT_BINARY_SENSOR)
jsonConfig["device_class"] = getValueName(json[MCMT_DEVICE_CLASS].as<ha_binary_sensor_device_class_t>()); {
if (json[MCMT_EXPIRE_AFTER]) ha_binary_sensor_device_class_t deviceClass = json["class"].as<ha_binary_sensor_device_class_t>();
jsonConfig["expire_after"] = json[MCMT_EXPIRE_AFTER]; if (deviceClass == HABSDC_BATTERY || deviceClass == HABSDC_WINDOW || deviceClass == HABSDC_DOOR)
if (json[MCMT_OFF_DELAY]) jsonConfig["payload_off"] = json["payload_off"];
jsonConfig["off_delay"] = json[MCMT_OFF_DELAY]; if (deviceClass == HABSDC_CONNECTIVITY)
if (json[MCMT_PAYLOAD_ON]) jsonConfig["expire_after"] = json["expire_after"];
jsonConfig["payload_on"] = json[MCMT_PAYLOAD_ON]; jsonConfig["device_class"] = getValueName(deviceClass);
if (json[MCMT_PAYLOAD_OFF]) jsonConfig["payload_on"] = json["payload_on"];
jsonConfig["payload_off"] = json[MCMT_PAYLOAD_OFF]; }
char buffer[2048]{0}; char buffer[2048]{0};
serializeJsonPretty(jsonConfig, buffer); serializeJsonPretty(jsonConfig, buffer);
mqttPublish((config.topicPrefix + "/" + getValueName(type) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true); mqttPublish((topicPrefix + "/" + getValueName(type) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
} }
if (incomingData.deviceType == ENDT_RF_SENSOR) if (incomingData.deviceType == ENDT_RF_SENSOR)
{ {
esp_now_payload_data_t configData; esp_now_payload_data_t configData;
memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message)); memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
DynamicJsonDocument json(sizeof(esp_now_payload_data_t::message)); StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
deserializeJson(json, configData.message); deserializeJson(json, configData.message);
uint8_t unit = json[MCMT_DEVICE_UNIT].as<uint8_t>(); uint8_t unit = json["u"].as<uint8_t>();
ha_component_type_t haComponentType = json[MCMT_COMPONENT_TYPE].as<ha_component_type_t>(); ha_component_type_t type = json["t"].as<ha_component_type_t>();
rf_sensor_type_t rfSensorType = json[MCMT_RF_SENSOR_TYPE].as<rf_sensor_type_t>(); rf_sensor_type_t rf = json["r"].as<rf_sensor_type_t>();
uint16_t rfSensorId = json[MCMT_RF_SENSOR_ID].as<uint16_t>(); uint16_t id = json["i"].as<uint16_t>();
String valueTemplate = json[MCMT_VALUE_TEMPLATE].as<String>(); String tmp = json["v"].as<String>();
DynamicJsonDocument jsonConfig(2048); // Same as PubSubClient buffer size. StaticJsonDocument<2048> jsonConfig;
jsonConfig["platform"] = "mqtt"; jsonConfig["platform"] = "mqtt";
jsonConfig["name"] = getValueName(rfSensorType) + " " + rfSensorId + " " + valueTemplate; jsonConfig["name"] = getValueName(rf) + " " + id + " " + tmp;
jsonConfig["unique_id"] = String(rfSensorId) + "-" + unit; jsonConfig["unique_id"] = String(id) + "-" + unit;
jsonConfig["state_topic"] = config.topicPrefix + "/rf_sensor/" + getValueName(rfSensorType) + "/" + rfSensorId + "/state"; jsonConfig["state_topic"] = topicPrefix + "/rf_sensor/" + getValueName(rf) + "/" + id + "/state";
jsonConfig["value_template"] = "{{ value_json." + valueTemplate + " }}"; jsonConfig["value_template"] = "{{ value_json." + tmp + " }}";
if (type == HACT_SENSOR)
{
jsonConfig["device_class"] = getValueName(json["h"].as<ha_sensor_device_class_t>());
jsonConfig["unit_of_measurement"] = json["m"];
jsonConfig["expire_after"] = json["e"];
}
if (type == HACT_BINARY_SENSOR)
{
ha_binary_sensor_device_class_t deviceClass = json["h"].as<ha_binary_sensor_device_class_t>();
if (deviceClass == HABSDC_MOISTURE)
jsonConfig["expire_after"] = json["e"];
jsonConfig["device_class"] = getValueName(deviceClass);
jsonConfig["payload_on"] = json["o"];
jsonConfig["payload_off"] = json["f"];
}
jsonConfig["force_update"] = "true"; jsonConfig["force_update"] = "true";
jsonConfig["retain"] = "true"; jsonConfig["retain"] = "true";
if (haComponentType == HACT_SENSOR)
{
jsonConfig["device_class"] = getValueName(json[MCMT_DEVICE_CLASS].as<ha_sensor_device_class_t>());
jsonConfig["unit_of_measurement"] = json[MCMT_UNIT_OF_MEASUREMENT];
}
if (haComponentType == HACT_BINARY_SENSOR)
jsonConfig["device_class"] = getValueName(json[MCMT_DEVICE_CLASS].as<ha_binary_sensor_device_class_t>());
if (json[MCMT_EXPIRE_AFTER])
jsonConfig["expire_after"] = json[MCMT_EXPIRE_AFTER];
if (json[MCMT_OFF_DELAY])
jsonConfig["off_delay"] = json[MCMT_OFF_DELAY];
if (json[MCMT_PAYLOAD_ON])
jsonConfig["payload_on"] = json[MCMT_PAYLOAD_ON];
if (json[MCMT_PAYLOAD_OFF])
jsonConfig["payload_off"] = json[MCMT_PAYLOAD_OFF];
char buffer[2048]{0}; char buffer[2048]{0};
serializeJsonPretty(jsonConfig, buffer); serializeJsonPretty(jsonConfig, buffer);
mqttPublish((config.topicPrefix + "/" + getValueName(haComponentType) + "/" + rfSensorId + "-" + unit + "/config").c_str(), buffer, true); mqttPublish((topicPrefix + "/" + getValueName(type) + "/" + id + "-" + unit + "/config").c_str(), buffer, true);
} }
if (incomingData.deviceType == ENDT_RF_GATEWAY) if (incomingData.deviceType == ENDT_RF_GATEWAY)
{ {
esp_now_payload_data_t configData; esp_now_payload_data_t configData;
memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message)); memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
DynamicJsonDocument json(sizeof(esp_now_payload_data_t::message)); StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
deserializeJson(json, configData.message); deserializeJson(json, configData.message);
uint8_t unit = json[MCMT_DEVICE_UNIT].as<uint8_t>(); uint8_t unit = json["unit"].as<uint8_t>();
DynamicJsonDocument jsonConfig(2048); // Same as PubSubClient buffer size. StaticJsonDocument<2048> jsonConfig;
jsonConfig["platform"] = "mqtt"; jsonConfig["platform"] = "mqtt";
jsonConfig["name"] = json[MCMT_DEVICE_NAME]; jsonConfig["name"] = json["name"];
jsonConfig["unique_id"] = myNet.macToString(sender) + "-" + unit; jsonConfig["unique_id"] = myNet.macToString(sender) + "-" + unit;
jsonConfig["device_class"] = getValueName(json[MCMT_DEVICE_CLASS].as<ha_binary_sensor_device_class_t>()); jsonConfig["device_class"] = getValueName(json["class"].as<ha_binary_sensor_device_class_t>());
jsonConfig["state_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/status"; jsonConfig["state_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/status";
jsonConfig["json_attributes_topic"] = config.topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/attributes"; jsonConfig["json_attributes_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/attributes";
jsonConfig["payload_on"] = json[MCMT_PAYLOAD_ON]; jsonConfig["payload_on"] = json["payload_on"];
jsonConfig["expire_after"] = json[MCMT_EXPIRE_AFTER]; jsonConfig["expire_after"] = json["expire_after"];
jsonConfig["force_update"] = "true"; jsonConfig["force_update"] = "true";
jsonConfig["retain"] = "true"; jsonConfig["retain"] = "true";
char buffer[2048]{0}; char buffer[2048]{0};
serializeJsonPretty(jsonConfig, buffer); serializeJsonPretty(jsonConfig, buffer);
mqttPublish((config.topicPrefix + "/" + getValueName(json[MCMT_COMPONENT_TYPE].as<ha_component_type_t>()) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true); mqttPublish((topicPrefix + "/" + getValueName(json["type"].as<ha_component_type_t>()) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
} }
} }
if (incomingData.payloadsType == ENPT_FORWARD) if (incomingData.payloadsType == ENPT_FORWARD)
{ {
esp_now_payload_data_t forwardData; esp_now_payload_data_t forwardData;
memcpy(&forwardData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message)); memcpy(&forwardData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
DynamicJsonDocument json(sizeof(esp_now_payload_data_t::message)); StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
deserializeJson(json, forwardData.message); deserializeJson(json, forwardData.message);
if (incomingData.deviceType == ENDT_RF_GATEWAY) if (incomingData.deviceType == ENDT_RF_GATEWAY)
mqttPublish((config.topicPrefix + "/rf_sensor/" + getValueName(json["type"].as<rf_sensor_type_t>()) + "/" + json["id"].as<uint16_t>() + "/state").c_str(), incomingData.message, false); mqttPublish((topicPrefix + "/rf_sensor/" + getValueName(json["type"].as<rf_sensor_type_t>()) + "/" + json["id"].as<uint16_t>() + "/state").c_str(), incomingData.message, false);
} }
} }
@ -409,30 +402,29 @@ void onMqttMessage(char *topic, byte *payload, unsigned int length)
} }
esp_now_payload_data_t outgoingData; esp_now_payload_data_t outgoingData;
outgoingData.deviceType = ENDT_GATEWAY; outgoingData.deviceType = ENDT_GATEWAY;
outgoingData.payloadsType = ENPT_SET; StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
DynamicJsonDocument json(sizeof(esp_now_payload_data_t::message));
if (message == "update" || message == "restart") if (message == "update" || message == "restart")
{ {
if (mac == myNet.getNodeMac() && message == "restart") if (mac == myNet.getNodeMac() && message == "restart")
ESP.restart(); ESP.restart();
flag = true; flag = true;
} }
if (String(topic) == config.topicPrefix + "/espnow_switch/" + mac + "/set" || String(topic) == config.topicPrefix + "/espnow_led/" + mac + "/set") if (String(topic) == topicPrefix + "/espnow_switch/" + mac + "/set" || String(topic) == topicPrefix + "/espnow_led/" + mac + "/set")
{ {
flag = true; flag = true;
json["set"] = message; json["set"] = message;
} }
if (String(topic) == config.topicPrefix + "/espnow_led/" + mac + "/brightness") if (String(topic) == topicPrefix + "/espnow_led/" + mac + "/brightness")
{ {
flag = true; flag = true;
json["brightness"] = message; json["brightness"] = message;
} }
if (String(topic) == config.topicPrefix + "/espnow_led/" + mac + "/temperature") if (String(topic) == topicPrefix + "/espnow_led/" + mac + "/temperature")
{ {
flag = true; flag = true;
json["temperature"] = message; json["temperature"] = message;
} }
if (String(topic) == config.topicPrefix + "/espnow_led/" + mac + "/rgb") if (String(topic) == topicPrefix + "/espnow_led/" + mac + "/rgb")
{ {
flag = true; flag = true;
json["rgb"] = message; json["rgb"] = message;
@ -441,8 +433,8 @@ void onMqttMessage(char *topic, byte *payload, unsigned int length)
{ {
if (message == "restart") if (message == "restart")
outgoingData.payloadsType = ENPT_RESTART; outgoingData.payloadsType = ENPT_RESTART;
if (message == "update") else
outgoingData.payloadsType = ENPT_UPDATE; outgoingData.payloadsType = message == "update" ? ENPT_UPDATE : ENPT_SET;
serializeJsonPretty(json, outgoingData.message); serializeJsonPretty(json, outgoingData.message);
char temp[sizeof(esp_now_payload_data_t)]{0}; char temp[sizeof(esp_now_payload_data_t)]{0};
memcpy(&temp, &outgoingData, sizeof(esp_now_payload_data_t)); memcpy(&temp, &outgoingData, sizeof(esp_now_payload_data_t));
@ -456,14 +448,14 @@ void sendKeepAliveMessage()
{ {
keepAliveMessageTimerSemaphore = false; keepAliveMessageTimerSemaphore = false;
if (isMqttAvailable) if (isMqttAvailable)
mqttPublish((config.topicPrefix + "/espnow_gateway/" + myNet.getNodeMac() + "/status").c_str(), "online", true); mqttPublish((topicPrefix + "/espnow_gateway/" + myNet.getNodeMac() + "/status").c_str(), "online", true);
esp_now_payload_data_t outgoingData; esp_now_payload_data_t outgoingData;
outgoingData.deviceType = ENDT_GATEWAY; outgoingData.deviceType = ENDT_GATEWAY;
outgoingData.payloadsType = ENPT_KEEP_ALIVE; outgoingData.payloadsType = ENPT_KEEP_ALIVE;
DynamicJsonDocument json(sizeof(esp_now_payload_data_t::message)); StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
json["MQTT"] = isMqttAvailable ? "online" : "offline"; json["MQTT"] = isMqttAvailable ? "online" : "offline";
json["frequency"] = 10; // For compatibility with the previous version. Will be removed in future releases. json["frequency"] = 10; // For compatibility with the previous version. Will be removed in future releases.
if (config.workMode == ESP_NOW_WIFI && WiFi.isConnected()) if (workMode == ESP_NOW_WIFI)
{ {
ntpWiFiClient.update(); ntpWiFiClient.update();
uint64_t epochTime = ntpWiFiClient.getEpochTime(); uint64_t epochTime = ntpWiFiClient.getEpochTime();
@ -471,7 +463,7 @@ void sendKeepAliveMessage()
json["time"] = ntpWiFiClient.getFormattedTime(); json["time"] = ntpWiFiClient.getFormattedTime();
json["date"] = String(time->tm_mday) + "." + String(time->tm_mon + 1) + "." + String(time->tm_year + 1900); json["date"] = String(time->tm_mday) + "." + String(time->tm_mon + 1) + "." + String(time->tm_year + 1900);
} }
if (config.workMode == ESP_NOW_LAN && Ethernet.linkStatus() == LinkON) if (workMode == ESP_NOW_LAN)
{ {
ntpEthClient.update(); ntpEthClient.update();
uint64_t epochTime = ntpEthClient.getEpochTime(); uint64_t epochTime = ntpEthClient.getEpochTime();
@ -496,7 +488,7 @@ void sendAttributesMessage()
uint32_t mins = secs / 60; uint32_t mins = secs / 60;
uint32_t hours = mins / 60; uint32_t hours = mins / 60;
uint32_t days = hours / 24; uint32_t days = hours / 24;
DynamicJsonDocument json(sizeof(esp_now_payload_data_t::message)); StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
json["Type"] = "ESP-NOW gateway"; json["Type"] = "ESP-NOW gateway";
#if defined(ESP8266) #if defined(ESP8266)
json["MCU"] = "ESP8266"; json["MCU"] = "ESP8266";
@ -507,32 +499,32 @@ void sendAttributesMessage()
json["MAC"] = myNet.getNodeMac(); json["MAC"] = myNet.getNodeMac();
json["Firmware"] = firmware; json["Firmware"] = firmware;
json["Library"] = myNet.getFirmwareVersion(); json["Library"] = myNet.getFirmwareVersion();
if (config.workMode == ESP_NOW_WIFI) if (workMode == ESP_NOW_WIFI)
json["IP"] = WiFi.localIP().toString(); json["IP"] = WiFi.localIP().toString();
if (config.workMode == ESP_NOW_LAN) if (workMode == ESP_NOW_LAN)
json["IP"] = Ethernet.localIP().toString(); json["IP"] = Ethernet.localIP().toString();
json["Uptime"] = "Days:" + String(days) + " Hours:" + String(hours - (days * 24)) + " Mins:" + String(mins - (hours * 60)); json["Uptime"] = "Days:" + String(days) + " Hours:" + String(hours - (days * 24)) + " Mins:" + String(mins - (hours * 60));
char buffer[sizeof(esp_now_payload_data_t::message)]{0}; char buffer[sizeof(esp_now_payload_data_t::message)]{0};
serializeJsonPretty(json, buffer); serializeJsonPretty(json, buffer);
mqttPublish((config.topicPrefix + "/espnow_gateway/" + myNet.getNodeMac() + "/attributes").c_str(), buffer, true); mqttPublish((topicPrefix + "/espnow_gateway/" + myNet.getNodeMac() + "/attributes").c_str(), buffer, true);
} }
void sendConfigMessage() void sendConfigMessage()
{ {
DynamicJsonDocument json(2048); // Same as PubSubClient buffer size. StaticJsonDocument<1024> json;
json["platform"] = "mqtt"; json["platform"] = "mqtt";
json["name"] = config.deviceName; json["name"] = deviceName;
json["unique_id"] = myNet.getNodeMac() + "-1"; json["unique_id"] = myNet.getNodeMac() + "-1";
json["device_class"] = "connectivity"; json["device_class"] = "connectivity";
json["state_topic"] = config.topicPrefix + "/espnow_gateway/" + myNet.getNodeMac() + "/status"; json["state_topic"] = topicPrefix + "/espnow_gateway/" + myNet.getNodeMac() + "/status";
json["json_attributes_topic"] = config.topicPrefix + "/espnow_gateway/" + myNet.getNodeMac() + "/attributes"; json["json_attributes_topic"] = topicPrefix + "/espnow_gateway/" + myNet.getNodeMac() + "/attributes";
json["payload_on"] = "online"; json["payload_on"] = "online";
json["expire_after"] = 30; json["expire_after"] = 30;
json["force_update"] = "true"; json["force_update"] = "true";
json["retain"] = "true"; json["retain"] = "true";
char buffer[1024]{0}; char buffer[1024]{0};
serializeJsonPretty(json, buffer); serializeJsonPretty(json, buffer);
mqttPublish((config.topicPrefix + "/binary_sensor/" + myNet.getNodeMac() + "-1" + "/config").c_str(), buffer, true); mqttPublish((topicPrefix + "/binary_sensor/" + myNet.getNodeMac() + "-1" + "/config").c_str(), buffer, true);
} }
String getValue(String data, char separator, uint8_t index) String getValue(String data, char separator, uint8_t index)
@ -552,27 +544,47 @@ String getValue(String data, char separator, uint8_t index)
void loadConfig() void loadConfig()
{ {
EEPROM.begin(4096); if (!LittleFS.exists("/config.json"))
if (EEPROM.read(4095) == 254)
{
EEPROM.get(0, config);
EEPROM.end();
}
else
{
EEPROM.end();
saveConfig(); saveConfig();
} File file = LittleFS.open("/config.json", "r");
delay(50); String jsonFile = file.readString();
StaticJsonDocument<1024> json;
deserializeJson(json, jsonFile);
espnowNetName = json["espnowNetName"].as<String>();
deviceName = json["deviceName"].as<String>();
ssid = json["ssid"].as<String>();
password = json["password"].as<String>();
mqttHostName = json["mqttHostName"].as<String>();
mqttHostPort = json["mqttHostPort"];
mqttUserLogin = json["mqttUserLogin"].as<String>();
mqttUserPassword = json["mqttUserPassword"].as<String>();
topicPrefix = json["topicPrefix"].as<String>();
workMode = json["workMode"];
ntpHostName = json["ntpHostName"].as<String>();
gmtOffset = json["gmtOffset"];
file.close();
} }
void saveConfig() void saveConfig()
{ {
EEPROM.begin(4096); StaticJsonDocument<1024> json;
EEPROM.write(4095, 254); json["firmware"] = firmware;
EEPROM.put(0, config); json["espnowNetName"] = espnowNetName;
EEPROM.end(); json["deviceName"] = deviceName;
delay(50); json["ssid"] = ssid;
json["password"] = password;
json["mqttHostName"] = mqttHostName;
json["mqttHostPort"] = mqttHostPort;
json["mqttUserLogin"] = mqttUserLogin;
json["mqttUserPassword"] = mqttUserPassword;
json["topicPrefix"] = topicPrefix;
json["workMode"] = workMode;
json["ntpHostName"] = ntpHostName;
json["gmtOffset"] = gmtOffset;
json["system"] = "empty";
File file = LittleFS.open("/config.json", "w");
serializeJsonPretty(json, file);
file.close();
} }
String xmlNode(String tags, String data) String xmlNode(String tags, String data)
@ -594,7 +606,7 @@ void setupWebServer()
ssdpHeader = xmlNode("specVersion", ssdpHeader); ssdpHeader = xmlNode("specVersion", ssdpHeader);
ssdpHeader += xmlNode("URLBase", "http://" + WiFi.localIP().toString()); ssdpHeader += xmlNode("URLBase", "http://" + WiFi.localIP().toString());
String ssdpDescription = xmlNode("deviceType", "upnp:rootdevice"); String ssdpDescription = xmlNode("deviceType", "upnp:rootdevice");
ssdpDescription += xmlNode("friendlyName", config.deviceName); ssdpDescription += xmlNode("friendlyName", deviceName);
ssdpDescription += xmlNode("presentationURL", "/"); ssdpDescription += xmlNode("presentationURL", "/");
ssdpDescription += xmlNode("serialNumber", "0000000" + String(random(1000))); ssdpDescription += xmlNode("serialNumber", "0000000" + String(random(1000)));
ssdpDescription += xmlNode("modelName", "ESP-NOW gateway"); ssdpDescription += xmlNode("modelName", "ESP-NOW gateway");
@ -612,57 +624,38 @@ void setupWebServer()
webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request) webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(LittleFS, "/index.htm"); }); { request->send(LittleFS, "/index.htm"); });
webServer.on("/function.js", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(LittleFS, "/function.js"); });
webServer.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(LittleFS, "/style.css"); });
webServer.on("/setting", HTTP_GET, [](AsyncWebServerRequest *request) webServer.on("/setting", HTTP_GET, [](AsyncWebServerRequest *request)
{ {
config.ssid = request->getParam("ssid")->value(); ssid = request->getParam("ssid")->value();
config.password = request->getParam("password")->value(); password = request->getParam("password")->value();
config.mqttHostName = request->getParam("mqttHostName")->value(); mqttHostName = request->getParam("host")->value();
config.mqttHostPort = request->getParam("mqttHostPort")->value().toInt(); mqttHostPort = request->getParam("port")->value().toInt();
config.mqttUserLogin = request->getParam("mqttUserLogin")->value(); mqttUserLogin = request->getParam("login")->value();
config.mqttUserPassword = request->getParam("mqttUserPassword")->value(); mqttUserPassword = request->getParam("pass")->value();
config.topicPrefix = request->getParam("topicPrefix")->value(); topicPrefix = request->getParam("prefix")->value();
config.deviceName = request->getParam("deviceName")->value(); deviceName = request->getParam("name")->value();
config.espnowNetName = request->getParam("espnowNetName")->value(); espnowNetName = request->getParam("net")->value();
config.workMode = request->getParam("workMode")->value().toInt(); workMode = request->getParam("mode")->value().toInt();
config.ntpHostName = request->getParam("ntpHostName")->value(); ntpHostName = request->getParam("ntp")->value();
config.gmtOffset = request->getParam("gmtOffset")->value().toInt(); gmtOffset = request->getParam("zone")->value().toInt();
request->send(200); request->send(200);
saveConfig(); }); saveConfig(); });
webServer.on("/config", HTTP_GET, [](AsyncWebServerRequest *request)
{
String configJson;
DynamicJsonDocument json(2048); // For overflow protection.
json["firmware"] = firmware;
json["espnowNetName"] = config.espnowNetName;
json["deviceName"] = config.deviceName;
json["ssid"] = config.ssid;
json["password"] = config.password;
json["mqttHostName"] = config.mqttHostName;
json["mqttHostPort"] = config.mqttHostPort;
json["mqttUserLogin"] = config.mqttUserLogin;
json["mqttUserPassword"] = config.mqttUserPassword;
json["topicPrefix"] = config.topicPrefix;
json["workMode"] = config.workMode;
json["ntpHostName"] = config.ntpHostName;
json["gmtOffset"] = config.gmtOffset;
serializeJsonPretty(json, configJson);
request->send(200, "application/json", configJson); });
webServer.on("/restart", HTTP_GET, [](AsyncWebServerRequest *request) webServer.on("/restart", HTTP_GET, [](AsyncWebServerRequest *request)
{request->send(200); {
request->send(200);
ESP.restart(); }); ESP.restart(); });
webServer.onNotFound([](AsyncWebServerRequest *request) webServer.onNotFound([](AsyncWebServerRequest *request)
{ request->send(404, "text/plain", "File Not Found"); }); {
if (LittleFS.exists(request->url()))
request->send(LittleFS, request->url());
else
{
request->send(404, "text/plain", "File Not Found");
} });
if (config.workMode == ESP_NOW_WIFI) if (workMode == ESP_NOW_WIFI)
SSDP.begin(); SSDP.begin();
webServer.begin(); webServer.begin();
@ -672,18 +665,18 @@ void checkMqttAvailability()
{ {
mqttAvailabilityCheckTimerSemaphore = false; mqttAvailabilityCheckTimerSemaphore = false;
if (config.workMode == ESP_NOW_WIFI) if (workMode == ESP_NOW_WIFI)
if (WiFi.isConnected()) if (WiFi.isConnected())
if (!mqttWifiClient.connected()) if (!mqttWifiClient.connected())
{ {
isMqttAvailable = false; isMqttAvailable = false;
if (mqttWifiClient.connect(mqttUserID, config.mqttUserLogin.c_str(), config.mqttUserPassword.c_str())) if (mqttWifiClient.connect(mqttUserID, mqttUserLogin.c_str(), mqttUserPassword.c_str()))
{ {
isMqttAvailable = true; isMqttAvailable = true;
mqttWifiClient.subscribe((config.topicPrefix + "/espnow_gateway/#").c_str()); mqttWifiClient.subscribe((topicPrefix + "/espnow_gateway/#").c_str());
mqttWifiClient.subscribe((config.topicPrefix + "/espnow_switch/#").c_str()); mqttWifiClient.subscribe((topicPrefix + "/espnow_switch/#").c_str());
mqttWifiClient.subscribe((config.topicPrefix + "/espnow_led/#").c_str()); mqttWifiClient.subscribe((topicPrefix + "/espnow_led/#").c_str());
sendConfigMessage(); sendConfigMessage();
sendAttributesMessage(); sendAttributesMessage();
@ -691,18 +684,18 @@ void checkMqttAvailability()
} }
} }
if (config.workMode == ESP_NOW_LAN) if (workMode == ESP_NOW_LAN)
if (Ethernet.linkStatus() == LinkON) if (Ethernet.linkStatus() == LinkON)
if (!mqttEthClient.connected()) if (!mqttEthClient.connected())
{ {
isMqttAvailable = false; isMqttAvailable = false;
if (mqttEthClient.connect(mqttUserID, config.mqttUserLogin.c_str(), config.mqttUserPassword.c_str())) if (mqttEthClient.connect(mqttUserID, mqttUserLogin.c_str(), mqttUserPassword.c_str()))
{ {
isMqttAvailable = true; isMqttAvailable = true;
mqttEthClient.subscribe((config.topicPrefix + "/espnow_gateway/#").c_str()); mqttEthClient.subscribe((topicPrefix + "/espnow_gateway/#").c_str());
mqttEthClient.subscribe((config.topicPrefix + "/espnow_switch/#").c_str()); mqttEthClient.subscribe((topicPrefix + "/espnow_switch/#").c_str());
mqttEthClient.subscribe((config.topicPrefix + "/espnow_led/#").c_str()); mqttEthClient.subscribe((topicPrefix + "/espnow_led/#").c_str());
sendConfigMessage(); sendConfigMessage();
sendAttributesMessage(); sendAttributesMessage();
@ -713,9 +706,9 @@ void checkMqttAvailability()
void mqttPublish(const char *topic, const char *payload, bool retained) void mqttPublish(const char *topic, const char *payload, bool retained)
{ {
if (config.workMode == ESP_NOW_WIFI) if (workMode == ESP_NOW_WIFI)
mqttWifiClient.publish(topic, payload, retained); mqttWifiClient.publish(topic, payload, retained);
if (config.workMode == ESP_NOW_LAN) if (workMode == ESP_NOW_LAN)
mqttEthClient.publish(topic, payload, retained); mqttEthClient.publish(topic, payload, retained);
} }