From 2b88fec2eeecc7c1dfd386977bc8c62682ecb955 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Thu, 8 Feb 2024 18:52:27 +0100 Subject: [PATCH] check valid pins for board_profile and analog --- interface/src/project/validators.ts | 38 ++++++++- src/analogsensor.cpp | 9 +- src/system.cpp | 5 +- src/system.h | 2 +- src/web/WebSettingsService.cpp | 122 +++++++++++++++------------- 5 files changed, 111 insertions(+), 65 deletions(-) diff --git a/interface/src/project/validators.ts b/interface/src/project/validators.ts index ee788ef1c..aa4004b8c 100644 --- a/interface/src/project/validators.ts +++ b/interface/src/project/validators.ts @@ -22,6 +22,26 @@ export const GPIO_VALIDATOR = { } }; +export const GPIO_VALIDATORR = { + validator(rule: InternalRuleItem, value: number, callback: (error?: string) => void) { + if ( + value && + (value === 1 || + (value >= 6 && value <= 11) || + (value >= 16 && value <= 17) || + value === 20 || + value === 24 || + (value >= 28 && value <= 31) || + value > 40 || + value < 0) + ) { + callback('Must be an valid GPIO port'); + } else { + callback(); + } + } +}; + export const GPIO_VALIDATORC3 = { validator(rule: InternalRuleItem, value: number, callback: (error?: string) => void) { if (value && ((value >= 11 && value <= 19) || value > 21 || value < 0)) { @@ -69,6 +89,14 @@ export const createSettingsValidator = (settings: Settings) => tx_gpio: [{ required: true, message: 'Tx GPIO is required' }, GPIO_VALIDATOR], rx_gpio: [{ required: true, message: 'Rx GPIO is required' }, GPIO_VALIDATOR] }), + ...(settings.board_profile === 'CUSTOM' && + settings.platform === 'ESP32PSRAM' && { + led_gpio: [{ required: true, message: 'LED GPIO is required' }, GPIO_VALIDATORR], + dallas_gpio: [{ required: true, message: 'GPIO is required' }, GPIO_VALIDATORR], + pbutton_gpio: [{ required: true, message: 'Button GPIO is required' }, GPIO_VALIDATORR], + tx_gpio: [{ required: true, message: 'Tx GPIO is required' }, GPIO_VALIDATORR], + rx_gpio: [{ required: true, message: 'Rx GPIO is required' }, GPIO_VALIDATORR] + }), ...(settings.board_profile === 'CUSTOM' && settings.platform === 'ESP32-C3' && { led_gpio: [{ required: true, message: 'LED GPIO is required' }, GPIO_VALIDATORC3], @@ -193,7 +221,15 @@ export const analogSensorItemValidation = (sensors: AnalogSensor[], creating: bo n: [{ required: true, message: 'Name is required' }], g: [ { required: true, message: 'GPIO is required' }, - platform === 'ESP32-S3' ? GPIO_VALIDATORS3 : platform === 'ESP32-C3' ? GPIO_VALIDATORC3 : GPIO_VALIDATOR, + platform === 'ESP32-S3' + ? GPIO_VALIDATORS3 + : platform === 'ESP32-S2' + ? GPIO_VALIDATORS2 + : platform === 'ESP32-C3' + ? GPIO_VALIDATORC3 + : platform === 'ESP32R' + ? GPIO_VALIDATORR + : GPIO_VALIDATOR, ...(creating ? [isGPIOUniqueValidator(sensors)] : []) ] }); diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 987f8d709..e8e7517d0 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -69,7 +69,7 @@ void AnalogSensor::reload() { // update existing sensors bool found = false; for (const auto & sensor : settings.analogCustomizations) { //search customlist - if (sensor_.gpio() == sensor.gpio) { + if (System::is_valid_gpio(sensor.gpio) && sensor_.gpio() == sensor.gpio) { // for output sensors set value to new start-value if ((sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT) && (sensor_.type() != sensor.type || sensor_.offset() != sensor.offset || sensor_.factor() != sensor.factor)) { @@ -94,11 +94,14 @@ void AnalogSensor::reload() { for (const auto & sensor : settings.analogCustomizations) { bool found = false; for (const auto & sensor_ : sensors_) { - if (sensor_.gpio() == sensor.gpio) { + if (System::is_valid_gpio(sensor.gpio) && sensor_.gpio() == sensor.gpio) { found = true; } } if (!found) { + if (!System::is_valid_gpio(sensor.gpio)) { + continue; + } sensors_.emplace_back(sensor.gpio, sensor.name, sensor.offset, sensor.factor, sensor.uom, sensor.type); sensors_.back().ha_registered = false; // this will trigger recreate of the HA config if (sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT) { @@ -790,8 +793,6 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) { sensor.set_value(v); pinMode(sensor.gpio(), OUTPUT); dacWrite(sensor.gpio(), sensor.offset()); - publish_sensor(sensor); - return true; } else #endif if (v == 0 || v == 1) { diff --git a/src/system.cpp b/src/system.cpp index bea8287c8..aa112b51c 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -420,9 +420,10 @@ void System::wifi_tweak() { // we allow 0 as it has a special function on the NodeMCU apparently // See https://diyprojects.io/esp32-how-to-use-gpio-digital-io-arduino-code/#.YFpVEq9KhjG // and https://nodemcu.readthedocs.io/en/dev-esp32/modules/gpio/ -bool System::is_valid_gpio(uint8_t pin) { +bool System::is_valid_gpio(uint8_t pin, bool has_psram) { #if CONFIG_IDF_TARGET_ESP32 || EMSESP_STANDALONE - if ((pin == 1) || (pin >= 6 && pin <= 11) || (pin == 20) || (pin == 24) || (pin >= 28 && pin <= 31) || (pin > 40)) { + if ((pin == 1) || (pin >= 6 && pin <= 11) || (pin == 20) || (pin == 24) || (pin >= 28 && pin <= 31) || (pin > 40) + || ((EMSESP::system_.PSram() > 0 || has_psram) && pin >= 16 && pin <= 17)) { #elif CONFIG_IDF_TARGET_ESP32S2 if ((pin >= 19 && pin <= 20) || (pin >= 22 && pin <= 32) || (pin > 40)) { #elif CONFIG_IDF_TARGET_ESP32C3 diff --git a/src/system.h b/src/system.h index ccff2ae71..ff11f0c36 100644 --- a/src/system.h +++ b/src/system.h @@ -105,7 +105,7 @@ class System { static void extractSettings(const char * filename, const char * section, JsonObject output); static bool saveSettings(const char * filename, const char * section, JsonObject input); - static bool is_valid_gpio(uint8_t pin); + static bool is_valid_gpio(uint8_t pin, bool has_psram = false); static bool load_board_profile(std::vector & data, const std::string & board_profile); static void restart_requested(bool restart_requested) { diff --git a/src/web/WebSettingsService.cpp b/src/web/WebSettingsService.cpp index 436f5d23e..8d0729934 100644 --- a/src/web/WebSettingsService.cpp +++ b/src/web/WebSettingsService.cpp @@ -76,7 +76,8 @@ void WebSettings::read(WebSettings & settings, JsonObject root) { root["eth_power"] = settings.eth_power; root["eth_phy_addr"] = settings.eth_phy_addr; root["eth_clock_mode"] = settings.eth_clock_mode; - root["platform"] = EMSESP_PLATFORM; + String platform = EMSESP_PLATFORM; + root["platform"] = (platform == "ESP32" && EMSESP::system_.PSram()) ? "ESP32R" : platform; } // call on initialization and also when settings are updated via web or console @@ -88,27 +89,39 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { // load default GPIO configuration based on board profile std::vector data; // // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode settings.board_profile = root["board_profile"] | EMSESP_DEFAULT_BOARD_PROFILE; + // for -D compile setting store it in NVS if ((String)EMSESP_DEFAULT_BOARD_PROFILE != "default" && EMSESP::nvs_.getString("boot") == "") { EMSESP::nvs_.putString("boot", (const char *)EMSESP_DEFAULT_BOARD_PROFILE); } - /* -#if CONFIG_IDF_TARGET_ESP32C3 - settings.board_profile = root["board_profile"] | "C3MINI"; -#elif CONFIG_IDF_TARGET_ESP32S2 - settings.board_profile = root["board_profile"] | "S2MINI"; -#elif CONFIG_IDF_TARGET_ESP32S3 - // settings.board_profile = root["board_profile"] | "S3MINI"; - settings.board_profile = root["board_profile"] | "S32S3"; // BBQKees Gateway S3 -#elif CONFIG_IDF_TARGET_ESP32 - settings.board_profile = root["board_profile"] | EMSESP_DEFAULT_BOARD_PROFILE; -#endif -*/ + + bool psram = ESP.getPsramSize() > 0; // System::PSram() is initializd later + if (System::load_board_profile(data, settings.board_profile.c_str())) { + if (settings.board_profile == "CUSTOM") { //read pins, fallback to S32 + data[0] = root["led_gpio"] | 2; + data[1] = root["dallas_gpio"] | 18; + data[2] = root["rx_gpio"] | 23; + data[3] = root["tx_gpio"] | 5; + data[4] = root["pbutton_gpio"] | 0; + data[5] = root["phy_type"] | PHY_type::PHY_TYPE_NONE; + data[6] = root["eth_power"] | 0; + data[7] = root["eth_phy_addr"] | 0; + data[8] = root["eth_clock_mode"] | 0; + } + // check valid pins in this board profile + if (!System::is_valid_gpio(data[0], psram) || !System::is_valid_gpio(data[1], psram) || !System::is_valid_gpio(data[2], psram) + || !System::is_valid_gpio(data[3], psram) || !System::is_valid_gpio(data[4], psram) || !System::is_valid_gpio(data[6], psram)) { + settings.board_profile = ""; // reset to factory default + } + } + // load the profile if (!System::load_board_profile(data, settings.board_profile.c_str())) { // unknown, check for NVS or scan for ethernet, use default E32/E32V2/S32 settings.board_profile = EMSESP::nvs_.getString("boot"); if (!System::load_board_profile(data, settings.board_profile.c_str())) { -#if CONFIG_IDF_TARGET_ESP32 && !defined(EMSESP_STANDALONE) - if (settings.board_profile == "") { // empty: new test +#if defined(EMSESP_STANDALONE) + settings.board_profile = "S32"; +#elif CONFIG_IDF_TARGET_ESP32 + if (settings.board_profile == "" && !psram) { // empty: new test for E32 #if ESP_ARDUINO_VERSION_MAJOR < 3 if (ETH.begin(1, 16, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_IN)) { #else @@ -118,7 +131,7 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { } else { EMSESP::nvs_.putString("boot", "Test"); } - } else if (settings.board_profile == "Test") { + } else if (settings.board_profile == "Test" || psram) { // test E32V2 #if ESP_ARDUINO_VERSION_MAJOR < 3 if (ETH.begin(0, 15, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_OUT)) { #else @@ -132,39 +145,58 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { EMSESP::nvs_.putString("boot", "S32"); } ESP.restart(); +#elif CONFIG_IDF_TARGET_ESP32C3 + settings.board_profile = "C3MINI"; +#elif CONFIG_IDF_TARGET_ESP32S2 + settings.board_profile = "S2MINI"; +#elif CONFIG_IDF_TARGET_ESP32S3 + settings.board_profile = "S32S3"; // BBQKees Gateway S3 #else settings.board_profile = "S32"; - System::load_board_profile(data, settings.board_profile.c_str()); #endif + System::load_board_profile(data, settings.board_profile.c_str()); } EMSESP::logger().info("No board profile found. Re-setting to %s", settings.board_profile.c_str()); } else { EMSESP::logger().info("Loading board profile %s", settings.board_profile.c_str()); } - uint8_t default_led_gpio = data[0]; - uint8_t default_dallas_gpio = data[1]; - uint8_t default_rx_gpio = data[2]; - uint8_t default_tx_gpio = data[3]; - uint8_t default_pbutton_gpio = data[4]; - uint8_t default_phy_type = data[5]; - uint8_t default_eth_power = data[6]; - uint8_t default_eth_phy_addr = data[7]; - uint8_t default_eth_clock_mode = data[8]; - int prev; reset_flags(); + // pins + prev = settings.led_gpio; + settings.led_gpio = data[0]; + check_flag(prev, settings.led_gpio, ChangeFlags::LED); + prev = settings.dallas_gpio; + settings.dallas_gpio = data[1]; + check_flag(prev, settings.dallas_gpio, ChangeFlags::SENSOR); + prev = settings.rx_gpio; + settings.rx_gpio = data[2]; + check_flag(prev, settings.rx_gpio, ChangeFlags::RESTART); + prev = settings.tx_gpio; + settings.tx_gpio = data[3]; + check_flag(prev, settings.tx_gpio, ChangeFlags::RESTART); + prev = settings.pbutton_gpio; + settings.pbutton_gpio = data[4]; + check_flag(prev, settings.pbutton_gpio, ChangeFlags::BUTTON); + prev = settings.phy_type; + settings.phy_type = data[5]; + check_flag(prev, settings.phy_type, ChangeFlags::RESTART); + prev = settings.eth_power; + settings.eth_power = data[6]; + check_flag(prev, settings.eth_power, ChangeFlags::RESTART); + prev = settings.eth_phy_addr; + settings.eth_phy_addr = data[7]; + check_flag(prev, settings.eth_phy_addr, ChangeFlags::RESTART); + prev = settings.eth_clock_mode; + settings.eth_clock_mode = data[8]; + check_flag(prev, settings.eth_clock_mode, ChangeFlags::RESTART); + // tx_mode, rx and tx pins prev = settings.tx_mode; settings.tx_mode = root["tx_mode"] | EMSESP_DEFAULT_TX_MODE; check_flag(prev, settings.tx_mode, ChangeFlags::UART); - prev = settings.rx_gpio; - settings.rx_gpio = root["rx_gpio"] | default_rx_gpio; - check_flag(prev, settings.rx_gpio, ChangeFlags::RESTART); - prev = settings.tx_gpio; - settings.tx_gpio = root["tx_gpio"] | default_tx_gpio; - check_flag(prev, settings.tx_gpio, ChangeFlags::RESTART); // syslog prev = settings.syslog_enabled; @@ -188,15 +220,7 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { } #endif - // button - prev = settings.pbutton_gpio; - settings.pbutton_gpio = root["pbutton_gpio"] | default_pbutton_gpio; - check_flag(prev, settings.pbutton_gpio, ChangeFlags::BUTTON); - // temperaturesensor - prev = settings.dallas_gpio; - settings.dallas_gpio = root["dallas_gpio"] | default_dallas_gpio; - check_flag(prev, settings.dallas_gpio, ChangeFlags::SENSOR); prev = settings.dallas_parasite; settings.dallas_parasite = root["dallas_parasite"] | EMSESP_DEFAULT_DALLAS_PARASITE; check_flag(prev, settings.dallas_parasite, ChangeFlags::SENSOR); @@ -216,9 +240,6 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { check_flag(prev, settings.shower_alert_coldshot, ChangeFlags::SHOWER); // led - prev = settings.led_gpio; - settings.led_gpio = root["led_gpio"] | default_led_gpio; - check_flag(prev, settings.led_gpio, ChangeFlags::LED); prev = settings.hide_led; settings.hide_led = root["hide_led"] | EMSESP_DEFAULT_HIDE_LED; check_flag(prev, settings.hide_led, ChangeFlags::LED); @@ -228,19 +249,6 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { settings.analog_enabled = root["analog_enabled"] | EMSESP_DEFAULT_ANALOG_ENABLED; check_flag(prev, settings.analog_enabled, ChangeFlags::ADC); - // ethernet - prev = settings.phy_type; - settings.phy_type = root["phy_type"] | default_phy_type; - check_flag(prev, settings.phy_type, ChangeFlags::RESTART); - prev = settings.eth_power; - settings.eth_power = root["eth_power"] | default_eth_power; - check_flag(prev, settings.eth_power, ChangeFlags::RESTART); - prev = settings.eth_phy_addr; - settings.eth_phy_addr = root["eth_phy_addr"] | default_eth_phy_addr; - check_flag(prev, settings.eth_phy_addr, ChangeFlags::RESTART); - prev = settings.eth_clock_mode; - settings.eth_clock_mode = root["eth_clock_mode"] | default_eth_clock_mode; - check_flag(prev, settings.eth_clock_mode, ChangeFlags::RESTART); // // these need system restarts first before settings are activated...