mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-26 22:22:16 +03:00
278 lines
9.9 KiB
C++
278 lines
9.9 KiB
C++
|
|
#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<JsonObject>())
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
String key = kvp.key().c_str();
|
|||
|
|
SerialPrint("i", F("=>MQTT"), "Msg from HOMEd: " + key);
|
|||
|
|
String value = kvp.value().as<const char *>();
|
|||
|
|
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<JsonArray>();
|
|||
|
|
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>(), "/");
|
|||
|
|
String id = chipId + "-" + device;
|
|||
|
|
String expose = value["name"];
|
|||
|
|
if (value["name"].as<String>() == "toggle")
|
|||
|
|
{
|
|||
|
|
HOMEdJSON = HOMEdJSON + "\"switch_" + device + "\",";
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
HOMEdJSON = HOMEdJSON + "\"" + device + "\",";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (value["name"].as<String>() == "anydataTmp")
|
|||
|
|
{
|
|||
|
|
// HOMEdJSON = HOMEdJSON + "\"temperature_" + device + "\",";
|
|||
|
|
options = options + "\"" + device + "\":{\"type\": \"sensor\", \"class\": \"temperature\", \"state\": \"measurement\", \"unit\": \"°C\", \"round\": 1},";
|
|||
|
|
}
|
|||
|
|
if (value["name"].as<String>() == "anydataHum")
|
|||
|
|
{
|
|||
|
|
// HOMEdJSON = HOMEdJSON + "\"humidity_" + device + "\",";
|
|||
|
|
options = options + "\"" + device + "\":{\"type\": \"sensor\", \"class\": \"humidity\", \"state\": \"measurement\", \"unit\": \"%\", \"round\": 1},";
|
|||
|
|
}
|
|||
|
|
if (value["name"].as<String>() == "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<IoTItem *>::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<IoTItem *>::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;
|
|||
|
|
}
|
|||
|
|
}
|