auto-publish HA when MQTT settings change on web

This commit is contained in:
proddy
2021-01-08 20:52:46 +01:00
parent a26d8454d6
commit 908cf5c965
4 changed files with 26 additions and 48 deletions

View File

@@ -41,8 +41,7 @@ MqttSettingsService::MqttSettingsService(AsyncWebServer * server, FS * fs, Secur
, _disconnectReason(AsyncMqttClientDisconnectReason::TCP_DISCONNECTED) , _disconnectReason(AsyncMqttClientDisconnectReason::TCP_DISCONNECTED)
, _mqttClient() { , _mqttClient() {
#ifdef ESP32 #ifdef ESP32
WiFi.onEvent(std::bind(&MqttSettingsService::onStationModeDisconnected, this, std::placeholders::_1, std::placeholders::_2), WiFi.onEvent(std::bind(&MqttSettingsService::onStationModeDisconnected, this, std::placeholders::_1, std::placeholders::_2), WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
WiFi.onEvent(std::bind(&MqttSettingsService::onStationModeGotIP, this, std::placeholders::_1, std::placeholders::_2), WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP); WiFi.onEvent(std::bind(&MqttSettingsService::onStationModeGotIP, this, std::placeholders::_1, std::placeholders::_2), WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP);
#elif defined(ESP8266) #elif defined(ESP8266)
_onStationModeDisconnectedHandler = WiFi.onStationModeDisconnected(std::bind(&MqttSettingsService::onStationModeDisconnected, this, std::placeholders::_1)); _onStationModeDisconnectedHandler = WiFi.onStationModeDisconnected(std::bind(&MqttSettingsService::onStationModeDisconnected, this, std::placeholders::_1));
@@ -155,8 +154,7 @@ void MqttSettingsService::configureMqtt() {
// Serial.println(F("Connecting to MQTT...")); // Serial.println(F("Connecting to MQTT..."));
_mqttClient.setServer(retainCstr(_state.host.c_str(), &_retainedHost), _state.port); _mqttClient.setServer(retainCstr(_state.host.c_str(), &_retainedHost), _state.port);
if (_state.username.length() > 0) { if (_state.username.length() > 0) {
_mqttClient.setCredentials(retainCstr(_state.username.c_str(), &_retainedUsername), _mqttClient.setCredentials(retainCstr(_state.username.c_str(), &_retainedUsername), retainCstr(_state.password.length() > 0 ? _state.password.c_str() : nullptr, &_retainedPassword));
retainCstr(_state.password.length() > 0 ? _state.password.c_str() : nullptr, &_retainedPassword));
} else { } else {
_mqttClient.setCredentials(retainCstr(nullptr, &_retainedUsername), retainCstr(nullptr, &_retainedPassword)); _mqttClient.setCredentials(retainCstr(nullptr, &_retainedUsername), retainCstr(nullptr, &_retainedPassword));
} }

View File

@@ -407,6 +407,17 @@ void EMSESP::publish_all_loop() {
} }
} }
// force HA to re-create all the devices
void EMSESP::reset_mqtt_ha() {
if (!Mqtt::ha_enabled()) {
return;
}
for (const auto & emsdevice : emsdevices) {
emsdevice->ha_config_done(false);
}
}
// create json doc for the devices values and add to MQTT publish queue // create json doc for the devices values and add to MQTT publish queue
void EMSESP::publish_device_values(uint8_t device_type) { void EMSESP::publish_device_values(uint8_t device_type) {
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE_DYN); // use max size DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE_DYN); // use max size
@@ -675,8 +686,7 @@ bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
} }
read_next_ = false; read_next_ = false;
} else if (watch() == WATCH_ON) { } else if (watch() == WATCH_ON) {
if ((watch_id_ == WATCH_ID_NONE) || (telegram->type_id == watch_id_) if ((watch_id_ == WATCH_ID_NONE) || (telegram->type_id == watch_id_) || ((watch_id_ < 0x80) && ((telegram->src == watch_id_) || (telegram->dest == watch_id_)))) {
|| ((watch_id_ < 0x80) && ((telegram->src == watch_id_) || (telegram->dest == watch_id_)))) {
LOG_NOTICE(pretty_telegram(telegram).c_str()); LOG_NOTICE(pretty_telegram(telegram).c_str());
} else if (!trace_raw_) { } else if (!trace_raw_) {
LOG_TRACE(pretty_telegram(telegram).c_str()); LOG_TRACE(pretty_telegram(telegram).c_str());
@@ -837,8 +847,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, std::
if (device_p == nullptr) { if (device_p == nullptr) {
LOG_NOTICE(F("Unrecognized EMS device (device ID 0x%02X, product ID %d). Please report on GitHub."), device_id, product_id); LOG_NOTICE(F("Unrecognized EMS device (device ID 0x%02X, product ID %d). Please report on GitHub."), device_id, product_id);
std::string name("unknown"); std::string name("unknown");
emsdevices.push_back( emsdevices.push_back(EMSFactory::add(DeviceType::GENERIC, device_id, product_id, version, name, DeviceFlags::EMS_DEVICE_FLAG_NONE, EMSdevice::Brand::NO_BRAND));
EMSFactory::add(DeviceType::GENERIC, device_id, product_id, version, name, DeviceFlags::EMS_DEVICE_FLAG_NONE, EMSdevice::Brand::NO_BRAND));
return false; // not found return false; // not found
} }
@@ -856,9 +865,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, std::
return true; return true;
} }
Command::add_with_json(device_type, F_(info), [device_type](const char * value, const int8_t id, JsonObject & json) { Command::add_with_json(device_type, F_(info), [device_type](const char * value, const int8_t id, JsonObject & json) { return command_info(device_type, json); });
return command_info(device_type, json);
});
return true; return true;
} }
@@ -887,12 +894,7 @@ void EMSESP::send_read_request(const uint16_t type_id, const uint8_t dest) {
} }
// sends write request // sends write request
void EMSESP::send_write_request(const uint16_t type_id, void EMSESP::send_write_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, uint8_t * message_data, const uint8_t message_length, const uint16_t validate_typeid) {
const uint8_t dest,
const uint8_t offset,
uint8_t * message_data,
const uint8_t message_length,
const uint16_t validate_typeid) {
txservice_.add(Telegram::Operation::TX_WRITE, dest, type_id, offset, message_data, message_length); txservice_.add(Telegram::Operation::TX_WRITE, dest, type_id, offset, message_data, message_length);
txservice_.set_post_send_query(validate_typeid); // store which type_id to send Tx read after a write txservice_.set_post_send_query(validate_typeid); // store which type_id to send Tx read after a write

View File

@@ -83,6 +83,7 @@ class EMSESP {
static void publish_other_values(); static void publish_other_values();
static void publish_sensor_values(const bool time, const bool force = false); static void publish_sensor_values(const bool time, const bool force = false);
static void publish_all(bool force = false); static void publish_all(bool force = false);
static void reset_mqtt_ha();
#ifdef EMSESP_STANDALONE #ifdef EMSESP_STANDALONE
static void run_test(uuid::console::Shell & shell, const std::string & command); // only for testing static void run_test(uuid::console::Shell & shell, const std::string & command); // only for testing
@@ -96,12 +97,7 @@ class EMSESP {
static void send_read_request(const uint16_t type_id, const uint8_t dest); static void send_read_request(const uint16_t type_id, const uint8_t dest);
static void send_read_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset); static void send_read_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset);
static void send_write_request(const uint16_t type_id, static void send_write_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, uint8_t * message_data, const uint8_t message_length, const uint16_t validate_typeid);
const uint8_t dest,
const uint8_t offset,
uint8_t * message_data,
const uint8_t message_length,
const uint16_t validate_typeid);
static void send_write_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, const uint8_t value); static void send_write_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, const uint8_t value);
static void send_write_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid); static void send_write_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid);

View File

@@ -196,19 +196,10 @@ void Mqtt::show_mqtt(uuid::console::Shell & shell) {
if (message.packet_id_ == 0) { if (message.packet_id_ == 0) {
shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s"), message.id_, content->topic.c_str(), content->payload.c_str()); shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s"), message.id_, content->topic.c_str(), content->payload.c_str());
} else { } else {
shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s (pid %d)"), shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s (pid %d)"), message.id_, content->topic.c_str(), content->payload.c_str(), message.packet_id_);
message.id_,
content->topic.c_str(),
content->payload.c_str(),
message.packet_id_);
} }
} else { } else {
shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s (pid %d, retry #%d)"), shell.printfln(F(" [%02d] (Pub) topic=%s payload=%s (pid %d, retry #%d)"), message.id_, content->topic.c_str(), content->payload.c_str(), message.packet_id_, message.retry_count_);
message.id_,
content->topic.c_str(),
content->payload.c_str(),
message.packet_id_,
message.retry_count_);
} }
} else { } else {
// Subscribe messages // Subscribe messages
@@ -296,10 +287,7 @@ void Mqtt::on_message(const char * topic, const char * payload, size_t len) {
// print all the topics related to a specific device type // print all the topics related to a specific device type
void Mqtt::show_topic_handlers(uuid::console::Shell & shell, const uint8_t device_type) { void Mqtt::show_topic_handlers(uuid::console::Shell & shell, const uint8_t device_type) {
if (std::count_if(mqtt_subfunctions_.cbegin(), if (std::count_if(mqtt_subfunctions_.cbegin(), mqtt_subfunctions_.cend(), [=](MQTTSubFunction const & mqtt_subfunction) { return device_type == mqtt_subfunction.device_type_; }) == 0) {
mqtt_subfunctions_.cend(),
[=](MQTTSubFunction const & mqtt_subfunction) { return device_type == mqtt_subfunction.device_type_; })
== 0) {
return; return;
} }
@@ -344,7 +332,7 @@ void Mqtt::reset_mqtt() {
} }
if (mqttClient_->connected()) { if (mqttClient_->connected()) {
mqttClient_->disconnect(); // force a disconnect mqttClient_->disconnect(true); // force a disconnect
} }
} }
@@ -513,6 +501,7 @@ void Mqtt::on_connect() {
// we doing a re-connect from a TCP break // we doing a re-connect from a TCP break
// only re-subscribe again to all MQTT topics // only re-subscribe again to all MQTT topics
resubscribe(); resubscribe();
EMSESP::reset_mqtt_ha(); // re-create all HA devices if there are any
} }
publish_retain(F("status"), "online", true); // say we're alive to the Last Will topic, with retain on publish_retain(F("status"), "online", true); // say we're alive to the Last Will topic, with retain on
@@ -721,15 +710,8 @@ void Mqtt::process_queue() {
} }
// else try and publish it // else try and publish it
uint16_t packet_id = uint16_t packet_id = mqttClient_->publish(message->topic.c_str(), mqtt_qos_, message->retain, message->payload.c_str(), message->payload.size(), false, mqtt_message.id_);
mqttClient_->publish(message->topic.c_str(), mqtt_qos_, message->retain, message->payload.c_str(), message->payload.size(), false, mqtt_message.id_); LOG_DEBUG(F("Publishing topic %s (#%02d, retain=%d, try#%d, size %d, pid %d)"), message->topic.c_str(), mqtt_message.id_, message->retain, mqtt_message.retry_count_ + 1, message->payload.size(), packet_id);
LOG_DEBUG(F("Publishing topic %s (#%02d, retain=%d, try#%d, size %d, pid %d)"),
message->topic.c_str(),
mqtt_message.id_,
message->retain,
mqtt_message.retry_count_ + 1,
message->payload.size(),
packet_id);
if (packet_id == 0) { if (packet_id == 0) {
// it failed. if we retried n times, give up. remove from queue // it failed. if we retried n times, give up. remove from queue