mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-26 22:22:16 +03:00
Discovery HA and HomeD
This commit is contained in:
@@ -9,6 +9,15 @@
|
|||||||
#include <PubSubClient.h>
|
#include <PubSubClient.h>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
#ifdef libretiny
|
||||||
|
#include <vector>
|
||||||
|
#include <typedef.h>
|
||||||
|
#ifdef STANDARD_WEB_SERVER
|
||||||
|
#include <WebServer.h>
|
||||||
|
#endif
|
||||||
|
#include <HTTPClient.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
#include "WiFi.h"
|
#include "WiFi.h"
|
||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
@@ -22,6 +31,7 @@
|
|||||||
|
|
||||||
#ifdef ASYNC_WEB_SERVER
|
#ifdef ASYNC_WEB_SERVER
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include "AsyncWebServer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef STANDARD_WEB_SERVER
|
#ifdef STANDARD_WEB_SERVER
|
||||||
@@ -60,6 +70,9 @@ extern IoTItem* rtcItem;
|
|||||||
extern IoTItem* tlgrmItem;
|
extern IoTItem* tlgrmItem;
|
||||||
extern IoTBench* benchLoadItem;
|
extern IoTBench* benchLoadItem;
|
||||||
extern IoTBench* benchTaskItem;
|
extern IoTBench* benchTaskItem;
|
||||||
|
extern IoTDiscovery* HADiscovery;
|
||||||
|
extern IoTDiscovery* HOMEdDiscovery;
|
||||||
|
|
||||||
|
|
||||||
extern TickerScheduler ts;
|
extern TickerScheduler ts;
|
||||||
extern WiFiClient espClient;
|
extern WiFiClient espClient;
|
||||||
@@ -77,6 +90,9 @@ extern ESP8266HTTPUpdateServer httpUpdater;
|
|||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
extern WebServer HTTP;
|
extern WebServer HTTP;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef libretiny
|
||||||
|
extern WebServer HTTP;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef STANDARD_WEB_SOCKETS
|
#ifdef STANDARD_WEB_SOCKETS
|
||||||
|
|||||||
36
include/classes/IoTDiscovery.h
Normal file
36
include/classes/IoTDiscovery.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "Global.h"
|
||||||
|
#include "classes/IoTItem.h"
|
||||||
|
|
||||||
|
class IoTDiscovery : public IoTItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IoTDiscovery(const String ¶meters);
|
||||||
|
~IoTDiscovery();
|
||||||
|
|
||||||
|
// inline bool isDiscoveryHomed() { return HOMEd; }
|
||||||
|
|
||||||
|
// inline bool isDiscoveryHA() { return HA; }
|
||||||
|
|
||||||
|
String HOMEdTopic = "";
|
||||||
|
String HATopic = "";
|
||||||
|
//String ChipId = "";
|
||||||
|
|
||||||
|
virtual void mqttSubscribeDiscovery();
|
||||||
|
|
||||||
|
virtual void publishStatusHOMEd(const String &topic, const String &data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
boolean publishRetain(const String &topic, const String &data);
|
||||||
|
virtual void getlayoutHA();
|
||||||
|
virtual void deleteFromHOMEd();
|
||||||
|
virtual void getlayoutHOMEd();
|
||||||
|
|
||||||
|
//bool HOMEd = false;
|
||||||
|
//bool HA = false;
|
||||||
|
//String HOMEdTopic;
|
||||||
|
|
||||||
|
};
|
||||||
@@ -59,6 +59,8 @@ class IoTItem {
|
|||||||
//virtual IoTBench* getBenchmark();
|
//virtual IoTBench* getBenchmark();
|
||||||
virtual IoTBench*getBenchmarkTask();
|
virtual IoTBench*getBenchmarkTask();
|
||||||
virtual IoTBench*getBenchmarkLoad();
|
virtual IoTBench*getBenchmarkLoad();
|
||||||
|
virtual IoTBench*getHADiscovery();
|
||||||
|
virtual IoTBench*getHOMEdDiscovery();
|
||||||
virtual unsigned long getRtcUnixTime();
|
virtual unsigned long getRtcUnixTime();
|
||||||
|
|
||||||
// делаем доступным модулям отправку сообщений в телеграм
|
// делаем доступным модулям отправку сообщений в телеграм
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ void* getAPI(String subtype, String params);
|
|||||||
|
|
||||||
void configure(String path) {
|
void configure(String path) {
|
||||||
File file = seekFile(path);
|
File file = seekFile(path);
|
||||||
|
if (!file) {
|
||||||
|
SerialPrint(F("E"), F("FS"), F("configure file open error"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
file.find("[");
|
file.find("[");
|
||||||
while (file.available()) {
|
while (file.available()) {
|
||||||
String jsonArrayElement = file.readStringUntil('}') + "}";
|
String jsonArrayElement = file.readStringUntil('}') + "}";
|
||||||
@@ -36,6 +40,9 @@ void configure(String path) {
|
|||||||
// пробуем спросить драйвер Benchmark
|
// пробуем спросить драйвер Benchmark
|
||||||
if (driver = myIoTItem->getBenchmarkTask()) benchTaskItem = ((IoTBench*)driver);
|
if (driver = myIoTItem->getBenchmarkTask()) benchTaskItem = ((IoTBench*)driver);
|
||||||
if (driver = myIoTItem->getBenchmarkLoad()) benchLoadItem = ((IoTBench*)driver);
|
if (driver = myIoTItem->getBenchmarkLoad()) benchLoadItem = ((IoTBench*)driver);
|
||||||
|
// пробуем спросить драйвер для интеграций
|
||||||
|
if (driver = myIoTItem->getHOMEdDiscovery()) HOMEdDiscovery = ((IoTDiscovery*)driver);
|
||||||
|
if (driver = myIoTItem->getHADiscovery()) HADiscovery = ((IoTDiscovery*)driver);
|
||||||
// пробуем спросить драйвер Telegram_v2
|
// пробуем спросить драйвер Telegram_v2
|
||||||
if (driver = myIoTItem->getTlgrmDriver()) tlgrmItem = (IoTItem*)driver;
|
if (driver = myIoTItem->getTlgrmDriver()) tlgrmItem = (IoTItem*)driver;
|
||||||
IoTItems.push_back(myIoTItem);
|
IoTItems.push_back(myIoTItem);
|
||||||
@@ -59,8 +66,13 @@ void clearConfigure() {
|
|||||||
if (*it) delete *it;
|
if (*it) delete *it;
|
||||||
}
|
}
|
||||||
IoTItems.clear();
|
IoTItems.clear();
|
||||||
|
#ifdef libretiny
|
||||||
|
valuesFlashJson.remove(0, valuesFlashJson.length());
|
||||||
|
#else
|
||||||
valuesFlashJson.clear();
|
valuesFlashJson.clear();
|
||||||
|
#endif
|
||||||
benchTaskItem = nullptr;
|
benchTaskItem = nullptr;
|
||||||
benchLoadItem = nullptr;
|
benchLoadItem = nullptr;
|
||||||
|
HOMEdDiscovery = nullptr;
|
||||||
|
HADiscovery = nullptr;
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,9 @@ ESP8266WebServer HTTP(80);
|
|||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
WebServer HTTP(80);
|
WebServer HTTP(80);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef libretiny
|
||||||
|
WebServer HTTP(80);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef STANDARD_WEB_SOCKETS
|
#ifdef STANDARD_WEB_SOCKETS
|
||||||
@@ -35,6 +38,8 @@ IoTItem* rtcItem = nullptr;
|
|||||||
IoTItem* tlgrmItem = nullptr;
|
IoTItem* tlgrmItem = nullptr;
|
||||||
IoTBench* benchTaskItem = nullptr;
|
IoTBench* benchTaskItem = nullptr;
|
||||||
IoTBench* benchLoadItem = nullptr;
|
IoTBench* benchLoadItem = nullptr;
|
||||||
|
IoTDiscovery* HOMEdDiscovery = nullptr;
|
||||||
|
IoTDiscovery* HADiscovery = nullptr;
|
||||||
String settingsFlashJson = "{}"; // переменная в которой хранятся все настройки, находится в оперативной памяти и синхронизированна с flash памятью
|
String settingsFlashJson = "{}"; // переменная в которой хранятся все настройки, находится в оперативной памяти и синхронизированна с flash памятью
|
||||||
String valuesFlashJson = "{}"; // переменная в которой хранятся все значения элементов, которые необходимо сохранить на flash. Находится в оперативной памяти и синхронизированна с flash памятью
|
String valuesFlashJson = "{}"; // переменная в которой хранятся все значения элементов, которые необходимо сохранить на flash. Находится в оперативной памяти и синхронизированна с flash памятью
|
||||||
String errorsHeapJson = "{}"; // переменная в которой хранятся все ошибки, находится в оперативной памяти только
|
String errorsHeapJson = "{}"; // переменная в которой хранятся все ошибки, находится в оперативной памяти только
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "MqttClient.h"
|
#include "MqttClient.h"
|
||||||
|
#include "classes/IoTDiscovery.h"
|
||||||
|
|
||||||
void mqttInit() {
|
void mqttInit() {
|
||||||
mqtt.setCallback(mqttCallback);
|
mqtt.setCallback(mqttCallback);
|
||||||
@@ -59,10 +60,24 @@ boolean mqttConnect() {
|
|||||||
if (!mqtt.connected()) {
|
if (!mqtt.connected()) {
|
||||||
bool connected = false;
|
bool connected = false;
|
||||||
if (mqttUser != "" && mqttPass != "") {
|
if (mqttUser != "" && mqttPass != "") {
|
||||||
connected = mqtt.connect(chipId.c_str(), mqttUser.c_str(), mqttPass.c_str());
|
if (HOMEdDiscovery)
|
||||||
|
{
|
||||||
|
connected = mqtt.connect(chipId.c_str(), mqttUser.c_str(), mqttPass.c_str(), (HOMEdDiscovery->HOMEdTopic + "/device/custom/" + chipId).c_str(), 1, true, "{\"status\":\"offline\"}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connected = mqtt.connect(chipId.c_str(), mqttUser.c_str(), mqttPass.c_str(), (mqttRootDevice + "/state").c_str(), 1, true, "{\"status\":\"offline\"}");
|
||||||
|
}
|
||||||
SerialPrint("i", F("MQTT"), F("Go to connection with login and password"));
|
SerialPrint("i", F("MQTT"), F("Go to connection with login and password"));
|
||||||
} else if (mqttUser == "" && mqttPass == "") {
|
} else if (mqttUser == "" && mqttPass == "") {
|
||||||
connected = mqtt.connect(chipId.c_str());
|
if (HOMEdDiscovery)
|
||||||
|
{
|
||||||
|
connected = mqtt.connect(chipId.c_str(), (HOMEdDiscovery->HOMEdTopic + "/device/custom/" + chipId).c_str(), 1, true, "{\"status\":\"offline\"}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connected = mqtt.connect(chipId.c_str(), (mqttRootDevice + "/state").c_str(), 1, true, "{\"status\":\"offline\"}");
|
||||||
|
}
|
||||||
SerialPrint("i", F("MQTT"), F("Go to connection without login and password"));
|
SerialPrint("i", F("MQTT"), F("Go to connection without login and password"));
|
||||||
} else {
|
} else {
|
||||||
SerialPrint("E", F("MQTT"), F("✖ Login or password missed"));
|
SerialPrint("E", F("MQTT"), F("✖ Login or password missed"));
|
||||||
@@ -129,17 +144,33 @@ void mqttSubscribe() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(HOMEdDiscovery)
|
||||||
|
HOMEdDiscovery->mqttSubscribeDiscovery();
|
||||||
|
if(HADiscovery)
|
||||||
|
HADiscovery->mqttSubscribeDiscovery();
|
||||||
|
// оттправляем все статусы
|
||||||
|
if(HOMEdDiscovery || HADiscovery)
|
||||||
|
{
|
||||||
|
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it)
|
||||||
|
{
|
||||||
|
if ((*it)->iAmLocal)
|
||||||
|
{
|
||||||
|
publishStatusMqtt((*it)->getID(), (*it)->getValue());
|
||||||
|
(*it)->onMqttWsAppConnectEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mqttSubscribeExternal(String topic, bool usePrefix) {
|
void mqttSubscribeExternal(String topic, bool usePrefix) {
|
||||||
|
|
||||||
// SerialPrint("i", F("MQTT"), mqttRootDevice);
|
// SerialPrint("i", F("MQTT"), mqttRootDevice);
|
||||||
String _sb_topic = topic;
|
String _sb_topic = topic;
|
||||||
if (usePrefix)
|
if (usePrefix)
|
||||||
{
|
{
|
||||||
_sb_topic = mqttPrefix + "/" + topic;
|
_sb_topic = mqttPrefix + "/" + topic;
|
||||||
}
|
}
|
||||||
mqtt.subscribe(_sb_topic.c_str());
|
mqtt.subscribe(_sb_topic.c_str());
|
||||||
|
|
||||||
SerialPrint("i", F("MQTT"), ("subscribed external " + _sb_topic).c_str());
|
SerialPrint("i", F("MQTT"), ("subscribed external " + _sb_topic).c_str());
|
||||||
}
|
}
|
||||||
@@ -253,6 +284,10 @@ boolean publishChartMqtt(const String& topic, const String& data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean publishStatusMqtt(const String& topic, const String& data) {
|
boolean publishStatusMqtt(const String& topic, const String& data) {
|
||||||
|
if (HOMEdDiscovery)
|
||||||
|
{
|
||||||
|
HOMEdDiscovery->publishStatusHOMEd(topic, data);
|
||||||
|
}
|
||||||
String path = mqttRootDevice + "/" + topic + "/status";
|
String path = mqttRootDevice + "/" + topic + "/status";
|
||||||
String json = "{}";
|
String json = "{}";
|
||||||
jsonWriteStr(json, "status", data);
|
jsonWriteStr(json, "status", data);
|
||||||
@@ -322,47 +357,47 @@ void handleMqttStatus(bool send, int state) {
|
|||||||
const String getStateStr(int e) {
|
const String getStateStr(int e) {
|
||||||
switch (e) {
|
switch (e) {
|
||||||
case -4: // Нет ответа от сервера
|
case -4: // Нет ответа от сервера
|
||||||
return F("e1");
|
return F("e1");
|
||||||
break;
|
break;
|
||||||
case -3: // Соединение было разорвано
|
case -3: // Соединение было разорвано
|
||||||
return F("e2");
|
return F("e2");
|
||||||
break;
|
break;
|
||||||
case -2: // Ошибка соединения. Обычно возникает когда неверно указано название сервера MQTT
|
case -2: // Ошибка соединения. Обычно возникает когда неверно указано название сервера MQTT
|
||||||
return F("e3");
|
return F("e3");
|
||||||
break;
|
break;
|
||||||
case -1: // Клиент был отключен
|
case -1: // Клиент был отключен
|
||||||
return F("e4");
|
return F("e4");
|
||||||
break;
|
break;
|
||||||
case 0: // подключено
|
case 0: // подключено
|
||||||
return F("e5");
|
return F("e5");
|
||||||
break;
|
break;
|
||||||
case 1: // Ошибка версии
|
case 1: // Ошибка версии
|
||||||
return F("e6");
|
return F("e6");
|
||||||
break;
|
break;
|
||||||
case 2: // Отклонен идентификатор
|
case 2: // Отклонен идентификатор
|
||||||
return F("e7");
|
return F("e7");
|
||||||
break;
|
break;
|
||||||
case 3: // Не могу установить соединение
|
case 3: // Не могу установить соединение
|
||||||
return F("e8");
|
return F("e8");
|
||||||
break;
|
break;
|
||||||
case 4: // Неправильное имя пользователя/пароль
|
case 4: // Неправильное имя пользователя/пароль
|
||||||
return F("e9");
|
return F("e9");
|
||||||
break;
|
break;
|
||||||
case 5: // Не авторизован для подключения
|
case 5: // Не авторизован для подключения
|
||||||
return F("e10");
|
return F("e10");
|
||||||
break;
|
break;
|
||||||
case 6: // Название сервера пустое
|
case 6: // Название сервера пустое
|
||||||
return F("e11");
|
return F("e11");
|
||||||
break;
|
break;
|
||||||
case 7: // Имя пользователя или пароль пустые
|
case 7: // Имя пользователя или пароль пустые
|
||||||
return F("e12");
|
return F("e12");
|
||||||
break;
|
break;
|
||||||
case 8: // Подключение в процессе
|
case 8: // Подключение в процессе
|
||||||
return F("e13");
|
return F("e13");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return F("unk");
|
return F("unk");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
32
src/classes/IoTDiscovery.cpp
Normal file
32
src/classes/IoTDiscovery.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include "Global.h"
|
||||||
|
#include "classes/IoTDiscovery.h"
|
||||||
|
#include "IoTDiscovery.h"
|
||||||
|
|
||||||
|
IoTDiscovery::IoTDiscovery(const String ¶meters) : IoTItem(parameters)
|
||||||
|
{
|
||||||
|
/* int _tx, _rx, _speed, _line;
|
||||||
|
jsonRead(parameters, "rx", _rx);
|
||||||
|
jsonRead(parameters, "tx", _tx);
|
||||||
|
jsonRead(parameters, "speed", _speed);
|
||||||
|
jsonRead(parameters, "line", _line);
|
||||||
|
*/
|
||||||
|
//ChipId = getChipId();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IoTDiscovery::publishStatusHOMEd(const String &topic, const String &data) {}
|
||||||
|
void IoTDiscovery::getlayoutHA() {}
|
||||||
|
void IoTDiscovery::getlayoutHOMEd() {}
|
||||||
|
void IoTDiscovery::deleteFromHOMEd() {}
|
||||||
|
void IoTDiscovery::mqttSubscribeDiscovery(){}
|
||||||
|
|
||||||
|
boolean IoTDiscovery::publishRetain(const String &topic, const String &data)
|
||||||
|
{
|
||||||
|
if (mqtt.beginPublish(topic.c_str(), data.length(), true))
|
||||||
|
{
|
||||||
|
mqtt.print(data);
|
||||||
|
return mqtt.endPublish();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IoTDiscovery::~IoTDiscovery() {}
|
||||||
@@ -258,6 +258,14 @@ IoTBench *IoTItem::getBenchmarkLoad()
|
|||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
IoTBench *IoTItem::getHOMEdDiscovery()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
IoTBench *IoTItem::getHADiscovery()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
unsigned long IoTItem::getRtcUnixTime()
|
unsigned long IoTItem::getRtcUnixTime()
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
242
src/modules/virtual/DiscoveryHA/DiscoveryHA.cpp
Normal file
242
src/modules/virtual/DiscoveryHA/DiscoveryHA.cpp
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
#include "Global.h"
|
||||||
|
#include "classes/IoTDiscovery.h"
|
||||||
|
|
||||||
|
class DiscoveryHA : public IoTDiscovery
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
String _topic = "";
|
||||||
|
bool sendOk = false;
|
||||||
|
// bool topicOk = false;
|
||||||
|
bool HA = false;
|
||||||
|
public:
|
||||||
|
DiscoveryHA(String parameters) : IoTDiscovery(parameters)
|
||||||
|
{
|
||||||
|
_topic = jsonReadStr(parameters, "topic");
|
||||||
|
if (_topic && _topic != "" && _topic != "null")
|
||||||
|
{
|
||||||
|
HA = true;
|
||||||
|
HATopic = _topic;
|
||||||
|
}
|
||||||
|
if (mqttIsConnect() && HA)
|
||||||
|
{
|
||||||
|
#if defined ESP32
|
||||||
|
// пре реконнекте вызывается отправка всех виджетов из файла layout.json в HA
|
||||||
|
// на ESP8266 мало оперативки и это можно делать только до момента конфигурации
|
||||||
|
// mqttReconnect();
|
||||||
|
#endif
|
||||||
|
// sendOk = true;
|
||||||
|
// mqttSubscribeExternal(_topic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
void onMqttRecive(String &topic, String &msg)
|
||||||
|
{
|
||||||
|
if (!HA)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
// обработка топика, на который подписались
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
void doByInterval()
|
||||||
|
{
|
||||||
|
/* // периодически проверяем связь с MQTT брокером и если она появилась, то подписываемся на нужный топик
|
||||||
|
if (mqttIsConnect() && !sendOk && &&topicOk)
|
||||||
|
{
|
||||||
|
sendOk = true;
|
||||||
|
getlayoutHA();
|
||||||
|
publishRetain(mqttRootDevice + "/state", "{\"status\":\"online\"}");
|
||||||
|
//mqttSubscribeExternal(_topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
// если нет коннектас брокером, то сбрасываем флаг подписки, что бы при реконекте заново подписаться
|
||||||
|
if (!mqttIsConnect())
|
||||||
|
sendOk = false; */
|
||||||
|
}
|
||||||
|
/* String getMqttExterSub()
|
||||||
|
{
|
||||||
|
return _topic;
|
||||||
|
} */
|
||||||
|
|
||||||
|
void mqttSubscribeDiscovery()
|
||||||
|
{
|
||||||
|
if (HA)
|
||||||
|
{
|
||||||
|
getlayoutHA();
|
||||||
|
publishRetain(mqttRootDevice + "/state", "{\"status\":\"online\"}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void getlayoutHA()
|
||||||
|
{
|
||||||
|
if (HA)
|
||||||
|
{
|
||||||
|
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("HomeAssistant"));
|
||||||
|
JsonArray arr = doc.as<JsonArray>();
|
||||||
|
for (JsonVariant value : arr)
|
||||||
|
{
|
||||||
|
String dev = selectToMarkerLast(value["topic"].as<String>(), "/");
|
||||||
|
dev.replace(":", "");
|
||||||
|
String HAjson = "";
|
||||||
|
HAjson = "{\"availability\":[{\"topic\": \"" + mqttRootDevice + "/state\",\"value_template\": \"{{ value_json.status }}\"}],\"availability_mode\": \"any\",";
|
||||||
|
HAjson = HAjson + " \"device\": {\"identifiers\": [\"" + value["page"].as<String>() + "\"],";
|
||||||
|
HAjson = HAjson + " \"name\": \" " + value["page"].as<String>() + "\"},";
|
||||||
|
HAjson = HAjson + " \"name\": \"" + value["descr"].as<String>() + "\",";
|
||||||
|
HAjson = HAjson + " \"state_topic\": \"" + value["topic"].as<String>() + "/status\",";
|
||||||
|
HAjson = HAjson + " \"icon\": \"hass:none\",";
|
||||||
|
|
||||||
|
// сенсоры
|
||||||
|
if (value["name"].as<String>() == "anydataTmp")
|
||||||
|
{
|
||||||
|
HAjson = HAjson + " \"value_template\": \"{{ float( value_json.status, default = 0) | default }}\",";
|
||||||
|
HAjson = HAjson + " \"unique_id\": \"" + dev + "\",";
|
||||||
|
HAjson = HAjson + " \"state_class\": \"measurement\",";
|
||||||
|
HAjson = HAjson + " \"unit_of_measurement\": \"°C\"";
|
||||||
|
}
|
||||||
|
else if (value["name"].as<String>() == "anydataHum")
|
||||||
|
{
|
||||||
|
HAjson = HAjson + " \"value_template\": \"{{ float( value_json.status, default = 0) | default }}\",";
|
||||||
|
HAjson = HAjson + " \"unique_id\": \"" + dev + "\",";
|
||||||
|
HAjson = HAjson + " \"state_class\": \"measurement\",";
|
||||||
|
HAjson = HAjson + " \"unit_of_measurement\": \"%\"";
|
||||||
|
}
|
||||||
|
// ввод числа
|
||||||
|
else if (value["name"].as<String>() == "inputDgt")
|
||||||
|
{
|
||||||
|
HAjson = HAjson + " \"value_template\": \"{{ float( value_json.status, default = 0) | default }}\",";
|
||||||
|
HAjson = HAjson + " \"unique_id\": \"" + dev + "\",";
|
||||||
|
HAjson = HAjson + " \"command_topic\": \"" + value["topic"].as<String>() + "/control\",";
|
||||||
|
HAjson = HAjson + " \"mode\": \"box\",";
|
||||||
|
HAjson = HAjson + " \"min\": " + -1000000 + ",";
|
||||||
|
HAjson = HAjson + " \"max\": " + 1000000 + "";
|
||||||
|
}
|
||||||
|
// ввод текста inputTxt
|
||||||
|
else if (value["name"].as<String>() == "inputTxt")
|
||||||
|
{
|
||||||
|
HAjson = HAjson + " \"value_template\": \"{{ value_json.status | default }}\",";
|
||||||
|
HAjson = HAjson + " \"unique_id\": \"" + dev + "\",";
|
||||||
|
HAjson = HAjson + " \"command_topic\": \"" + value["topic"].as<String>() + "/control\"";
|
||||||
|
}
|
||||||
|
// переключатель
|
||||||
|
else if (value["name"].as<String>() == "toggle")
|
||||||
|
{
|
||||||
|
HAjson = HAjson + " \"value_template\": \"{{ value_json.status | default }}\",";
|
||||||
|
HAjson = HAjson + " \"unique_id\": \"" + dev + "\",";
|
||||||
|
HAjson = HAjson + " \"command_topic\": \"" + value["topic"].as<String>() + "/control\",";
|
||||||
|
HAjson = HAjson + " \"device_class\": \"switch\",";
|
||||||
|
HAjson = HAjson + " \"payload_off\": " + 0 + ",";
|
||||||
|
HAjson = HAjson + " \"payload_on\": " + 1 + ",";
|
||||||
|
HAjson = HAjson + " \"state_off\": " + 0 + ",";
|
||||||
|
HAjson = HAjson + " \"state_on\": " + 1 + "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HAjson = HAjson + " \"value_template\": \"{{ value_json.status | default }}\",";
|
||||||
|
HAjson = HAjson + " \"unique_id\": \"" + dev + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
HAjson = HAjson + " }";
|
||||||
|
// "has_entity_name" : false,
|
||||||
|
|
||||||
|
// SerialPrint("E", F("MQTT"), HAjson);
|
||||||
|
// текст
|
||||||
|
if (value["widget"].as<String>() == "anydata")
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!publishRetain(HATopic + "/sensor/" + chipId + "/" + dev + "/config", HAjson))
|
||||||
|
{
|
||||||
|
SerialPrint("E", F("MQTT"), F("Failed publish data to homeassitant"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ввод числа
|
||||||
|
if (value["name"].as<String>() == "inputDgt")
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!publishRetain(HATopic + "/number/" + chipId + "/" + dev + "/config", HAjson))
|
||||||
|
{
|
||||||
|
SerialPrint("E", F("MQTT"), F("Failed publish data to homeassitant"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ввод текста inputTxt
|
||||||
|
if (value["name"].as<String>() == "inputTxt")
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!publishRetain(HATopic + "/text/" + chipId + "/" + dev + "/config", HAjson))
|
||||||
|
{
|
||||||
|
SerialPrint("E", F("MQTT"), F("Failed publish data to homeassitant"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// переключатель
|
||||||
|
if (value["name"].as<String>() == "toggle")
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!publishRetain(HATopic + "/switch/" + chipId + "/" + dev + "/config", HAjson))
|
||||||
|
{
|
||||||
|
SerialPrint("E", F("MQTT"), F("Failed publish data to homeassitant"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
publishRetain(mqttRootDevice + "/state", "{\"status\":\"online\"}");
|
||||||
|
|
||||||
|
for (std::list<IoTItem *>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it)
|
||||||
|
{
|
||||||
|
if ((*it)->iAmLocal)
|
||||||
|
{
|
||||||
|
publishStatusMqtt((*it)->getID(), (*it)->getValue());
|
||||||
|
(*it)->onMqttWsAppConnectEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IoTDiscovery *getBenchmarkTask()
|
||||||
|
{
|
||||||
|
if (HA)
|
||||||
|
return this;
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
~DiscoveryHA(){};
|
||||||
|
};
|
||||||
|
|
||||||
|
void *getAPI_DiscoveryHA(String subtype, String param)
|
||||||
|
{
|
||||||
|
if (subtype == F("DiscoveryHA"))
|
||||||
|
{
|
||||||
|
return new DiscoveryHA(param);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/modules/virtual/DiscoveryHA/modinfo.json
Normal file
39
src/modules/virtual/DiscoveryHA/modinfo.json
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"menuSection": "virtual",
|
||||||
|
"configItem": [
|
||||||
|
{
|
||||||
|
"global": 0,
|
||||||
|
"name": "Discovery of HA",
|
||||||
|
"type": "Reading",
|
||||||
|
"subtype": "DiscoveryHA",
|
||||||
|
"id": "ha",
|
||||||
|
"widget": "",
|
||||||
|
"page": "",
|
||||||
|
"descr": "",
|
||||||
|
"topic": "homeassistant"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"about": {
|
||||||
|
"authorName": "Bubnov Mikhail",
|
||||||
|
"authorContact": "https://t.me/Mit4bmw",
|
||||||
|
"authorGit": "https://github.com/Mit4el",
|
||||||
|
"specialThanks": "@AVAKS",
|
||||||
|
"moduleName": "DiscoveryHA",
|
||||||
|
"moduleVersion": "1.0",
|
||||||
|
"usedRam": {
|
||||||
|
"esp32_4mb": 15,
|
||||||
|
"esp8266_4mb": 15
|
||||||
|
},
|
||||||
|
"title": "DiscoveryHA",
|
||||||
|
"moduleDesc": "Модуль проброса данных в MQTT для HomeAssistant",
|
||||||
|
"propInfo": {
|
||||||
|
"topic":"Топик HomeAssistant"
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
"defActive": false,
|
||||||
|
"usedLibs": {
|
||||||
|
"esp32*": [],
|
||||||
|
"esp82*": []
|
||||||
|
}
|
||||||
|
}
|
||||||
277
src/modules/virtual/DiscoveryHomeD/DiscoveryHomeD.cpp
Normal file
277
src/modules/virtual/DiscoveryHomeD/DiscoveryHomeD.cpp
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/modules/virtual/DiscoveryHomeD/modinfo.json
Normal file
39
src/modules/virtual/DiscoveryHomeD/modinfo.json
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"menuSection": "virtual",
|
||||||
|
"configItem": [
|
||||||
|
{
|
||||||
|
"global": 0,
|
||||||
|
"name": "Discovery of HomeD",
|
||||||
|
"type": "Reading",
|
||||||
|
"subtype": "DiscoveryHomeD",
|
||||||
|
"id": "homed",
|
||||||
|
"widget": "",
|
||||||
|
"page": "",
|
||||||
|
"descr": "",
|
||||||
|
"topic": "homed"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"about": {
|
||||||
|
"authorName": "Bubnov Mikhail",
|
||||||
|
"authorContact": "https://t.me/Mit4bmw",
|
||||||
|
"authorGit": "https://github.com/Mit4el",
|
||||||
|
"specialThanks": "@AVAKS",
|
||||||
|
"moduleName": "DiscoveryHomeD",
|
||||||
|
"moduleVersion": "1.0",
|
||||||
|
"usedRam": {
|
||||||
|
"esp32_4mb": 15,
|
||||||
|
"esp8266_4mb": 15
|
||||||
|
},
|
||||||
|
"title": "DiscoveryHomeD",
|
||||||
|
"moduleDesc": "Модуль проброса данных в MQTT для HOMEd-Custom",
|
||||||
|
"propInfo": {
|
||||||
|
"topic":"Топик службы HOMEd-Custom, например /myRoom/homed"
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
"defActive": false,
|
||||||
|
"usedLibs": {
|
||||||
|
"esp32*": [],
|
||||||
|
"esp82*": []
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user