diff --git a/ConfigSettings.h b/ConfigSettings.h index a4ba0f1..ead14cc 100644 --- a/ConfigSettings.h +++ b/ConfigSettings.h @@ -3,7 +3,7 @@ #ifndef configsettings_h #define configsettings_h -#define FW_VERSION "v2.2.2" +#define FW_VERSION "v2.2.3a" enum DeviceStatus { DS_OK = 0, DS_ERROR = 1, diff --git a/MQTT.cpp b/MQTT.cpp index 2f90566..72ae7b8 100644 --- a/MQTT.cpp +++ b/MQTT.cpp @@ -309,6 +309,22 @@ bool MQTTClass::publish(const char *topic, JsonObject &obj, bool retain) { serializeJson(obj, g_content, sizeof(g_content)); return this->publish(topic, g_content, retain); } +bool MQTTClass::unpublish(const char *topic) { + if(mqttClient.connected()) { + char top[128]; + if(strlen(settings.MQTT.rootTopic) > 0) + snprintf(top, sizeof(top), "%s/%s", settings.MQTT.rootTopic, topic); + else + strlcpy(top, topic, sizeof(top)); + mqttClient.publish(top, (const uint8_t *)"", 0, true); + return true; + } + return false; + +// mqttClient.beginPublish(topic, 0, true); +// mqttClient.endPublish(); +} + bool MQTTClass::publishBuffer(const char *topic, uint8_t *data, uint16_t len, bool retain) { size_t res; uint16_t offset = 0; diff --git a/MQTT.h b/MQTT.h index 98a86a1..073c943 100644 --- a/MQTT.h +++ b/MQTT.h @@ -15,6 +15,7 @@ class MQTTClass { bool disconnect(); bool connected(); void reset(); + bool unpublish(const char *topic); bool publish(const char *topic, const char *payload, bool retain = false); bool publish(const char *topic, JsonDocument &doc, bool retain = false); bool publish(const char *topic, JsonArray &arr, bool retain = false); diff --git a/Somfy.cpp b/Somfy.cpp index b375b97..db0ea89 100644 --- a/Somfy.cpp +++ b/Somfy.cpp @@ -1303,16 +1303,16 @@ void SomfyShade::load() { } void SomfyShade::publishState() { if(mqtt.connected()) { - this->publish("position", this->transformPosition(this->currentPos)); - this->publish("direction", this->direction); - this->publish("target", this->transformPosition(this->target)); + this->publish("position", this->transformPosition(this->currentPos), true); + this->publish("direction", this->direction, true); + this->publish("target", this->transformPosition(this->target), true); this->publish("lastRollingCode", this->lastRollingCode); - this->publish("mypos", this->transformPosition(this->myPos)); - this->publish("myTiltPos", this->transformPosition(this->myTiltPos)); + this->publish("mypos", this->transformPosition(this->myPos), true); + this->publish("myTiltPos", this->transformPosition(this->myTiltPos), true); if(this->tiltType != tilt_types::none) { - this->publish("tiltDirection", this->tiltDirection); - this->publish("tiltPosition", this->transformPosition(this->currentTiltPos)); - this->publish("tiltTarget", this->transformPosition(this->tiltTarget)); + this->publish("tiltDirection", this->tiltDirection, true); + this->publish("tiltPosition", this->transformPosition(this->currentTiltPos), true); + this->publish("tiltTarget", this->transformPosition(this->tiltTarget), true); } const uint8_t sunFlag = !!(this->flags & static_cast(somfy_flags_t::SunFlag)); const uint8_t isSunny = !!(this->flags & static_cast(somfy_flags_t::Sunny)); @@ -1450,14 +1450,14 @@ void SomfyShade::publishDisco() { } void SomfyShade::publish() { if(mqtt.connected()) { - this->publish("shadeId", this->shadeId); - this->publish("name", this->name); - this->publish("remoteAddress", this->getRemoteAddress()); - this->publish("shadeType", static_cast(this->shadeType)); - this->publish("tiltType", static_cast(this->tiltType)); - this->publish("flags", this->flags); - this->publish("flipCommands", this->flipCommands); - this->publish("flipPosition", this->flipPosition); + this->publish("shadeId", this->shadeId, true); + this->publish("name", this->name, true); + this->publish("remoteAddress", this->getRemoteAddress(), true); + this->publish("shadeType", static_cast(this->shadeType), true); + this->publish("tiltType", static_cast(this->tiltType), true); + this->publish("flags", this->flags, true); + this->publish("flipCommands", this->flipCommands, true); + this->publish("flipPosition", this->flipPosition, true); this->publishState(); this->publishDisco(); sockEmit.loop(); // Keep our socket alive. @@ -1465,8 +1465,8 @@ void SomfyShade::publish() { } void SomfyGroup::publishState() { if(mqtt.connected()) { - this->publish("direction", this->direction); - this->publish("lastRollingCode", this->lastRollingCode); + this->publish("direction", this->direction, true); + this->publish("lastRollingCode", this->lastRollingCode, true); const uint8_t sunFlag = !!(this->flags & static_cast(somfy_flags_t::SunFlag)); const uint8_t isSunny = !!(this->flags & static_cast(somfy_flags_t::Sunny)); const uint8_t isWindy = !!(this->flags & static_cast(somfy_flags_t::Windy)); @@ -1477,16 +1477,63 @@ void SomfyGroup::publishState() { } void SomfyGroup::publish() { if(mqtt.connected()) { - this->publish("groupId", this->groupId); - this->publish("name", this->name); - this->publish("remoteAddress", this->getRemoteAddress()); - this->publish("groupType", static_cast(this->groupType)); - this->publish("flags", this->flags); - this->publish("sunSensor", this->hasSunSensor()); + this->publish("groupId", this->groupId, true); + this->publish("name", this->name, true); + this->publish("remoteAddress", this->getRemoteAddress(), true); + this->publish("groupType", static_cast(this->groupType), true); + this->publish("flags", this->flags, true); + this->publish("sunSensor", this->hasSunSensor(), true); this->publishState(); } } char mqttTopicBuffer[55]; +void SomfyGroup::unpublish() { SomfyGroup::unpublish(this->groupId); } +void SomfyShade::unpublish() { SomfyShade::unpublish(this->shadeId); } +void SomfyShade::unpublish(uint8_t id) { + if(mqtt.connected()) { + SomfyShade::unpublish(id, "shadeId"); + SomfyShade::unpublish(id, "name"); + SomfyShade::unpublish(id, "remoteAddress"); + SomfyShade::unpublish(id, "shadeType"); + SomfyShade::unpublish(id, "tiltType"); + SomfyShade::unpublish(id, "flags"); + SomfyShade::unpublish(id, "flipCommands"); + SomfyShade::unpublish(id, "flipPosition"); + SomfyShade::unpublish(id, "position"); + SomfyShade::unpublish(id, "direction"); + SomfyShade::unpublish(id, "target"); + SomfyShade::unpublish(id, "lastRollingCode"); + SomfyShade::unpublish(id, "mypos"); + SomfyShade::unpublish(id, "myTiltPos"); + SomfyShade::unpublish(id, "tiltDirection"); + SomfyShade::unpublish(id, "tiltPosition"); + SomfyShade::unpublish(id, "tiltTarget"); + } +} +void SomfyGroup::unpublish(uint8_t id) { + if(mqtt.connected()) { + SomfyGroup::unpublish(id, "groupId"); + SomfyGroup::unpublish(id, "name"); + SomfyGroup::unpublish(id, "remoteAddress"); + SomfyGroup::unpublish(id, "groupType"); + SomfyGroup::unpublish(id, "direction"); + SomfyGroup::unpublish(id, "lastRollingCode"); + SomfyGroup::unpublish(id, "flags"); + SomfyGroup::unpublish(id, "SunSensor"); + } +} +void SomfyGroup::unpublish(uint8_t id, const char *topic) { + if(mqtt.connected()) { + snprintf(mqttTopicBuffer, sizeof(mqttTopicBuffer), "groups/%u/%s", id, topic); + mqtt.unpublish(mqttTopicBuffer); + } +} +void SomfyShade::unpublish(uint8_t id, const char *topic) { + if(mqtt.connected()) { + snprintf(mqttTopicBuffer, sizeof(mqttTopicBuffer), "shades/%u/%s", id, topic); + mqtt.unpublish(mqttTopicBuffer); + } +} bool SomfyShade::publish(const char *topic, int8_t val, bool retain) { if(mqtt.connected()) { snprintf(mqttTopicBuffer, sizeof(mqttTopicBuffer), "shades/%u/%s", this->shadeId, topic); @@ -1495,6 +1542,7 @@ bool SomfyShade::publish(const char *topic, int8_t val, bool retain) { } return false; } + bool SomfyShade::publish(const char *topic, const char *val, bool retain) { if(mqtt.connected()) { snprintf(mqttTopicBuffer, sizeof(mqttTopicBuffer), "shades/%u/%s", this->shadeId, topic); @@ -1621,7 +1669,7 @@ int8_t SomfyShade::p_direction(int8_t dir) { int8_t old = this->direction; if(old != dir) { this->direction = dir; - this->publish("direction", this->direction); + this->publish("direction", this->direction, true); } return old; } @@ -1637,7 +1685,7 @@ int8_t SomfyShade::p_tiltDirection(int8_t dir) { int8_t old = this->tiltDirection; if(old != dir) { this->tiltDirection = dir; - this->publish("tiltDirection", this->tiltDirection); + this->publish("tiltDirection", this->tiltDirection, true); } return old; } @@ -1646,7 +1694,7 @@ float SomfyShade::p_target(float target) { if(old != target) { this->target = target; if(this->transformPosition(old) != this->transformPosition(target)) - this->publish("target", this->transformPosition(this->target)); + this->publish("target", this->transformPosition(this->target), true); } return old; } @@ -1655,7 +1703,7 @@ float SomfyShade::p_tiltTarget(float target) { if(old != target) { this->tiltTarget = target; if(this->transformPosition(old) != this->transformPosition(target)) - this->publish("tiltTarget", this->transformPosition(this->tiltTarget)); + this->publish("tiltTarget", this->transformPosition(this->tiltTarget), true); } return old; } @@ -1665,7 +1713,7 @@ float SomfyShade::p_myPos(float pos) { //if(this->transformPosition(pos) == 0) Serial.println("MyPos = %.2f", pos); this->myPos = pos; if(this->transformPosition(old) != this->transformPosition(pos)) - this->publish("mypos", this->transformPosition(this->myPos)); + this->publish("mypos", this->transformPosition(this->myPos), true); } return old; } @@ -1674,7 +1722,7 @@ float SomfyShade::p_myTiltPos(float pos) { if(old != pos) { this->myTiltPos = pos; if(this->transformPosition(old) != this->transformPosition(pos)) - this->publish("myTiltPos", this->transformPosition(this->myTiltPos)); + this->publish("myTiltPos", this->transformPosition(this->myTiltPos), true); } return old; } @@ -3012,18 +3060,32 @@ void SomfyShadeController::publish() { JsonArray arrGroups = docGroups.to(); for(uint8_t i = 0; i < SOMFY_MAX_SHADES; i++) { SomfyShade *shade = &this->shades[i]; - if(shade->getShadeId() == 255) continue; + if(shade->getShadeId() == 255) { + continue; + } arrShades.add(shade->getShadeId()); shade->publish(); } - mqtt.publish("shades", arrShades); + mqtt.publish("shades", arrShades, true); + for(uint8_t i = 1; i <= SOMFY_MAX_SHADES; i++) { + SomfyShade *shade = this->getShadeById(i); + if(shade) continue; + else { + SomfyShade::unpublish(i); + } + } for(uint8_t i = 0; i < SOMFY_MAX_GROUPS; i++) { SomfyGroup *group = &this->groups[i]; if(group->getGroupId() == 255) continue; arrGroups.add(group->getGroupId()); group->publish(); } - mqtt.publish("groups", arrGroups); + for(uint8_t i = 1; i <= SOMFY_MAX_GROUPS; i++) { + SomfyGroup *group = this->getGroupById(i); + if(group) continue; + else SomfyGroup::unpublish(i); + } + mqtt.publish("groups", arrGroups, true); } uint8_t SomfyShadeController::getNextShadeId() { // There is no shortcut for this since the deletion of @@ -3359,6 +3421,7 @@ bool SomfyShadeController::deleteShade(uint8_t shadeId) { for(uint8_t i = 0; i < SOMFY_MAX_SHADES; i++) { if(this->shades[i].getShadeId() == shadeId) { shades[i].emitState("shadeRemoved"); + shades[i].unpublish(); this->shades[i].clear(); } } @@ -3382,7 +3445,8 @@ bool SomfyShadeController::deleteShade(uint8_t shadeId) { bool SomfyShadeController::deleteGroup(uint8_t groupId) { for(uint8_t i = 0; i < SOMFY_MAX_GROUPS; i++) { if(this->groups[i].getGroupId() == groupId) { - shades[i].emitState("groupRemoved"); + groups[i].emitState("groupRemoved"); + groups[i].unpublish(); this->groups[i].clear(); } } diff --git a/Somfy.h b/Somfy.h index 9a7bc57..40d949b 100644 --- a/Somfy.h +++ b/Somfy.h @@ -300,6 +300,9 @@ class SomfyShade : public SomfyRemote { void moveToMyPosition(); void processWaitingFrame(); void publish(); + void unpublish(); + static void unpublish(uint8_t id); + static void unpublish(uint8_t id, const char *topic); void publishState(); void commit(); void commitShadePosition(); @@ -352,6 +355,9 @@ class SomfyGroup : public SomfyRemote { bool hasShadeId(uint8_t shadeId); void compressLinkedShadeIds(); void publish(); + void unpublish(); + static void unpublish(uint8_t id); + static void unpublish(uint8_t id, const char *topic); void publishState(); void updateFlags(); void emitState(const char *evt = "groupState"); diff --git a/SomfyController.ino.esp32.bin b/SomfyController.ino.esp32.bin index 742b5c6..da361f8 100644 Binary files a/SomfyController.ino.esp32.bin and b/SomfyController.ino.esp32.bin differ diff --git a/SomfyController.littlefs.bin b/SomfyController.littlefs.bin index 51ff4f0..8504d71 100644 Binary files a/SomfyController.littlefs.bin and b/SomfyController.littlefs.bin differ diff --git a/data/index.html b/data/index.html index 7276598..d07c5ee 100644 --- a/data/index.html +++ b/data/index.html @@ -3,11 +3,11 @@ - - - + + + - +
diff --git a/data/index.js b/data/index.js index 10d9a87..82750bb 100644 --- a/data/index.js +++ b/data/index.js @@ -1252,7 +1252,7 @@ var security = new Security(); class General { initialized = false; - appVersion = 'v2.2.2'; + appVersion = 'v2.2.3a'; reloadApp = false; init() { if (this.initialized) return;