#include "Global.h" #include "classes/IoTDiscovery.h" // #include "MqttDiscovery.h" class DiscoveryHomeD : public IoTDiscovery { private: String _topic = ""; bool sendOk = false; // bool topicOk = false; bool HOMEd = false; public: DiscoveryHomeD(String parameters) : IoTDiscovery(parameters) { _topic = jsonReadStr(parameters, "topic"); if (_topic && _topic != "" && _topic != "null") { HOMEd = true; HOMEdTopic = _topic; } if (mqttIsConnect() && HOMEd) { mqttReconnect(); // sendOk = true; // mqttSubscribeExternal(_topic); } } void onMqttRecive(String &topic, String &payloadStr) { if (!HOMEd) return; if (msg.indexOf("HELLO") == -1) { /* String dev = selectToMarkerLast(topic, "/"); dev.toUpperCase(); dev.replace(":", ""); if (_topic != topic) { // SerialPrint("i", "ExternalMQTT", _id + " not equal: " + topic + " msg: " + msg); return; } */ // обработка топика, на который подписались if (topic.indexOf(F("/td/custom")) != -1) { // обрабатываем команды из HOMEd StaticJsonDocument<200> doc; deserializeJson(doc, payloadStr); for (JsonPair kvp : doc.as()) { String key = kvp.key().c_str(); SerialPrint("i", F("=>MQTT"), "Msg from HOMEd: " + key); String value = kvp.value().as(); if (key.indexOf(F("status_")) != -1) { key.replace("status_", ""); if (value == "on") { generateOrder(key, "1"); } else if (value == "off") { generateOrder(key, "0"); } else if (value == "toggle") { String val = (String)(1 - getItemValue(key).toInt()); generateOrder(key, val); } } if (!value) { float val = kvp.value(); generateOrder(key, (String)(val)); } } SerialPrint("i", F("=>MQTT"), "Msg from HOMEd: " + payloadStr); } } } void doByInterval() { /* // периодически проверяем связь с MQTT брокером и если она появилась, то подписываемся на нужный топик if (mqttIsConnect() && !sendOk && topicOk) { sendOk = true; publishRetain(_topic + "/device/custom/" + chipId, "{\"status\":\"online\"}"); String HOMEdsubscribeTopic = _topic + "/td/custom/" + chipId; // mqtt.subscribe(HOMEdsubscribeTopic.c_str()); mqttSubscribeExternal(HOMEdsubscribeTopic); } // если нет коннектас брокером, то сбрасываем флаг подписки, что бы при реконекте заново подписаться if (!mqttIsConnect()) sendOk = false; */ } void publishStatusHOMEd(const String &topic, const String &data) { String path_h = HOMEdTopic + "/fd/custom/" + chipId; String json_h = "{}"; if (topic != "onStart") { if (data.toInt() == 1) { jsonWriteStr(json_h, "status_" + topic, "on"); } else if (data.toInt() == 0) { jsonWriteStr(json_h, "status_" + topic, "off"); } if (data.toFloat()) { jsonWriteFloat(json_h, topic, data.toFloat()); } else { jsonWriteStr(json_h, topic, data); } mqtt.publish(path_h.c_str(), json_h.c_str(), false); } } void mqttSubscribeDiscovery() { if (HOMEd) { deleteFromHOMEd(); getlayoutHOMEd(); publishRetain(HOMEdTopic + "/device/custom/" + chipId, "{\"status\":\"online\"}"); String HOMEdsubscribeTopic = HOMEdTopic + "/td/custom/" + chipId; mqtt.subscribe(HOMEdsubscribeTopic.c_str()); } } void getlayoutHOMEd() { if (HOMEd) { String devName = jsonReadStr(settingsFlashJson, F("name")); auto file = seekFile("layout.json"); if (!file) { SerialPrint("E", F("MQTT"), F("no file layout.json")); return; } size_t size = file.size(); DynamicJsonDocument doc(size * 2); DeserializationError error = deserializeJson(doc, file); if (error) { SerialPrint("E", F("MQTT"), error.f_str()); jsonWriteInt(errorsHeapJson, F("jse3"), 1); // Ошибка чтения json файла с виджетами при отправки в mqtt } int i = 0; // String path = jsonReadStr(settingsFlashJson, F("HOMEd")); JsonArray arr = doc.as(); String HOMEdJSON = ""; HOMEdJSON = "{\"action\":\"updateDevice\","; HOMEdJSON = HOMEdJSON + "\"device\":\"" + chipId + "\","; HOMEdJSON = HOMEdJSON + "\"data\":{"; HOMEdJSON = HOMEdJSON + "\"active\": true,"; HOMEdJSON = HOMEdJSON + "\"cloud\": false,"; HOMEdJSON = HOMEdJSON + "\"discovery\": false,"; HOMEdJSON = HOMEdJSON + "\"id\":\"" + chipId + "\","; HOMEdJSON = HOMEdJSON + "\"name\":\"" + devName + "\","; HOMEdJSON = HOMEdJSON + "\"real\":true,"; HOMEdJSON = HOMEdJSON + "\"exposes\": ["; String options = ""; for (JsonVariant value : arr) { String name = value["descr"]; String device = selectToMarkerLast(value["topic"].as(), "/"); String id = chipId + "-" + device; String expose = value["name"]; if (value["name"].as() == "toggle") { HOMEdJSON = HOMEdJSON + "\"switch_" + device + "\","; } else { HOMEdJSON = HOMEdJSON + "\"" + device + "\","; } if (value["name"].as() == "anydataTmp") { // HOMEdJSON = HOMEdJSON + "\"temperature_" + device + "\","; options = options + "\"" + device + "\":{\"type\": \"sensor\", \"class\": \"temperature\", \"state\": \"measurement\", \"unit\": \"°C\", \"round\": 1},"; } if (value["name"].as() == "anydataHum") { // HOMEdJSON = HOMEdJSON + "\"humidity_" + device + "\","; options = options + "\"" + device + "\":{\"type\": \"sensor\", \"class\": \"humidity\", \"state\": \"measurement\", \"unit\": \"%\", \"round\": 1},"; } if (value["name"].as() == "inputDgt") { options = options + "\"" + device + "\":{\"type\": \"number\", \"min\": -10000, \"max\": 100000, \"step\": 0.1},"; } i++; } options = options.substring(0, options.length() - 1); HOMEdJSON = HOMEdJSON.substring(0, HOMEdJSON.length() - 1); HOMEdJSON = HOMEdJSON + "],"; HOMEdJSON = HOMEdJSON + " \"options\": {" + options + "}"; HOMEdJSON = HOMEdJSON + "}}"; String topic = (HOMEdTopic + "/command/custom").c_str(); if (!publish(topic, HOMEdJSON)) { SerialPrint("E", F("MQTT"), F("Failed publish data to HOMEd")); } file.close(); publishRetain(HOMEdTopic + "/device/custom/" + chipId, "{\"status\":\"online\"}"); for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { if ((*it)->iAmLocal) { publishStatusMqtt((*it)->getID(), (*it)->getValue()); (*it)->onMqttWsAppConnectEvent(); } } } } void deleteFromHOMEd() { if (HOMEd) { for (std::list::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) { if (*it) { String id_widget = (*it)->getID().c_str(); String HOMEdjson = ""; HOMEdjson = "{\"action\":\"removeDevice\","; HOMEdjson = HOMEdjson + "\"device\":\""; HOMEdjson = HOMEdjson + chipId; HOMEdjson = HOMEdjson + "\"}"; String topic = (HOMEdTopic + "/command/custom").c_str(); if (!publish(topic, HOMEdjson)) { SerialPrint("E", F("MQTT"), F("Failed remove from HOMEd")); } } } } } IoTBench *getBenchmarkTask() { if (HOMEd) return this; else return nullptr; } ~DiscoveryHomeD(){}; }; void *getAPI_DiscoveryHomeD(String subtype, String param) { if (subtype == F("DiscoveryHomeD")) { return new DiscoveryHomeD(param); } else { return nullptr; } }