|
|
|
@ -15,13 +15,6 @@
|
|
|
|
|
#include "ESP32SSDP.h"
|
|
|
|
|
#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 onMqttMessage(char *topic, byte *payload, unsigned int length);
|
|
|
|
@ -42,7 +35,14 @@ void checkMqttAvailability(void);
|
|
|
|
|
|
|
|
|
|
void mqttPublish(const char *topic, const char *payload, bool retained);
|
|
|
|
|
|
|
|
|
|
const String firmware{"1.3"};
|
|
|
|
|
typedef enum : uint8_t
|
|
|
|
|
{
|
|
|
|
|
ESP_NOW,
|
|
|
|
|
ESP_NOW_WIFI,
|
|
|
|
|
ESP_NOW_LAN
|
|
|
|
|
} work_mode_t;
|
|
|
|
|
|
|
|
|
|
const String firmware{"1.5"};
|
|
|
|
|
|
|
|
|
|
String espnowNetName{"DEFAULT"};
|
|
|
|
|
|
|
|
|
@ -227,25 +227,26 @@ void onEspnowMessage(const char *data, const uint8_t *sender)
|
|
|
|
|
memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
|
|
|
|
|
StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
|
|
|
|
|
deserializeJson(json, configData.message);
|
|
|
|
|
uint8_t unit = json["unit"].as<uint8_t>();
|
|
|
|
|
ha_component_type_t type = json["type"].as<ha_component_type_t>();
|
|
|
|
|
uint8_t unit = json[MCMT_DEVICE_UNIT].as<uint8_t>();
|
|
|
|
|
StaticJsonDocument<2048> jsonConfig;
|
|
|
|
|
jsonConfig["platform"] = "mqtt";
|
|
|
|
|
jsonConfig["name"] = json["name"];
|
|
|
|
|
jsonConfig["name"] = json[MCMT_DEVICE_NAME];
|
|
|
|
|
jsonConfig["unique_id"] = myNet.macToString(sender) + "-" + unit;
|
|
|
|
|
jsonConfig["device_class"] = getValueName(json["class"].as<ha_switch_device_class_t>());
|
|
|
|
|
jsonConfig["device_class"] = getValueName(json[MCMT_DEVICE_CLASS].as<ha_switch_device_class_t>());
|
|
|
|
|
jsonConfig["state_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state";
|
|
|
|
|
jsonConfig["value_template"] = "{{ value_json." + json["template"].as<String>() + " }}";
|
|
|
|
|
jsonConfig["value_template"] = "{{ value_json." + json[MCMT_VALUE_TEMPLATE].as<String>() + " }}";
|
|
|
|
|
jsonConfig["command_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/set";
|
|
|
|
|
jsonConfig["json_attributes_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/attributes";
|
|
|
|
|
jsonConfig["availability_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/status";
|
|
|
|
|
jsonConfig["payload_on"] = json["payload_on"];
|
|
|
|
|
jsonConfig["payload_off"] = json["payload_off"];
|
|
|
|
|
if (json[MCMT_PAYLOAD_ON])
|
|
|
|
|
jsonConfig["payload_on"] = json[MCMT_PAYLOAD_ON];
|
|
|
|
|
if (json[MCMT_PAYLOAD_OFF])
|
|
|
|
|
jsonConfig["payload_off"] = json[MCMT_PAYLOAD_OFF];
|
|
|
|
|
jsonConfig["optimistic"] = "false";
|
|
|
|
|
jsonConfig["retain"] = "true";
|
|
|
|
|
char buffer[2048]{0};
|
|
|
|
|
serializeJsonPretty(jsonConfig, buffer);
|
|
|
|
|
mqttPublish((topicPrefix + "/" + getValueName(type) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
|
|
|
|
|
mqttPublish((topicPrefix + "/" + getValueName(json[MCMT_COMPONENT_TYPE].as<ha_component_type_t>()) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
|
|
|
|
|
}
|
|
|
|
|
if (incomingData.deviceType == ENDT_LED)
|
|
|
|
|
{
|
|
|
|
@ -253,12 +254,11 @@ void onEspnowMessage(const char *data, const uint8_t *sender)
|
|
|
|
|
memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
|
|
|
|
|
StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
|
|
|
|
|
deserializeJson(json, configData.message);
|
|
|
|
|
uint8_t unit = json["unit"].as<uint8_t>();
|
|
|
|
|
ha_component_type_t type = json["type"].as<ha_component_type_t>();
|
|
|
|
|
esp_now_led_type_t ledClass = json["class"];
|
|
|
|
|
uint8_t unit = json[MCMT_DEVICE_UNIT].as<uint8_t>();
|
|
|
|
|
esp_now_led_type_t ledClass = json[MCMT_DEVICE_CLASS];
|
|
|
|
|
StaticJsonDocument<2048> jsonConfig;
|
|
|
|
|
jsonConfig["platform"] = "mqtt";
|
|
|
|
|
jsonConfig["name"] = json["name"];
|
|
|
|
|
jsonConfig["name"] = json[MCMT_DEVICE_NAME];
|
|
|
|
|
jsonConfig["unique_id"] = myNet.macToString(sender) + "-" + unit;
|
|
|
|
|
jsonConfig["state_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state";
|
|
|
|
|
jsonConfig["state_value_template"] = "{{ value_json.state }}";
|
|
|
|
@ -280,13 +280,15 @@ void onEspnowMessage(const char *data, const uint8_t *sender)
|
|
|
|
|
}
|
|
|
|
|
jsonConfig["json_attributes_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/attributes";
|
|
|
|
|
jsonConfig["availability_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/status";
|
|
|
|
|
jsonConfig["payload_on"] = json["payload_on"];
|
|
|
|
|
jsonConfig["payload_off"] = json["payload_off"];
|
|
|
|
|
if (json[MCMT_PAYLOAD_ON])
|
|
|
|
|
jsonConfig["payload_on"] = json[MCMT_PAYLOAD_ON];
|
|
|
|
|
if (json[MCMT_PAYLOAD_OFF])
|
|
|
|
|
jsonConfig["payload_off"] = json[MCMT_PAYLOAD_OFF];
|
|
|
|
|
jsonConfig["optimistic"] = "false";
|
|
|
|
|
jsonConfig["retain"] = "true";
|
|
|
|
|
char buffer[2048]{0};
|
|
|
|
|
serializeJsonPretty(jsonConfig, buffer);
|
|
|
|
|
mqttPublish((topicPrefix + "/" + getValueName(type) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
|
|
|
|
|
mqttPublish((topicPrefix + "/" + getValueName(json[MCMT_COMPONENT_TYPE].as<ha_component_type_t>()) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
|
|
|
|
|
}
|
|
|
|
|
if (incomingData.deviceType == ENDT_SENSOR)
|
|
|
|
|
{
|
|
|
|
@ -294,29 +296,96 @@ void onEspnowMessage(const char *data, const uint8_t *sender)
|
|
|
|
|
memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
|
|
|
|
|
StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
|
|
|
|
|
deserializeJson(json, configData.message);
|
|
|
|
|
uint8_t unit = json["unit"].as<uint8_t>();
|
|
|
|
|
ha_component_type_t type = json["type"].as<ha_component_type_t>();
|
|
|
|
|
uint8_t unit = json[MCMT_DEVICE_UNIT].as<uint8_t>();
|
|
|
|
|
ha_component_type_t type = json[MCMT_COMPONENT_TYPE].as<ha_component_type_t>();
|
|
|
|
|
StaticJsonDocument<2048> jsonConfig;
|
|
|
|
|
jsonConfig["platform"] = "mqtt";
|
|
|
|
|
jsonConfig["name"] = json["name"];
|
|
|
|
|
jsonConfig["name"] = json[MCMT_DEVICE_NAME];
|
|
|
|
|
jsonConfig["unique_id"] = myNet.macToString(sender) + "-" + unit;
|
|
|
|
|
jsonConfig["state_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/state";
|
|
|
|
|
jsonConfig["value_template"] = "{{ value_json." + json["template"].as<String>() + " }}";
|
|
|
|
|
jsonConfig["value_template"] = "{{ value_json." + json[MCMT_VALUE_TEMPLATE].as<String>() + " }}";
|
|
|
|
|
jsonConfig["json_attributes_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/attributes";
|
|
|
|
|
jsonConfig["force_update"] = "true";
|
|
|
|
|
jsonConfig["retain"] = "true";
|
|
|
|
|
if (type == HACT_SENSOR)
|
|
|
|
|
jsonConfig["device_class"] = getValueName(json["class"].as<ha_sensor_device_class_t>());
|
|
|
|
|
if (type == HACT_BINARY_SENSOR)
|
|
|
|
|
{
|
|
|
|
|
jsonConfig["device_class"] = getValueName(json["class"].as<ha_binary_sensor_device_class_t>());
|
|
|
|
|
jsonConfig["payload_on"] = json["payload_on"];
|
|
|
|
|
jsonConfig["payload_off"] = json["payload_off"];
|
|
|
|
|
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)
|
|
|
|
|
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};
|
|
|
|
|
serializeJsonPretty(jsonConfig, buffer);
|
|
|
|
|
mqttPublish((topicPrefix + "/" + getValueName(type) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
|
|
|
|
|
}
|
|
|
|
|
if (incomingData.deviceType == ENDT_RF_SENSOR)
|
|
|
|
|
{
|
|
|
|
|
esp_now_payload_data_t configData;
|
|
|
|
|
memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
|
|
|
|
|
StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
|
|
|
|
|
deserializeJson(json, configData.message);
|
|
|
|
|
uint8_t unit = json["u"].as<uint8_t>();
|
|
|
|
|
ha_component_type_t type = json["t"].as<ha_component_type_t>();
|
|
|
|
|
rf_sensor_type_t rf = json["r"].as<rf_sensor_type_t>();
|
|
|
|
|
uint16_t id = json["i"].as<uint16_t>();
|
|
|
|
|
String tmp = json["v"].as<String>();
|
|
|
|
|
StaticJsonDocument<2048> jsonConfig;
|
|
|
|
|
jsonConfig["platform"] = "mqtt";
|
|
|
|
|
jsonConfig["name"] = getValueName(rf) + " " + id + " " + tmp;
|
|
|
|
|
jsonConfig["unique_id"] = String(id) + "-" + unit;
|
|
|
|
|
jsonConfig["state_topic"] = topicPrefix + "/rf_sensor/" + getValueName(rf) + "/" + id + "/state";
|
|
|
|
|
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["retain"] = "true";
|
|
|
|
|
char buffer[2048]{0};
|
|
|
|
|
serializeJsonPretty(jsonConfig, buffer);
|
|
|
|
|
mqttPublish((topicPrefix + "/" + getValueName(type) + "/" + id + "-" + unit + "/config").c_str(), buffer, true);
|
|
|
|
|
}
|
|
|
|
|
if (incomingData.deviceType == ENDT_RF_GATEWAY)
|
|
|
|
|
{
|
|
|
|
|
esp_now_payload_data_t configData;
|
|
|
|
|
memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
|
|
|
|
|
StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
|
|
|
|
|
deserializeJson(json, configData.message);
|
|
|
|
|
uint8_t unit = json["unit"].as<uint8_t>();
|
|
|
|
|
StaticJsonDocument<2048> jsonConfig;
|
|
|
|
|
jsonConfig["platform"] = "mqtt";
|
|
|
|
|
jsonConfig["name"] = json["name"];
|
|
|
|
|
jsonConfig["unique_id"] = myNet.macToString(sender) + "-" + unit;
|
|
|
|
|
jsonConfig["device_class"] = getValueName(json["class"].as<ha_binary_sensor_device_class_t>());
|
|
|
|
|
jsonConfig["state_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/status";
|
|
|
|
|
jsonConfig["json_attributes_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/attributes";
|
|
|
|
|
jsonConfig["payload_on"] = json["payload_on"];
|
|
|
|
|
jsonConfig["expire_after"] = json["expire_after"];
|
|
|
|
|
jsonConfig["force_update"] = "true";
|
|
|
|
|
jsonConfig["retain"] = "true";
|
|
|
|
|
char buffer[2048]{0};
|
|
|
|
|
serializeJsonPretty(jsonConfig, buffer);
|
|
|
|
|
mqttPublish((topicPrefix + "/" + getValueName(json["type"].as<ha_component_type_t>()) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (incomingData.payloadsType == ENPT_FORWARD)
|
|
|
|
|
{
|
|
|
|
@ -324,7 +393,8 @@ void onEspnowMessage(const char *data, const uint8_t *sender)
|
|
|
|
|
memcpy(&forwardData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
|
|
|
|
|
StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
|
|
|
|
|
deserializeJson(json, forwardData.message);
|
|
|
|
|
mqttPublish((topicPrefix + "/rf_sensor/" + getValueName(json["type"].as<rf_sensor_type_t>()) + "/" + json["id"].as<uint16_t>()).c_str(), incomingData.message, false);
|
|
|
|
|
if (incomingData.deviceType == ENDT_RF_GATEWAY)
|
|
|
|
|
mqttPublish((topicPrefix + "/rf_sensor/" + getValueName(json["type"].as<rf_sensor_type_t>()) + "/" + json["id"].as<uint16_t>() + "/state").c_str(), incomingData.message, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -339,11 +409,10 @@ void onMqttMessage(char *topic, byte *payload, unsigned int length)
|
|
|
|
|
}
|
|
|
|
|
esp_now_payload_data_t outgoingData;
|
|
|
|
|
outgoingData.deviceType = ENDT_GATEWAY;
|
|
|
|
|
outgoingData.payloadsType = ENPT_SET;
|
|
|
|
|
StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
|
|
|
|
|
if (message == "update" || message == "restart")
|
|
|
|
|
{
|
|
|
|
|
mqttPublish(topic, "", true);
|
|
|
|
|
mqttPublish((String(topic) + "/status").c_str(), "offline", true);
|
|
|
|
|
if (mac == myNet.getNodeMac() && message == "restart")
|
|
|
|
|
ESP.restart();
|
|
|
|
|
flag = true;
|
|
|
|
@ -372,11 +441,9 @@ void onMqttMessage(char *topic, byte *payload, unsigned int length)
|
|
|
|
|
{
|
|
|
|
|
if (message == "restart")
|
|
|
|
|
outgoingData.payloadsType = ENPT_RESTART;
|
|
|
|
|
else
|
|
|
|
|
outgoingData.payloadsType = message == "update" ? ENPT_UPDATE : ENPT_SET;
|
|
|
|
|
char buffer[sizeof(esp_now_payload_data_t::message)]{0};
|
|
|
|
|
serializeJsonPretty(json, buffer);
|
|
|
|
|
memcpy(&outgoingData.message, &buffer, sizeof(esp_now_payload_data_t::message));
|
|
|
|
|
if (message == "update")
|
|
|
|
|
outgoingData.payloadsType = ENPT_UPDATE;
|
|
|
|
|
serializeJsonPretty(json, outgoingData.message);
|
|
|
|
|
char temp[sizeof(esp_now_payload_data_t)]{0};
|
|
|
|
|
memcpy(&temp, &outgoingData, sizeof(esp_now_payload_data_t));
|
|
|
|
|
uint8_t target[6];
|
|
|
|
@ -396,7 +463,7 @@ void sendKeepAliveMessage()
|
|
|
|
|
StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
|
|
|
|
|
json["MQTT"] = isMqttAvailable ? "online" : "offline";
|
|
|
|
|
json["frequency"] = 10; // For compatibility with the previous version. Will be removed in future releases.
|
|
|
|
|
if (workMode == ESP_NOW_WIFI)
|
|
|
|
|
if (workMode == ESP_NOW_WIFI && WiFi.isConnected())
|
|
|
|
|
{
|
|
|
|
|
ntpWiFiClient.update();
|
|
|
|
|
uint64_t epochTime = ntpWiFiClient.getEpochTime();
|
|
|
|
@ -404,7 +471,7 @@ void sendKeepAliveMessage()
|
|
|
|
|
json["time"] = ntpWiFiClient.getFormattedTime();
|
|
|
|
|
json["date"] = String(time->tm_mday) + "." + String(time->tm_mon + 1) + "." + String(time->tm_year + 1900);
|
|
|
|
|
}
|
|
|
|
|
if (workMode == ESP_NOW_LAN)
|
|
|
|
|
if (workMode == ESP_NOW_LAN && Ethernet.linkStatus() == LinkON)
|
|
|
|
|
{
|
|
|
|
|
ntpEthClient.update();
|
|
|
|
|
uint64_t epochTime = ntpEthClient.getEpochTime();
|
|
|
|
@ -569,16 +636,16 @@ void setupWebServer()
|
|
|
|
|
{
|
|
|
|
|
ssid = request->getParam("ssid")->value();
|
|
|
|
|
password = request->getParam("password")->value();
|
|
|
|
|
mqttHostName = request->getParam("host")->value();
|
|
|
|
|
mqttHostPort = request->getParam("port")->value().toInt();
|
|
|
|
|
mqttUserLogin = request->getParam("login")->value();
|
|
|
|
|
mqttUserPassword = request->getParam("pass")->value();
|
|
|
|
|
topicPrefix = request->getParam("prefix")->value();
|
|
|
|
|
deviceName = request->getParam("name")->value();
|
|
|
|
|
espnowNetName = request->getParam("net")->value();
|
|
|
|
|
workMode = request->getParam("mode")->value().toInt();
|
|
|
|
|
ntpHostName = request->getParam("ntp")->value();
|
|
|
|
|
gmtOffset = request->getParam("zone")->value().toInt();
|
|
|
|
|
mqttHostName = request->getParam("mqttHostName")->value();
|
|
|
|
|
mqttHostPort = request->getParam("mqttHostPor")->value().toInt();
|
|
|
|
|
mqttUserLogin = request->getParam("mqttUserLogin")->value();
|
|
|
|
|
mqttUserPassword = request->getParam("mqttUserPassword")->value();
|
|
|
|
|
topicPrefix = request->getParam("topicPrefix")->value();
|
|
|
|
|
deviceName = request->getParam("deviceName")->value();
|
|
|
|
|
espnowNetName = request->getParam("espnowNetName")->value();
|
|
|
|
|
workMode = request->getParam("workMode")->value().toInt();
|
|
|
|
|
ntpHostName = request->getParam("ntpHostName")->value();
|
|
|
|
|
gmtOffset = request->getParam("gmtOffset")->value().toInt();
|
|
|
|
|
request->send(200);
|
|
|
|
|
saveConfig(); });
|
|
|
|
|
|
|
|
|
@ -620,6 +687,8 @@ void checkMqttAvailability()
|
|
|
|
|
mqttWifiClient.subscribe((topicPrefix + "/espnow_led/#").c_str());
|
|
|
|
|
|
|
|
|
|
sendConfigMessage();
|
|
|
|
|
sendAttributesMessage();
|
|
|
|
|
sendKeepAliveMessage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -637,6 +706,8 @@ void checkMqttAvailability()
|
|
|
|
|
mqttEthClient.subscribe((topicPrefix + "/espnow_led/#").c_str());
|
|
|
|
|
|
|
|
|
|
sendConfigMessage();
|
|
|
|
|
sendAttributesMessage();
|
|
|
|
|
sendKeepAliveMessage();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|