mirror of
https://github.com/rstrouse/ESPSomfy-RTS.git
synced 2025-12-13 02:52:11 +01:00
Added MQTT auto discovery #180
This commit is contained in:
parent
f3e3553dad
commit
79c7ecccac
10 changed files with 156 additions and 9 deletions
|
|
@ -573,6 +573,7 @@ bool ShadeConfigFile::readSettingsRecord() {
|
||||||
}
|
}
|
||||||
bool ShadeConfigFile::readGroupRecord(SomfyGroup *group) {
|
bool ShadeConfigFile::readGroupRecord(SomfyGroup *group) {
|
||||||
pref.begin("ShadeCodes");
|
pref.begin("ShadeCodes");
|
||||||
|
uint32_t startPos = this->file.position();
|
||||||
group->setGroupId(this->readUInt8(255));
|
group->setGroupId(this->readUInt8(255));
|
||||||
group->groupType = static_cast<group_types>(this->readUInt8(0));
|
group->groupType = static_cast<group_types>(this->readUInt8(0));
|
||||||
group->setRemoteAddress(this->readUInt32(0));
|
group->setRemoteAddress(this->readUInt32(0));
|
||||||
|
|
@ -597,10 +598,15 @@ bool ShadeConfigFile::readGroupRecord(SomfyGroup *group) {
|
||||||
if(group->getGroupId() == 255) group->clear();
|
if(group->getGroupId() == 255) group->clear();
|
||||||
else group->compressLinkedShadeIds();
|
else group->compressLinkedShadeIds();
|
||||||
pref.end();
|
pref.end();
|
||||||
|
if(this->file.position() != startPos + this->header.groupRecordSize) {
|
||||||
|
Serial.println("Reading to end of group record");
|
||||||
|
this->seekChar(CFG_REC_END);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool ShadeConfigFile::readShadeRecord(SomfyShade *shade) {
|
bool ShadeConfigFile::readShadeRecord(SomfyShade *shade) {
|
||||||
pref.begin("ShadeCodes");
|
pref.begin("ShadeCodes");
|
||||||
|
uint32_t startPos = this->file.position();
|
||||||
shade->setShadeId(this->readUInt8(255));
|
shade->setShadeId(this->readUInt8(255));
|
||||||
shade->paired = this->readBool(false);
|
shade->paired = this->readBool(false);
|
||||||
shade->shadeType = static_cast<shade_types>(this->readUInt8(0));
|
shade->shadeType = static_cast<shade_types>(this->readUInt8(0));
|
||||||
|
|
@ -676,6 +682,10 @@ bool ShadeConfigFile::readShadeRecord(SomfyShade *shade) {
|
||||||
}
|
}
|
||||||
if(shade->proto == radio_proto::GP_Remote)
|
if(shade->proto == radio_proto::GP_Remote)
|
||||||
pinMode(shade->gpioMy, OUTPUT);
|
pinMode(shade->gpioMy, OUTPUT);
|
||||||
|
if(this->file.position() != startPos + this->header.shadeRecordSize) {
|
||||||
|
Serial.println("Reading to end of shade record");
|
||||||
|
this->seekChar(CFG_REC_END);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool ShadeConfigFile::loadFile(SomfyShadeController *s, const char *filename) {
|
bool ShadeConfigFile::loadFile(SomfyShadeController *s, const char *filename) {
|
||||||
|
|
|
||||||
|
|
@ -245,21 +245,25 @@ bool MQTTSettings::begin() {
|
||||||
}
|
}
|
||||||
bool MQTTSettings::toJSON(JsonObject &obj) {
|
bool MQTTSettings::toJSON(JsonObject &obj) {
|
||||||
obj["enabled"] = this->enabled;
|
obj["enabled"] = this->enabled;
|
||||||
|
obj["pubDisco"] = this->pubDisco;
|
||||||
obj["protocol"] = this->protocol;
|
obj["protocol"] = this->protocol;
|
||||||
obj["hostname"] = this->hostname;
|
obj["hostname"] = this->hostname;
|
||||||
obj["port"] = this->port;
|
obj["port"] = this->port;
|
||||||
obj["username"] = this->username;
|
obj["username"] = this->username;
|
||||||
obj["password"] = this->password;
|
obj["password"] = this->password;
|
||||||
obj["rootTopic"] = this->rootTopic;
|
obj["rootTopic"] = this->rootTopic;
|
||||||
|
obj["discoTopic"] = this->discoTopic;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool MQTTSettings::fromJSON(JsonObject &obj) {
|
bool MQTTSettings::fromJSON(JsonObject &obj) {
|
||||||
if(obj.containsKey("enabled")) this->enabled = obj["enabled"];
|
if(obj.containsKey("enabled")) this->enabled = obj["enabled"];
|
||||||
|
if(obj.containsKey("pubDisco")) this->pubDisco = obj["pubDisco"];
|
||||||
this->parseValueString(obj, "protocol", this->protocol, sizeof(this->protocol));
|
this->parseValueString(obj, "protocol", this->protocol, sizeof(this->protocol));
|
||||||
this->parseValueString(obj, "hostname", this->hostname, sizeof(this->hostname));
|
this->parseValueString(obj, "hostname", this->hostname, sizeof(this->hostname));
|
||||||
this->parseValueString(obj, "username", this->username, sizeof(this->username));
|
this->parseValueString(obj, "username", this->username, sizeof(this->username));
|
||||||
this->parseValueString(obj, "password", this->password, sizeof(this->password));
|
this->parseValueString(obj, "password", this->password, sizeof(this->password));
|
||||||
this->parseValueString(obj, "rootTopic", this->rootTopic, sizeof(this->rootTopic));
|
this->parseValueString(obj, "rootTopic", this->rootTopic, sizeof(this->rootTopic));
|
||||||
|
this->parseValueString(obj, "discoTopic", this->discoTopic, sizeof(this->discoTopic));
|
||||||
if(obj.containsKey("port")) this->port = obj["port"];
|
if(obj.containsKey("port")) this->port = obj["port"];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -273,6 +277,8 @@ bool MQTTSettings::save() {
|
||||||
pref.putString("password", this->password);
|
pref.putString("password", this->password);
|
||||||
pref.putString("rootTopic", this->rootTopic);
|
pref.putString("rootTopic", this->rootTopic);
|
||||||
pref.putBool("enabled", this->enabled);
|
pref.putBool("enabled", this->enabled);
|
||||||
|
pref.putBool("pubDisco", this->pubDisco);
|
||||||
|
pref.putString("discoTopic", this->discoTopic);
|
||||||
pref.end();
|
pref.end();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -285,6 +291,8 @@ bool MQTTSettings::load() {
|
||||||
pref.getString("password", this->password, sizeof(this->password));
|
pref.getString("password", this->password, sizeof(this->password));
|
||||||
pref.getString("rootTopic", this->rootTopic, sizeof(this->rootTopic));
|
pref.getString("rootTopic", this->rootTopic, sizeof(this->rootTopic));
|
||||||
this->enabled = pref.getBool("enabled", false);
|
this->enabled = pref.getBool("enabled", false);
|
||||||
|
this->pubDisco = pref.getBool("pubDisco", false);
|
||||||
|
pref.getString("discoTopic", this->discoTopic, sizeof(this->discoTopic));
|
||||||
pref.end();
|
pref.end();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -131,12 +131,14 @@ class SecuritySettings: BaseSettings {
|
||||||
class MQTTSettings: BaseSettings {
|
class MQTTSettings: BaseSettings {
|
||||||
public:
|
public:
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
|
bool pubDisco = false;
|
||||||
char hostname[65] = "ESPSomfyRTS";
|
char hostname[65] = "ESPSomfyRTS";
|
||||||
char protocol[10] = "mqtt://";
|
char protocol[10] = "mqtt://";
|
||||||
uint16_t port = 1883;
|
uint16_t port = 1883;
|
||||||
char username[33] = "";
|
char username[33] = "";
|
||||||
char password[33] = "";
|
char password[33] = "";
|
||||||
char rootTopic[65] = "";
|
char rootTopic[65] = "";
|
||||||
|
char discoTopic[65] = "homeassistant";
|
||||||
bool begin();
|
bool begin();
|
||||||
bool save();
|
bool save();
|
||||||
bool load();
|
bool load();
|
||||||
|
|
|
||||||
21
MQTT.cpp
21
MQTT.cpp
|
|
@ -309,6 +309,27 @@ bool MQTTClass::publish(const char *topic, JsonObject &obj, bool retain) {
|
||||||
serializeJson(obj, g_content, sizeof(g_content));
|
serializeJson(obj, g_content, sizeof(g_content));
|
||||||
return this->publish(topic, g_content, retain);
|
return this->publish(topic, g_content, retain);
|
||||||
}
|
}
|
||||||
|
bool MQTTClass::publishBuffer(const char *topic, uint8_t *data, uint16_t len, bool retain) {
|
||||||
|
size_t res;
|
||||||
|
uint16_t offset = 0;
|
||||||
|
uint16_t to_write = len;
|
||||||
|
uint16_t buff_len;
|
||||||
|
mqttClient.beginPublish(topic, len, retain);
|
||||||
|
do {
|
||||||
|
buff_len = to_write;
|
||||||
|
if(buff_len > 128) buff_len = 128;
|
||||||
|
res = mqttClient.write(data+offset, buff_len);
|
||||||
|
offset += buff_len;
|
||||||
|
to_write -= buff_len;
|
||||||
|
} while(res == buff_len && to_write > 0);
|
||||||
|
mqttClient.endPublish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool MQTTClass::publishDisco(const char *topic, JsonObject &obj, bool retain) {
|
||||||
|
serializeJson(obj, g_content, sizeof(g_content));
|
||||||
|
this->publishBuffer(topic, (uint8_t *)g_content, strlen(g_content), retain);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
bool MQTTClass::publish(const char *topic, int8_t val, bool retain) {
|
bool MQTTClass::publish(const char *topic, int8_t val, bool retain) {
|
||||||
snprintf(g_content, sizeof(g_content), "%d", val);
|
snprintf(g_content, sizeof(g_content), "%d", val);
|
||||||
return this->publish(topic, g_content, retain);
|
return this->publish(topic, g_content, retain);
|
||||||
|
|
|
||||||
2
MQTT.h
2
MQTT.h
|
|
@ -24,6 +24,8 @@ class MQTTClass {
|
||||||
bool publish(const char *topic, uint32_t val, bool retain = false);
|
bool publish(const char *topic, uint32_t val, bool retain = false);
|
||||||
bool publish(const char *topic, uint16_t val, bool retain = false);
|
bool publish(const char *topic, uint16_t val, bool retain = false);
|
||||||
bool publish(const char *topic, bool val, bool retain = false);
|
bool publish(const char *topic, bool val, bool retain = false);
|
||||||
|
bool publishBuffer(const char *topic, uint8_t *data, uint16_t len, bool retain = false);
|
||||||
|
bool publishDisco(const char *topic, JsonObject &obj, bool retain = false);
|
||||||
bool subscribe(const char *topic);
|
bool subscribe(const char *topic);
|
||||||
bool unsubscribe(const char *topic);
|
bool unsubscribe(const char *topic);
|
||||||
static void receive(const char *topic, byte *payload, uint32_t length);
|
static void receive(const char *topic, byte *payload, uint32_t length);
|
||||||
|
|
|
||||||
92
Somfy.cpp
92
Somfy.cpp
|
|
@ -1299,8 +1299,99 @@ void SomfyShade::publishState() {
|
||||||
mqtt.publish(topic, isWindy);
|
mqtt.publish(topic, isWindy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void SomfyShade::publishDisco() {
|
||||||
|
if(!mqtt.connected() || !settings.MQTT.pubDisco) return;
|
||||||
|
char topic[128] = "";
|
||||||
|
DynamicJsonDocument doc(2048);
|
||||||
|
JsonObject obj = doc.to<JsonObject>();
|
||||||
|
snprintf(topic, sizeof(topic), "%s/shades/%d", settings.MQTT.rootTopic, this->shadeId);
|
||||||
|
obj["~"] = topic;
|
||||||
|
JsonObject dobj = obj.createNestedObject("device");
|
||||||
|
dobj["hw_version"] = settings.fwVersion.name;
|
||||||
|
dobj["name"] = settings.hostname;
|
||||||
|
dobj["mf"] = "rstrouse";
|
||||||
|
JsonArray arrids = dobj.createNestedArray("identifiers");
|
||||||
|
//snprintf(topic, sizeof(topic), "mqtt_espsomfyrts_%s_shade%d", settings.serverId, this->shadeId);
|
||||||
|
snprintf(topic, sizeof(topic), "mqtt_espsomfyrts_%s", settings.serverId);
|
||||||
|
arrids.add(topic);
|
||||||
|
//snprintf(topic, sizeof(topic), "ESPSomfy-RTS_%s", settings.serverId);
|
||||||
|
dobj["via_device"] = topic;
|
||||||
|
dobj["model"] = "ESPSomfy-RTS MQTT";
|
||||||
|
snprintf(topic, sizeof(topic), "%s/status", settings.MQTT.rootTopic);
|
||||||
|
obj["availability_topic"] = topic;
|
||||||
|
obj["payload_available"] = "online";
|
||||||
|
obj["payload_not_available"] = "offline";
|
||||||
|
obj["name"] = this->name;
|
||||||
|
snprintf(topic, sizeof(topic), "mqtt_%s_shade%d", settings.serverId, this->shadeId);
|
||||||
|
obj["unique_id"] = topic;
|
||||||
|
switch(this->shadeType) {
|
||||||
|
case shade_types::blind:
|
||||||
|
obj["device_class"] = "blind";
|
||||||
|
break;
|
||||||
|
case shade_types::ldrapery:
|
||||||
|
case shade_types::rdrapery:
|
||||||
|
case shade_types::cdrapery:
|
||||||
|
obj["device_class"] = "curtain";
|
||||||
|
break;
|
||||||
|
case shade_types::garage1:
|
||||||
|
case shade_types::garage3:
|
||||||
|
obj["device_class"] = "garage";
|
||||||
|
break;
|
||||||
|
case shade_types::awning:
|
||||||
|
obj["device_class"] = "awning";
|
||||||
|
break;
|
||||||
|
case shade_types::shutter:
|
||||||
|
obj["device_class"] = "shutter";
|
||||||
|
break;
|
||||||
|
case shade_types::drycontact:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
obj["device_class"] = "shade";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(this->shadeType != shade_types::drycontact) {
|
||||||
|
if(this->tiltType != tilt_types::tiltonly) {
|
||||||
|
obj["command_topic"] = "~/direction/set";
|
||||||
|
obj["position_topic"] = "~/position";
|
||||||
|
obj["set_position_topic"] = "~/target/set";
|
||||||
|
obj["state_topic"] = "~/direction";
|
||||||
|
obj["payload_close"] = "1";
|
||||||
|
obj["payload_open"] = "-1";
|
||||||
|
obj["payload_stop"] = "0";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj["payload_close"] = nullptr;
|
||||||
|
obj["payload_open"] = nullptr;
|
||||||
|
obj["payload_stop"] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->tiltType != tilt_types::none) {
|
||||||
|
obj["tilt_command_topic"] = "~/tiltTarget/set";
|
||||||
|
obj["tilt_status_topic"] = "~/tiltPosition";
|
||||||
|
}
|
||||||
|
obj["position_open"] = 0;
|
||||||
|
obj["position_closed"] = 100;
|
||||||
|
obj["state_closing"] = "1";
|
||||||
|
obj["state_opening"] = "-1";
|
||||||
|
obj["state_stopped"] = "0";
|
||||||
|
snprintf(topic, sizeof(topic), "%s/cover/%d/config", settings.MQTT.discoTopic, this->shadeId);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
obj["payload_on"] = 100;
|
||||||
|
obj["payload_off"] = 0;
|
||||||
|
obj["state_off"] = 0;
|
||||||
|
obj["state_on"] = 100;
|
||||||
|
obj["state_topic"] = "~/position";
|
||||||
|
obj["command_topic"] = "~/target/set";
|
||||||
|
snprintf(topic, sizeof(topic), "%s/switch/%d/config", settings.MQTT.discoTopic, this->shadeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj["enabled_by_default"] = true;
|
||||||
|
mqtt.publishDisco(topic, obj);
|
||||||
|
}
|
||||||
void SomfyShade::publish() {
|
void SomfyShade::publish() {
|
||||||
if(mqtt.connected()) {
|
if(mqtt.connected()) {
|
||||||
|
this->publishDisco();
|
||||||
char topic[32];
|
char topic[32];
|
||||||
snprintf(topic, sizeof(topic), "shades/%u/shadeId", this->shadeId);
|
snprintf(topic, sizeof(topic), "shades/%u/shadeId", this->shadeId);
|
||||||
mqtt.publish(topic, this->shadeId);
|
mqtt.publish(topic, this->shadeId);
|
||||||
|
|
@ -2511,6 +2602,7 @@ bool SomfyShade::save() {
|
||||||
pref.end();
|
pref.end();
|
||||||
}
|
}
|
||||||
this->commit();
|
this->commit();
|
||||||
|
this->publishDisco();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool SomfyGroup::save() { somfy.commit(); return true; }
|
bool SomfyGroup::save() { somfy.commit(); return true; }
|
||||||
|
|
|
||||||
1
Somfy.h
1
Somfy.h
|
|
@ -319,6 +319,7 @@ class SomfyShade : public SomfyRemote {
|
||||||
bool publish(const char *topic, uint32_t val, bool retain = false);
|
bool publish(const char *topic, uint32_t val, bool retain = false);
|
||||||
bool publish(const char *topic, uint16_t val, bool retain = false);
|
bool publish(const char *topic, uint16_t val, bool retain = false);
|
||||||
bool publish(const char *topic, bool val, bool retain = false);
|
bool publish(const char *topic, bool val, bool retain = false);
|
||||||
|
void publishDisco();
|
||||||
};
|
};
|
||||||
class SomfyGroup : public SomfyRemote {
|
class SomfyGroup : public SomfyRemote {
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -245,9 +245,15 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div id="divMQTT" class="subtab-content" style="display:none;">
|
<div id="divMQTT" class="subtab-content" style="display:none;">
|
||||||
<div class="field-group" style="vertical-align:middle;">
|
<div class="field-group" style="vertical-align:middle;margin-top:-20px;">
|
||||||
<input id="cbMqttEnabled" name="mqtt-enabled" type="checkbox" data-bind="mqtt.enabled" style="display:inline-block;" />
|
<div class="field-group" style="display:inline-block;width:auto;">
|
||||||
<label for="cbMqttEnabled" style="display:inline-block;cursor:pointer;">Enable MQTT client</label>
|
<input id="cbMqttEnabled" name="mqtt-enabled" type="checkbox" data-bind="mqtt.enabled" style="display:inline-block;" />
|
||||||
|
<label for="cbMqttEnabled" style="display:inline-block;cursor:pointer;">Enable MQTT client</label>
|
||||||
|
</div>
|
||||||
|
<div class="field-group" style="display:inline-block;width:auto;float:right;">
|
||||||
|
<input id="cbPubDisco" name="pub-disco" type="checkbox" data-bind="mqtt.pubDisco" style="display:inline-block;margin-left:7px;" onclick="document.getElementById('divDiscoveryTopic').style.display = this.checked ? '' : 'none'" />
|
||||||
|
<label for="cbPubDisco" style="display:inline-block;cursor:pointer;">Publish Discovery</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field-group1" style="white-space:nowrap;">
|
<div class="field-group1" style="white-space:nowrap;">
|
||||||
<select name="mqtt-protocol" data-bind="mqtt.protocol" style="width:54px;">
|
<select name="mqtt-protocol" data-bind="mqtt.protocol" style="width:54px;">
|
||||||
|
|
@ -271,6 +277,10 @@
|
||||||
<input id="fldMqttTopic" name="mqtt-topic" type="text" length=64 data-bind="mqtt.rootTopic" placeholder="Root Topic">
|
<input id="fldMqttTopic" name="mqtt-topic" type="text" length=64 data-bind="mqtt.rootTopic" placeholder="Root Topic">
|
||||||
<label for="fldMqttTopic">Root Topic</label>
|
<label for="fldMqttTopic">Root Topic</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="field-group" id="divDiscoveryTopic" style="display:none;">
|
||||||
|
<input id="fldDiscoTopic" name="disco-topic" type="text" length=64 data-bind="mqtt.discoTopic" placeholder="Discovery Topic">
|
||||||
|
<label for="fldDiscoTopic">Discovery Topic</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="button-container">
|
<div class="button-container">
|
||||||
<button id="btnConnectMQTT" type="button" onclick="mqtt.connectMQTT();">Save MQTT Settings</button>
|
<button id="btnConnectMQTT" type="button" onclick="mqtt.connectMQTT();">Save MQTT Settings</button>
|
||||||
|
|
@ -785,11 +795,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="divLoginPassword" style="display:none;" onkeyup="if (event.code === 'Enter') security.login();">
|
<div id="divLoginPassword" style="display:none;" onkeyup="if (event.code === 'Enter') security.login();">
|
||||||
<div class="field-group">
|
<div class="field-group">
|
||||||
<input id="fldLoginUsername" name="username" type="text" data-bind="login.username" length=32 placeholder="Username"/>
|
<input id="fldLoginUsername" name="username" type="text" data-bind="login.username" length=32 placeholder="Username" />
|
||||||
<label for="fldLoginUsername">Username</label>
|
<label for="fldLoginUsername">Username</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="field-group">
|
<div class="field-group">
|
||||||
<input id="fldLoginPassword" name="password" type="password" data-bind="login.password" length=32 placeholder="Password"/>
|
<input id="fldLoginPassword" name="password" type="password" data-bind="login.password" length=32 placeholder="Password" />
|
||||||
<label for="fldLoginPassword">Password</label>
|
<label for="fldLoginPassword">Password</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -853,7 +863,7 @@
|
||||||
mouseDown = false;
|
mouseDown = false;
|
||||||
});
|
});
|
||||||
(async () => { await init(); })();
|
(async () => { await init(); })();
|
||||||
/*
|
/*
|
||||||
security.init();
|
security.init();
|
||||||
//(async () => { await general.init(); })();
|
//(async () => { await general.init(); })();
|
||||||
general.init();
|
general.init();
|
||||||
|
|
@ -868,9 +878,9 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
//ui.toElement(document.getElementById('divContainer'), o);
|
//ui.toElement(document.getElementById('divContainer'), o);
|
||||||
//console.log(ui.fromElement(document.getElementById('divContainer')));
|
//console.log(ui.fromElement(document.getElementById('divContainer')));
|
||||||
//(async () => { await initSockets(); })();
|
//(async () => { await initSockets(); })();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -3947,6 +3947,7 @@ class MQTT {
|
||||||
else {
|
else {
|
||||||
console.log(settings);
|
console.log(settings);
|
||||||
ui.toElement(document.getElementById('divMQTT'), { mqtt: settings });
|
ui.toElement(document.getElementById('divMQTT'), { mqtt: settings });
|
||||||
|
document.getElementById('divDiscoveryTopic').style.display = settings.pubDisco ? '' : 'none';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue