diff --git a/include/MqttClient.h b/include/MqttClient.h index 99ed843f..35827e4e 100644 --- a/include/MqttClient.h +++ b/include/MqttClient.h @@ -14,6 +14,7 @@ boolean mqttConnect(); void mqttReconnect(); void mqttLoop(); void mqttSubscribe(); +bool mqttIsConnect(); boolean publish(const String& topic, const String& data); boolean publishData(const String& topic, const String& data); @@ -21,6 +22,7 @@ boolean publishChartMqtt(const String& topic, const String& data); boolean publishJsonMqtt(const String& topic, const String& json); boolean publishStatusMqtt(const String& topic, const String& data); boolean publishEvent(const String& topic, const String& data); +void mqttSubscribeExternal(String topic, bool usePrefix); bool publishChartFileToMqtt(String path, String id, int maxCount); diff --git a/src/MqttClient.cpp b/src/MqttClient.cpp index 4324e7c1..cfc5e8c2 100644 --- a/src/MqttClient.cpp +++ b/src/MqttClient.cpp @@ -95,6 +95,10 @@ void mqttReconnect() { mqttConnect(); } +bool mqttIsConnect(){ + return mqtt.connected(); +} + void getMqttData() { mqttServer = jsonReadStr(settingsFlashJson, F("mqttServer")); mqttPort = jsonReadInt(settingsFlashJson, F("mqttPort")); @@ -116,6 +120,16 @@ void mqttSubscribe() { } } +void mqttSubscribeExternal(String topic, bool usePrefix) { + SerialPrint("i", F("MQTT"), ("subscribed external" + topic).c_str()); + // SerialPrint("i", F("MQTT"), mqttRootDevice); + if (usePrefix) + { + mqtt.subscribe((mqttPrefix + topic).c_str()); + } + mqtt.subscribe(topic.c_str()); +} + void mqttCallback(char* topic, uint8_t* payload, size_t length) { String topicStr = String(topic); // SerialPrint("i", "=>MQTT", topicStr); diff --git a/src/classes/IoTScenario.cpp b/src/classes/IoTScenario.cpp index b1c7b988..6aa26e77 100644 --- a/src/classes/IoTScenario.cpp +++ b/src/classes/IoTScenario.cpp @@ -341,7 +341,8 @@ enum SysOp { sysop_getRSSI, sysop_getIP, sysop_mqttPub, - sysop_getUptime + sysop_getUptime, + sysop_mqttIsConnect }; IoTValue sysExecute(SysOp command, std::vector ¶m) { @@ -442,6 +443,9 @@ IoTValue sysExecute(SysOp command, std::vector ¶m) { value.valS = jsonReadStr(errorsHeapJson, F("upt")); value.isDecimal = false; break; + case sysop_mqttIsConnect: + value.valD = mqttIsConnect(); + break; } return value; @@ -496,6 +500,8 @@ class SysCallExprAST : public ExprAST { operation = sysop_getTime; else if (Callee == F("getUptime")) operation = sysop_getUptime; + else if (Callee == F("mqttIsConnect")) + operation = sysop_mqttIsConnect; else operation = sysop_notfound; } diff --git a/src/modules/sceninfo.json b/src/modules/sceninfo.json index fb472e38..551f6d0e 100644 --- a/src/modules/sceninfo.json +++ b/src/modules/sceninfo.json @@ -69,6 +69,11 @@ "descr": "Отправить значение в топик MQTT", "params": ["Топик", "Значение"] }, + { + "name": "mqttIsConnect", + "descr": "Получить состояние подключения к MQTT", + "params": [] + }, { "name": "getHours", "descr": "Получить текущее число часов. Если время не получено из сети Интернет или внешнего RTC, то условие пропускается", diff --git a/src/modules/sensors/ExternalMQTT/ExternalMQTT.cpp b/src/modules/sensors/ExternalMQTT/ExternalMQTT.cpp index 3ad82a54..91da0b9c 100644 --- a/src/modules/sensors/ExternalMQTT/ExternalMQTT.cpp +++ b/src/modules/sensors/ExternalMQTT/ExternalMQTT.cpp @@ -13,16 +13,24 @@ private: int red = 0; int offline = 0; bool dataFromNode = false; + String _topic = ""; + bool _isJson; + bool _addPrefix; + bool _debug; public: ExternalMQTT(String parameters) : IoTItem(parameters) { - _MAC = jsonReadStr(parameters, "MAC"); _sensor = jsonReadStr(parameters, "sensor"); jsonRead(parameters, F("orange"), orange); jsonRead(parameters, F("red"), red); jsonRead(parameters, F("offline"), offline); + _topic = jsonReadStr(parameters, "topic"); + _isJson = jsonReadBool(parameters, "isJson"); + _addPrefix = jsonReadBool(parameters, "addPrefix"); + _debug = jsonReadBool(parameters, "debug"); dataFromNode = false; + mqttSubscribeExternal(_topic, _addPrefix); } char *TimeToString(unsigned long t) { @@ -38,38 +46,58 @@ public: { if (msg.indexOf("HELLO") == -1) { - - // SerialPrint("i", "onMqttRecive", "Прилетело " + topic); - // SerialPrint("i", "onMqttRecive", "Прилетело " + msg); + if (_debug) + { + SerialPrint("i", "onMqttRecive", "Прилетело " + topic + " msg: " + msg); + // SerialPrint("i", "onMqttRecive", "Прилетело " + msg); + } String dev = selectToMarkerLast(topic, "/"); dev.toUpperCase(); dev.replace(":", ""); - if (_MAC == "") + if (_topic != topic) { - SerialPrint("i", "onMqttRecive", dev + " --> " + msg); + return; } - DynamicJsonDocument doc(JSON_BUFFER_SIZE); - DeserializationError error = deserializeJson(doc, msg); - if (error) + if (_isJson) { - SerialPrint("E", F("onMqttRecive"), error.f_str()); - } - JsonObject jsonObject = doc.as(); - - for (JsonPair kv : jsonObject) - { - String key = kv.key().c_str(); - String val = kv.value(); - if (_MAC == dev && _sensor == key) + DynamicJsonDocument doc(JSON_BUFFER_SIZE); + DeserializationError error = deserializeJson(doc, msg); + if (error) { - dataFromNode = true; - _minutesPassed = 0; - setValue(val); - // setNewWidgetAttributes(); + SerialPrint("E", F("onMqttRecive"), error.f_str()); } + JsonObject jsonObject = doc.as(); - // Serial.println("Key: " + key); - // Serial.println("Value: " + val); + for (JsonPair kv : jsonObject) + { + String key = kv.key().c_str(); + String val = kv.value(); + if (_debug) + { + SerialPrint("i", "onMqttRecive", "Прилетело MAC: " + dev + " key=" + key + " val=" + val); + } + if (_sensor == key) + { + dataFromNode = true; + _minutesPassed = 0; + setValue(val); + // setNewWidgetAttributes(); + } + + // Serial.println("Key: " + key); + // Serial.println("Value: " + val); + } + } + else + { + if (_debug) + { + SerialPrint("i", "onMqttRecive", "Прилетело MAC: " + dev + " val=" + msg); + } + dataFromNode = true; + _minutesPassed = 0; + setValue(msg); + // setNewWidgetAttributes(); } } } @@ -116,7 +144,22 @@ public: } sendSubWidgetsValues(_id, json); } - + /* + IoTValue execute(String command, std::vector ¶m) + { + if (command == "mqttSubscribe") + { + if (param.size() == 2) + { + if (!param[0].isDecimal && param[1].isDecimal) + { + mqttSubscribeExternal(param[0].valS, (bool)param[0].valD); + } + } + } + return {}; + } + */ ~ExternalMQTT(){}; }; diff --git a/src/modules/sensors/ExternalMQTT/modinfo.json b/src/modules/sensors/ExternalMQTT/modinfo.json index 92304416..70825798 100644 --- a/src/modules/sensors/ExternalMQTT/modinfo.json +++ b/src/modules/sensors/ExternalMQTT/modinfo.json @@ -10,13 +10,16 @@ "widget": "", "page": "", "descr": "", - "MAC": "", "sensor": "", + "topic": "", + "addPrefix": 0, + "isJson": 1, "round": "", "orange": 60, "red": 120, "offline": 180, - "int": 60 + "int": 60, + "debug": 0 } ], "about": { @@ -25,7 +28,7 @@ "authorGit": "https://github.com/avaksru", "specialThanks": "", "moduleName": "ExternalMQTT", - "moduleVersion": "1", + "moduleVersion": "1.2", "usedRam": { "esp32_4mb": 15, "esp8266_4mb": 15 @@ -38,13 +41,18 @@ "orange": "количество минут после которого окрасить виджет в оранжевый цвет", "red": "количество минут после которого окрасить виджет в красный цвет", "offline": "количество минут после которого отобразить что устройство offline, если все три orange red и offline поставить в ноль - то функция окраски выключится", - "MAC": "MAC адрес беспроводного датчика", - "sensor": "Тип сенсора: температура / влажность / время / ... " + "sensor": "Тип сенсора: температура / влажность / время / ... Он же ключ в json пакете ", + "topic":"Подписаться на произвольный топик (полный путь), в модуле данный топик буде проверяться с отправителем, например homed/fd/zigbee/temp", + "addPrefix":"1 (число), будет добавлен стандартный префикс из настроек, 0 - не добавлять префикс", + "isJson":"1 - ожидаем в топике json, 0 - в топике просто значение (при 0 поле sensor заполнять не требуется)", + "debug":"1 - выводить дополнительный лог в сериал" } + }, "defActive": false, "usedLibs": { "esp32_4mb": [], + "esp32s2_4mb": [], "esp8266_4mb": [], "esp8266_1mb": [], "esp8266_1mb_ota": [],