From a693e96248f2cce5bfe204db29e6ad2b2b1ae2e6 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 16 Nov 2025 20:41:45 +0100 Subject: [PATCH] validate board gpios in system --- .../src/app/main/SensorsAnalogDialog.tsx | 39 +++++------ src/core/console.cpp | 2 +- src/core/emsesp.cpp | 30 --------- src/core/emsesp.h | 2 - src/core/system.cpp | 67 ++++++++++++------- src/core/system.h | 6 ++ src/core/temperaturesensor.cpp | 4 +- src/web/WebSettingsService.cpp | 2 +- 8 files changed, 70 insertions(+), 82 deletions(-) diff --git a/interface/src/app/main/SensorsAnalogDialog.tsx b/interface/src/app/main/SensorsAnalogDialog.tsx index baeb8f2b9..618c92846 100644 --- a/interface/src/app/main/SensorsAnalogDialog.tsx +++ b/interface/src/app/main/SensorsAnalogDialog.tsx @@ -172,30 +172,21 @@ const SensorsAnalogDialog = ({ {dialogTitle} - {editItem.s ? ( - - ) : ( - - {availableGPIOs?.map((gpio: number) => ( - - {gpio} - - ))} - - )} + + {availableGPIOs?.map((gpio: number) => ( + + {gpio} + + ))} + const & commands) { shell.printfln(F_(tx_mode_fmt), settings.tx_mode); return StateUpdateResult::CHANGED; }); - EMSESP::uart_init(); + EMSESP::system_.uart_init(false); }); // diff --git a/src/core/emsesp.cpp b/src/core/emsesp.cpp index ad1540a98..6f6be5293 100644 --- a/src/core/emsesp.cpp +++ b/src/core/emsesp.cpp @@ -240,36 +240,6 @@ void EMSESP::watch_id(uint16_t watch_id) { watch_id_ = watch_id; } -// resets all counters and bumps the UART -// this is called when the tx_mode is persisted in the FS either via Web UI or the console -void EMSESP::uart_init() { - uint8_t tx_mode = 0; - uint8_t rx_gpio = 0; - uint8_t tx_gpio = 0; - EMSESP::webSettingsService.read([&](WebSettings const & settings) { - tx_mode = settings.tx_mode; - rx_gpio = settings.rx_gpio; - tx_gpio = settings.tx_gpio; - }); - - EMSuart::stop(); - - // don't start UART if we have invalid GPIOs - if (EMSESP::system_.is_valid_gpio(rx_gpio) && EMSESP::system_.is_valid_gpio(tx_gpio)) { - EMSuart::start(tx_mode, rx_gpio, tx_gpio); // start UART - } else { - LOG_WARNING("Invalid UART Rx/Tx GPIOs. Check config."); - } - - txservice_.start(); // sends out request to EMS bus for all devices - txservice_.tx_mode(tx_mode); - - // force a fetch for all new values, unless Tx is set to off - // if (tx_mode != 0) { - // EMSESP::fetch_device_values(); - // } -} - // return status of bus: connected (0), connected but Tx is broken (1), disconnected (2) uint8_t EMSESP::bus_status() { if (!rxservice_.bus_connected()) { diff --git a/src/core/emsesp.h b/src/core/emsesp.h index a34e8be65..17a5aa133 100644 --- a/src/core/emsesp.h +++ b/src/core/emsesp.h @@ -147,8 +147,6 @@ class EMSESP { static void dump_all_entities(uuid::console::Shell & shell); static void dump_all_telegrams(uuid::console::Shell & shell); - static void uart_init(); - static void incoming_telegram(uint8_t * data, const uint8_t length); static bool sensor_enabled() { diff --git a/src/core/system.cpp b/src/core/system.cpp index 0acbd660c..5f81b31ef 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -406,15 +406,21 @@ void System::syslog_init() { // read some specific system settings to store locally for faster access void System::reload_settings() { + // set gpios to zero for valid check + led_gpio_ = 0; + rx_gpio_ = 0; + tx_gpio_ = 0; + pbutton_gpio_ = 0; + dallas_gpio_ = 0; EMSESP::webSettingsService.read([&](WebSettings & settings) { version_ = settings.version; - pbutton_gpio_ = settings.pbutton_gpio; + pbutton_gpio_ = is_valid_gpio(settings.pbutton_gpio) ? settings.pbutton_gpio : 0; analog_enabled_ = settings.analog_enabled; low_clock_ = settings.low_clock; hide_led_ = settings.hide_led; led_type_ = settings.led_type; - led_gpio_ = settings.led_gpio; + led_gpio_ = is_valid_gpio(settings.led_gpio) ? settings.led_gpio : 0; board_profile_ = settings.board_profile; telnet_enabled_ = settings.telnet_enabled; @@ -423,10 +429,10 @@ void System::reload_settings() { modbus_max_clients_ = settings.modbus_max_clients; modbus_timeout_ = settings.modbus_timeout; - rx_gpio_ = settings.rx_gpio; - tx_gpio_ = settings.tx_gpio; - dallas_gpio_ = settings.dallas_gpio; - + tx_mode_ = settings.tx_mode; + rx_gpio_ = is_valid_gpio(settings.rx_gpio) ? settings.rx_gpio : 0; + tx_gpio_ = is_valid_gpio(settings.tx_gpio) ? settings.tx_gpio : 0; + dallas_gpio_ = is_valid_gpio(settings.dallas_gpio) ? settings.dallas_gpio : 0; syslog_enabled_ = settings.syslog_enabled; syslog_level_ = settings.syslog_level; syslog_mark_interval_ = settings.syslog_mark_interval; @@ -497,7 +503,7 @@ void System::start() { led_init(false); // init LED button_init(false); // the special button network_init(false); // network - EMSESP::uart_init(); // start UART + uart_init(false); // start UART syslog_init(); // start syslog } @@ -550,11 +556,6 @@ void System::button_init(bool refresh) { } #ifndef EMSESP_STANDALONE - if (!is_valid_gpio(pbutton_gpio_)) { - LOG_WARNING("Invalid button GPIO. Check config."); - myPButton_.init(255, HIGH); // disable - return; - } if (!myPButton_.init(pbutton_gpio_, HIGH)) { LOG_WARNING("Multi-functional button not detected"); return; @@ -572,18 +573,17 @@ void System::button_init(bool refresh) { void System::led_init(bool refresh) { if (refresh) { // disabled old led port before setting new one - if ((led_gpio_ != 0) && is_valid_gpio(led_gpio_)) { + if (led_gpio_) { #if ESP_ARDUINO_VERSION_MAJOR < 3 led_type_ ? neopixelWrite(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); #else led_type_ ? rgbLedWrite(led_gpio_, 0, 0, 0) : digitalWrite(led_gpio_, !LED_ON); #endif - pinMode(led_gpio_, INPUT); } reload_settings(); } - if ((led_gpio_ != 0) && is_valid_gpio(led_gpio_)) { // 0 means disabled + if ((led_gpio_)) { // 0 means disabled if (led_type_) { // rgb LED WS2812B, use Neopixel #if ESP_ARDUINO_VERSION_MAJOR < 3 @@ -595,9 +595,27 @@ void System::led_init(bool refresh) { pinMode(led_gpio_, OUTPUT); digitalWrite(led_gpio_, !LED_ON); // start with LED off } + } else { + LOG_INFO("LED disabled"); } } +void System::uart_init(bool refresh) { + if (refresh) { + reload_settings(); + } + EMSuart::stop(); + + // don't start UART if we have invalid GPIOs + if (rx_gpio_ && tx_gpio_) { + EMSuart::start(tx_mode_, rx_gpio_, tx_gpio_); // start UART + } else { + LOG_WARNING("Invalid UART Rx/Tx GPIOs. Check config."); + } + + EMSESP::txservice_.start(); // reset counters and send devices request +} + // checks system health and handles LED flashing wizardry void System::loop() { // check if we're supposed to do a reset/restart @@ -1802,11 +1820,12 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output node["ethPhyAddr"] = settings.eth_phy_addr; node["ethClockMmode"] = settings.eth_clock_mode; } - node["rxGPIO"] = settings.rx_gpio; - node["txGPIO"] = settings.tx_gpio; - node["dallasGPIO"] = settings.dallas_gpio; - node["pbuttonGPIO"] = settings.pbutton_gpio; - node["ledGPIO"] = settings.led_gpio; + node["rxGPIO"] = EMSESP::system_.rx_gpio_; + node["txGPIO"] = EMSESP::system_.tx_gpio_; + node["dallasGPIO"] = EMSESP::system_.dallas_gpio_; + node["pbuttonGPIO"] = EMSESP::system_.pbutton_gpio_; + node["ledGPIO"] = EMSESP::system_.led_gpio_; + node["ledType"] = settings.led_type; node["ledType"] = settings.led_type; } node["hideLed"] = settings.hide_led; @@ -2369,10 +2388,12 @@ std::vector System::valid_gpio_list() { valid_gpios.erase(std::remove(valid_gpios.begin(), valid_gpios.end(), 22), valid_gpios.end()); } - // filter out GPIOs already used in application settings + // filter out GPIOs already used in application settings, gpio 0 means disabled, except for pbutton for (const auto & gpio : valid_gpios) { - if (gpio == EMSESP::system_.pbutton_gpio_ || gpio == EMSESP::system_.led_gpio_ || gpio == EMSESP::system_.dallas_gpio_ - || gpio == EMSESP::system_.rx_gpio_ || gpio == EMSESP::system_.tx_gpio_) { + if (gpio == EMSESP::system_.pbutton_gpio_ + || (gpio + && (gpio == EMSESP::system_.led_gpio_ || gpio == EMSESP::system_.dallas_gpio_ || gpio == EMSESP::system_.rx_gpio_ + || gpio == EMSESP::system_.tx_gpio_))) { valid_gpios.erase(std::remove(valid_gpios.begin(), valid_gpios.end(), gpio), valid_gpios.end()); } } diff --git a/src/core/system.h b/src/core/system.h index fb53eb231..a73b9700c 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -133,6 +133,7 @@ class System { void network_init(bool refresh); void button_init(bool refresh); void commands_init(); + void uart_init(bool refresh); void systemStatus(uint8_t status_code); uint8_t systemStatus(); @@ -145,6 +146,10 @@ class System { static bool readCommand(const char * data); + void dallas_gpio(uint8_t gpio) { + dallas_gpio_ = gpio; + } + bool telnet_enabled() { return telnet_enabled_; } @@ -413,6 +418,7 @@ class System { uint8_t pbutton_gpio_; uint8_t rx_gpio_; uint8_t tx_gpio_; + uint8_t tx_mode_; uint8_t dallas_gpio_; bool telnet_enabled_; bool syslog_enabled_; diff --git a/src/core/temperaturesensor.cpp b/src/core/temperaturesensor.cpp index 0a540dcb4..a4f744ecf 100644 --- a/src/core/temperaturesensor.cpp +++ b/src/core/temperaturesensor.cpp @@ -55,10 +55,12 @@ void TemperatureSensor::start(const bool factory_settings) { // load settings void TemperatureSensor::reload() { // load the service settings + EMSESP::system_.dallas_gpio(0); // reset in system to check valid sensor EMSESP::webSettingsService.read([&](WebSettings const & settings) { - dallas_gpio_ = settings.dallas_gpio; + dallas_gpio_ = EMSESP::system_.is_valid_gpio(settings.dallas_gpio) ? settings.dallas_gpio : 0; parasite_ = settings.dallas_parasite; }); + EMSESP::system_.dallas_gpio(dallas_gpio_); // set to system for checks for (auto & sensor : sensors_) { remove_ha_topic(sensor.id()); diff --git a/src/web/WebSettingsService.cpp b/src/web/WebSettingsService.cpp index 46135d9b3..609a44308 100644 --- a/src/web/WebSettingsService.cpp +++ b/src/web/WebSettingsService.cpp @@ -409,7 +409,7 @@ void WebSettingsService::onUpdate() { } if (WebSettings::has_flags(WebSettings::ChangeFlags::UART)) { - EMSESP::uart_init(); + EMSESP::system_.uart_init(true); } if (WebSettings::has_flags(WebSettings::ChangeFlags::SYSLOG)) {