diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index e45970f42..e84f32deb 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -22,6 +22,7 @@ For more details go to [emsesp.org](https://emsesp.org/). - SRC climate creation [#2936](https://github.com/emsesp/EMS-ESP32/issues/2936) and [#2960](https://github.com/emsesp/EMS-ESP32/issues/2960) - missing translations [#3015](https://github.com/emsesp/EMS-ESP32/issues/3015) - custom entities check fetch length +- modbus initialization [#3064](https://github.com/emsesp/EMS-ESP32/issues/3064) ## Changed diff --git a/src/ESP32React/MqttSettingsService.cpp b/src/ESP32React/MqttSettingsService.cpp index 3f53e8027..c371a5438 100644 --- a/src/ESP32React/MqttSettingsService.cpp +++ b/src/ESP32React/MqttSettingsService.cpp @@ -167,10 +167,14 @@ bool MqttSettingsService::configureMqtt() { #ifndef NO_TLS_SUPPORT if (_state.enableTLS) { if (_state.rootCA == "insecure") { +#if defined(EMSESP_DEBUG) emsesp::EMSESP::logger().debug("Start insecure MQTT"); +#endif static_cast(_mqttClient)->setInsecure(); } else { +#if defined(EMSESP_DEBUG) emsesp::EMSESP::logger().debug("Start secure MQTT with rootCA"); +#endif String certificate = "-----BEGIN CERTIFICATE-----\n" + _state.rootCA + "\n-----END CERTIFICATE-----\n"; static_cast(_mqttClient)->setCACert(certificate.c_str()); } diff --git a/src/core/system.cpp b/src/core/system.cpp index a9c0cb2f1..ad33f5c13 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -637,6 +637,29 @@ void System::syslog_init() { #endif } +// start or reconfigure modbus +void System::modbus_init() { + EMSESP::webSettingsService.read([&](WebSettings & settings) { + if (settings.modbus_enabled) { + if (EMSESP::modbus_ == nullptr) { + EMSESP::modbus_ = new Modbus; + EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000); + } else if (settings.modbus_port != modbus_port_ || settings.modbus_max_clients != modbus_max_clients_ || settings.modbus_timeout != modbus_timeout_) { + EMSESP::modbus_->stop(); + EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000); + } + } else if (EMSESP::modbus_ != nullptr) { + EMSESP::modbus_->stop(); + delete EMSESP::modbus_; + EMSESP::modbus_ = nullptr; + } + modbus_enabled_ = settings.modbus_enabled; + modbus_port_ = settings.modbus_port; + modbus_max_clients_ = settings.modbus_max_clients; + modbus_timeout_ = settings.modbus_timeout; + }); +} + // read specific major system settings to store locally for faster access void System::store_settings(WebSettings & settings) { version_ = settings.version; @@ -668,25 +691,6 @@ void System::store_settings(WebSettings & settings) { readonly_mode_ = settings.readonly_mode; locale_ = settings.locale; developer_mode_ = settings.developer_mode; - - // start services - if (settings.modbus_enabled) { - if (EMSESP::modbus_ == nullptr) { - EMSESP::modbus_ = new Modbus; - EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000); - } else if (settings.modbus_port != modbus_port_ || settings.modbus_max_clients != modbus_max_clients_ || settings.modbus_timeout != modbus_timeout_) { - EMSESP::modbus_->stop(); - EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000); - } - } else if (EMSESP::modbus_ != nullptr) { - EMSESP::modbus_->stop(); - delete EMSESP::modbus_; - EMSESP::modbus_ = nullptr; - } - modbus_enabled_ = settings.modbus_enabled; - modbus_port_ = settings.modbus_port; - modbus_max_clients_ = settings.modbus_max_clients; - modbus_timeout_ = settings.modbus_timeout; } // Starts up core services @@ -728,6 +732,7 @@ void System::start() { last_system_check_ = 0; // force the LED to go from fast flash to pulse uart_init(); // start UART syslog_init(); // start syslog + modbus_init(); // start modbus } // button single click @@ -3421,6 +3426,24 @@ void System::remove_gpio(uint8_t pin, bool also_system) { } } +// remove a gpio that has 0 for disable +void System::remove_optional_gpio(uint8_t pin) { + if (pin) { + remove_gpio(pin, false); + } +} + +// set unused gpios to default state input high-Z +void System::reset_unused_gpios() { + for (const auto & pin : valid_system_gpios_) { + auto it = std::find_if(used_gpios_.begin(), used_gpios_.end(), [pin](const GpioUsage & usage) { return usage.pin == pin; }); + if (it == used_gpios_.end()) { + LOG_DEBUG("reset pin %d", pin); + pinMode(pin, INPUT); + } + } +} + // return a list of GPIO's available for use std::vector System::available_gpios() { std::vector gpios; diff --git a/src/core/system.h b/src/core/system.h index a92257b5d..bdf2399a9 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -115,6 +115,7 @@ class System { void show_mem(const char * note); void store_settings(class WebSettings & settings); void syslog_init(); + void modbus_init(); bool check_upgrade(); bool check_restore(); void heartbeat_json(JsonObject output); @@ -342,6 +343,8 @@ class System { #endif static void remove_gpio(uint8_t pin, bool also_system = false); // remove a gpio from both valid (optional) and used lists + static void remove_optional_gpio(uint8_t pin); + static void reset_unused_gpios(); // Partition info map: partition name -> {version, size, install_date} std::map, AllocatorPSRAM>> partition_info_; diff --git a/src/emsesp_version.h b/src/emsesp_version.h index 0173e604e..929ebedf7 100644 --- a/src/emsesp_version.h +++ b/src/emsesp_version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.9.0-dev.3" +#define EMSESP_APP_VERSION "3.9.0-dev.4" diff --git a/src/web/WebCustomEntityService.cpp b/src/web/WebCustomEntityService.cpp index faf9f54eb..94c9bb024 100644 --- a/src/web/WebCustomEntityService.cpp +++ b/src/web/WebCustomEntityService.cpp @@ -166,7 +166,9 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web bool WebCustomEntityService::command_setvalue(const char * value, const int8_t id, const char * name) { // don't write if there is no value, to prevent setting an empty value by mistake when parsing attributes if (!strlen(value)) { +#if defined(EMSESP_DEBUG) EMSESP::logger().debug("can't set empty value!"); +#endif return false; } diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index 54473a128..fc4e8d8ba 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -563,7 +563,9 @@ void WebSchedulerService::condition() { } else if (match.length() == 1 && match[0] == '0' && scheduleItem.retry_cnt == 1) { scheduleItem.retry_cnt = 0xFF; } else if (match.length() != 1) { // the match is not boolean +#if defined(EMSESP_DEBUG) EMSESP::logger().debug("condition result: %s", match.c_str()); +#endif } } } diff --git a/src/web/WebSettingsService.cpp b/src/web/WebSettingsService.cpp index 2cd8dfa0c..1f2b6444c 100644 --- a/src/web/WebSettingsService.cpp +++ b/src/web/WebSettingsService.cpp @@ -20,7 +20,7 @@ namespace emsesp { -uint8_t WebSettings::flags_ = 0; +uint16_t WebSettings::flags_ = 0; WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) : _httpEndpoint(WebSettings::read, WebSettings::update, this, server, EMSESP_SETTINGS_SERVICE_PATH, securityManager) @@ -128,11 +128,11 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { reset_flags(); // before loading new board profile free old gpios from used list to allow remapping - EMSESP::system_.remove_gpio(original_settings.led_gpio); - EMSESP::system_.remove_gpio(original_settings.dallas_gpio); + EMSESP::system_.remove_optional_gpio(original_settings.led_gpio); + EMSESP::system_.remove_optional_gpio(original_settings.dallas_gpio); EMSESP::system_.remove_gpio(original_settings.pbutton_gpio); - EMSESP::system_.remove_gpio(original_settings.rx_gpio); - EMSESP::system_.remove_gpio(original_settings.tx_gpio); + EMSESP::system_.remove_optional_gpio(original_settings.rx_gpio); + EMSESP::system_.remove_optional_gpio(original_settings.tx_gpio); // see if the user has changed the board profile // this will set: led_gpio, dallas_gpio, rx_gpio, tx_gpio, pbutton_gpio, phy_type, eth_power, eth_phy_addr, eth_clock_mode, led_type @@ -256,10 +256,14 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { check_flag(original_settings.low_clock, settings.low_clock, ChangeFlags::RESTART); // Modbus settings - settings.modbus_enabled = root["modbus_enabled"] | EMSESP_DEFAULT_MODBUS_ENABLED; - settings.modbus_port = root["modbus_port"] | EMSESP_DEFAULT_MODBUS_PORT; + settings.modbus_enabled = root["modbus_enabled"] | EMSESP_DEFAULT_MODBUS_ENABLED; + check_flag(original_settings.modbus_enabled, settings.modbus_enabled, ChangeFlags::MODBUS); + settings.modbus_port = root["modbus_port"] | EMSESP_DEFAULT_MODBUS_PORT; + check_flag(original_settings.modbus_port, settings.modbus_port, ChangeFlags::MODBUS); settings.modbus_max_clients = root["modbus_max_clients"] | EMSESP_DEFAULT_MODBUS_MAX_CLIENTS; - settings.modbus_timeout = root["modbus_timeout"] | EMSESP_DEFAULT_MODBUS_TIMEOUT; + check_flag(original_settings.modbus_max_clients, settings.modbus_max_clients, ChangeFlags::MODBUS); + settings.modbus_timeout = root["modbus_timeout"] | EMSESP_DEFAULT_MODBUS_TIMEOUT; + check_flag(original_settings.modbus_timeout, settings.modbus_timeout, ChangeFlags::MODBUS); // // these may need mqtt restart to rebuild HA discovery topics @@ -395,7 +399,11 @@ void WebSettingsService::onUpdate() { Mqtt::reset_mqtt(); // reload MQTT, init HA etc } + if (WebSettings::has_flags(WebSettings::ChangeFlags::MODBUS)) { + EMSESP::system_.modbus_init(); + } WebSettings::reset_flags(); + EMSESP::system_.reset_unused_gpios(); } void WebSettingsService::begin() { @@ -537,7 +545,7 @@ void WebSettings::set_board_profile(WebSettings & settings) { } // returns true if the value was changed -bool WebSettings::check_flag(int prev_v, int new_v, uint8_t flag) { +bool WebSettings::check_flag(int prev_v, int new_v, uint16_t flag) { if (prev_v != new_v) { add_flags(flag); #if defined(EMSESP_DEBUG) @@ -548,11 +556,11 @@ bool WebSettings::check_flag(int prev_v, int new_v, uint8_t flag) { return false; } -void WebSettings::add_flags(uint8_t flags) { +void WebSettings::add_flags(uint16_t flags) { flags_ |= flags; } -bool WebSettings::has_flags(uint8_t flags) { +bool WebSettings::has_flags(uint16_t flags) { return (flags_ & flags) == flags; } @@ -560,7 +568,7 @@ void WebSettings::reset_flags() { flags_ = ChangeFlags::NONE; } -uint8_t WebSettings::get_flags() { +uint16_t WebSettings::get_flags() { return flags_; } diff --git a/src/web/WebSettingsService.h b/src/web/WebSettingsService.h index 65526669e..43d72b3a0 100644 --- a/src/web/WebSettingsService.h +++ b/src/web/WebSettingsService.h @@ -128,7 +128,7 @@ class WebSettings { static void read(WebSettings & settings, JsonObject root); static StateUpdateResult update(JsonObject root, WebSettings & settings); - enum ChangeFlags : uint8_t { + enum ChangeFlags : uint16_t { NONE = 0, UART = (1 << 0), // 1 - uart SYSLOG = (1 << 1), // 2 - syslog @@ -138,19 +138,20 @@ class WebSettings { LED = (1 << 5), // 32 - led BUTTON = (1 << 6), // 64 - button MQTT = (1 << 7), // 128 - mqtt - RESTART = 0xFF // 255 - restart request (all changes) + MODBUS = (1 << 8), // 256 - modbus + RESTART = 0xFFFF // restart request (all changes) }; - static bool check_flag(int prev_v, int new_v, uint8_t flag); - static void add_flags(uint8_t flags); - static bool has_flags(uint8_t flags); - static void reset_flags(); - static uint8_t get_flags(); + static bool check_flag(int prev_v, int new_v, uint16_t flag); + static void add_flags(uint16_t flags); + static bool has_flags(uint16_t flags); + static void reset_flags(); + static uint16_t get_flags(); private: static void set_board_profile(WebSettings & settings); - static uint8_t flags_; + static uint16_t flags_; }; class WebSettingsService : public StatefulService {