From 090387ef37f3d32c9a05072727da2841f70d1b78 Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 17 Nov 2025 17:49:30 +0100 Subject: [PATCH 01/54] replace disabled sensor gpio (99) with code logic --- interface/src/app/main/Sensors.tsx | 43 +++++++++------- .../src/app/main/SensorsAnalogDialog.tsx | 18 +------ interface/src/app/main/types.ts | 14 +++--- interface/src/app/main/validators.ts | 8 --- mock-api/restServer.ts | 49 +++++++++++++------ src/core/analogsensor.cpp | 7 +-- src/web/WebDataService.cpp | 4 +- 7 files changed, 75 insertions(+), 68 deletions(-) diff --git a/interface/src/app/main/Sensors.tsx b/interface/src/app/main/Sensors.tsx index f1ba46979..b2e90736e 100644 --- a/interface/src/app/main/Sensors.tsx +++ b/interface/src/app/main/Sensors.tsx @@ -1,4 +1,4 @@ -import { useCallback, useContext, useMemo, useState } from 'react'; +import { useCallback, useContext, useMemo, useRef, useState } from 'react'; import { toast } from 'react-toastify'; import AddCircleOutlineOutlinedIcon from '@mui/icons-material/AddCircleOutlineOutlined'; @@ -54,7 +54,6 @@ const MS_PER_SECOND = 1000; const MS_PER_MINUTE = 60 * MS_PER_SECOND; const MS_PER_HOUR = 60 * MS_PER_MINUTE; const MS_PER_DAY = 24 * MS_PER_HOUR; -const DEFAULT_GPIO = 99; // not set const MIN_TEMP_ID = -100; const MAX_TEMP_ID = 100; const GPIO_25 = 25; @@ -128,15 +127,21 @@ const Sensors = () => { const [temperatureDialogOpen, setTemperatureDialogOpen] = useState(false); const [analogDialogOpen, setAnalogDialogOpen] = useState(false); const [creating, setCreating] = useState(false); + const firstAvailableGPIO = useRef(undefined); const { data: sensorData, send: fetchSensorData } = useRequest(readSensorData, { initialData: { ts: [], as: [], analog_enabled: false, - valid_gpio_list: [], + valid_gpio_list: [] as number[], platform: 'ESP32' } + }).onSuccess((event) => { + // store the first available GPIO in a ref + if (event.data.valid_gpio_list.length > 0) { + firstAvailableGPIO.current = event.data.valid_gpio_list[0]; + } }); const { send: sendTemperatureSensor } = useRequest( @@ -186,10 +191,14 @@ const Sensors = () => { sortToggleType: SortToggleType.AlternateWithReset, sortFns: { GPIO: (array) => - [...array].sort((a, b) => (a as AnalogSensor).g - (b as AnalogSensor).g), + [...array].sort( + (a, b) => ((a as AnalogSensor)?.g ?? 0) - ((b as AnalogSensor)?.g ?? 0) + ), NAME: (array) => [...array].sort((a, b) => - (a as AnalogSensor).n.localeCompare((b as AnalogSensor).n) + ((a as AnalogSensor)?.n ?? '').localeCompare( + (b as AnalogSensor)?.n ?? '' + ) ), TYPE: (array) => [...array].sort((a, b) => (a as AnalogSensor).t - (b as AnalogSensor).t), @@ -338,19 +347,23 @@ const Sensors = () => { }, [fetchSensorData]); const addAnalogSensor = useCallback(() => { + if (firstAvailableGPIO.current === undefined) { + toast.error('No available GPIO found'); + return; + } setCreating(true); setSelectedAnalogSensor({ id: Math.floor(Math.random() * (MAX_TEMP_ID - MIN_TEMP_ID) + MIN_TEMP_ID), n: '', - g: DEFAULT_GPIO, - u: 0, + g: firstAvailableGPIO.current, + u: DeviceValueUOM.NONE, v: 0, o: 0, - t: 0, f: 1, + t: AnalogType.NOTUSED, d: false, - o_n: '', - s: false + s: false, + o_n: '' }); setAnalogDialogOpen(true); }, []); @@ -447,7 +460,7 @@ const Sensors = () => { item={as} onClick={() => updateAnalogSensor(as)} > - {as.g !== 99 ? as.g : ''} + {as.g} {as.n} {AnalogTypeNames[as.t]} {(as.t === AnalogType.DIGITAL_OUT && @@ -455,14 +468,10 @@ const Sensors = () => { as.g !== GPIO_26) || as.t === AnalogType.DIGITAL_IN || as.t === AnalogType.PULSE ? ( - - {as.g !== 99 ? (as.v ? LL.ON() : LL.OFF()) : ''} - + {as.v ? LL.ON() : LL.OFF()} ) : ( - {as.t !== AnalogType.NOTUSED && as.g !== 99 - ? formatValue(as.v, as.u) - : ''} + {as.t !== AnalogType.NOTUSED ? formatValue(as.v, as.u) : ''} )} diff --git a/interface/src/app/main/SensorsAnalogDialog.tsx b/interface/src/app/main/SensorsAnalogDialog.tsx index c9d99c42c..179d1fc2b 100644 --- a/interface/src/app/main/SensorsAnalogDialog.tsx +++ b/interface/src/app/main/SensorsAnalogDialog.tsx @@ -152,20 +152,6 @@ const SensorsAnalogDialog = ({ [creating, LL] ); - // Ensure the current GPIO is in the list when no creating - // note GPIO 99 means not set - const availableGPIOs = useMemo(() => { - const filteredList = analogGPIOList.filter((gpio) => gpio !== 99); - if ( - editItem.g !== undefined && - editItem.g !== 99 && - !filteredList.includes(editItem.g) - ) { - return [...filteredList, editItem.g].sort((a, b) => a - b); - } - return filteredList; - }, [analogGPIOList, editItem.g]); - return ( {dialogTitle} @@ -175,12 +161,12 @@ const SensorsAnalogDialog = ({ name="g" label="GPIO" value={editItem.g} - sx={{ width: '8ch' }} + sx={{ width: '9ch' }} disabled={editItem.s} select onChange={updateFormValue} > - {availableGPIOs?.map((gpio: number) => ( + {analogGPIOList?.map((gpio: number) => ( {gpio} diff --git a/interface/src/app/main/types.ts b/interface/src/app/main/types.ts index 280dbc1c3..cea98fd44 100644 --- a/interface/src/app/main/types.ts +++ b/interface/src/app/main/types.ts @@ -89,15 +89,15 @@ export interface TemperatureSensor { export interface AnalogSensor { id: number; g: number; // GPIO - n: string; - v: number; - u: number; - o: number; - f: number; - t: number; + n: string; // name + v: number; // value + u: number; // uom + o: number; // offset + f: number; // factor + t: number; // type d: boolean; // deleted flag s: boolean; // system sensor flag - o_n?: string; + o_n?: string; // original name } export interface WriteTemperatureSensor { diff --git a/interface/src/app/main/validators.ts b/interface/src/app/main/validators.ts index 7ededce0c..8f320dcfb 100644 --- a/interface/src/app/main/validators.ts +++ b/interface/src/app/main/validators.ts @@ -310,14 +310,6 @@ export const analogSensorItemValidation = ( { required: true, message: 'Name is required' }, NAME_PATTERN, uniqueAnalogNameValidator(sensors, sensor.o_n) - ], - g: [ - { - required: true, - type: 'number', - min: 1, - message: 'GPIO is required' - } ] }); }; diff --git a/mock-api/restServer.ts b/mock-api/restServer.ts index 1268aeb1f..7fe7db9f9 100644 --- a/mock-api/restServer.ts +++ b/mock-api/restServer.ts @@ -276,10 +276,10 @@ function updateMask(entity: any, de: any, dd: any) { const old_custom_name = dd.nodes[dd_objIndex].cn; console.log( 'comparing names, old (' + - old_custom_name + - ') with new (' + - new_custom_name + - ')' + old_custom_name + + ') with new (' + + new_custom_name + + ')' ); if (old_custom_name !== new_custom_name) { changed = true; @@ -375,15 +375,15 @@ function check_upgrade(version: string) { console.log( 'Upgrade this version (' + - THIS_VERSION + - ') to dev (' + - dev_version + - ') is ' + - (DEV_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') + - ' and to stable (' + - stable_version + - ') is ' + - (STABLE_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') + THIS_VERSION + + ') to dev (' + + dev_version + + ') is ' + + (DEV_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') + + ' and to stable (' + + stable_version + + ') is ' + + (STABLE_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') ); data = { emsesp_version: THIS_VERSION, @@ -987,7 +987,7 @@ const emsesp_sensordata = { { id: 1, g: 35, n: 'motor', v: 0, u: 0, o: 17, f: 0, t: 0, d: false, s: false }, { id: 2, - g: 37, + g: 34, n: 'External_switch', v: 13, u: 0, @@ -1047,7 +1047,7 @@ const emsesp_sensordata = { } ], analog_enabled: true, - valid_gpio_list: [0, 2, 5, 12, 13, 15, 18, 19, 23, 25, 26, 27, 33, 37, 38] + valid_gpio_list: [] as number[] }; const activity = { @@ -4540,6 +4540,25 @@ router .get(EMSESP_SENSOR_DATA_ENDPOINT, () => { // random change the zolder temperature 0-100 emsesp_sensordata.ts[2].t = Math.floor(Math.random() * 100); + + // Build list of available GPIOs (S3 board pins) excluding used ones + // and sort it + const allGPIOs = [2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 21, 33, 34, 35, 36, 37, 38, 45, 46]; + const usedGPIOs = new Set([ + settings.led_gpio, + settings.dallas_gpio, + settings.pbutton_gpio, + settings.rx_gpio, + settings.tx_gpio, + ...emsesp_sensordata.as.map((item) => item.g) + ]); + + emsesp_sensordata.valid_gpio_list = allGPIOs + .filter((gpio) => !usedGPIOs.has(gpio)) + .sort((a, b) => a - b); + + // console.log('valid_gpio_list', emsesp_sensordata.valid_gpio_list); + return emsesp_sensordata; }) .get(EMSESP_DEVICEDATA_ENDPOINT1, (request) => diff --git a/src/core/analogsensor.cpp b/src/core/analogsensor.cpp index cfa19f91c..988cca9a6 100644 --- a/src/core/analogsensor.cpp +++ b/src/core/analogsensor.cpp @@ -157,12 +157,13 @@ void AnalogSensor::reload(bool get_nvs) { if (!found) { // check if the GPIO is valid before registering. If not, force set the sensor to disabled, but don't remove it // should only trigger if uploading a customization file with invalid gpios. + AnalogType type = static_cast(sensor.type); if (!EMSESP::system_.is_valid_gpio(sensor.gpio)) { LOG_WARNING("Bad GPIO %d for Sensor %s. Disabling.", sensor.gpio, sensor.name.c_str()); - sensors_.emplace_back(99, sensor.name, sensor.offset, sensor.factor, sensor.uom, sensor.type, sensor.is_system); - } else { - sensors_.emplace_back(sensor.gpio, sensor.name, sensor.offset, sensor.factor, sensor.uom, sensor.type, sensor.is_system); + type = AnalogType::NOTUSED; } + sensors_.emplace_back(sensor.gpio, sensor.name, sensor.offset, sensor.factor, sensor.uom, type, sensor.is_system); + sensors_.back().ha_registered = false; // this will trigger recreate of the HA config if (sensor.type == AnalogType::COUNTER || sensor.type >= AnalogType::DIGITAL_OUT) { sensors_.back().set_value(sensor.offset); diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index 1ba81c416..3db967c7d 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -146,7 +146,7 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) { obj["t"] = sensor.type(); obj["s"] = sensor.is_system(); - if (sensor.type() != AnalogSensor::AnalogType::NOTUSED && sensor.gpio() != 99) { + if (sensor.type() != AnalogSensor::AnalogType::NOTUSED) { obj["v"] = Helpers::transformNumFloat(sensor.value()); // is optional and is a float } else { obj["v"] = 0; // must have a value for web sorting to work @@ -436,7 +436,7 @@ void WebDataService::dashboard_data(AsyncWebServerRequest * request) { uint8_t count = 0; for (const auto & sensor : EMSESP::analogsensor_.sensors()) { // ignore system and disabled sensors - if (sensor.is_system() || sensor.type() == AnalogSensor::AnalogType::NOTUSED || sensor.gpio() == 99) { + if (sensor.is_system() || sensor.type() == AnalogSensor::AnalogType::NOTUSED) { continue; } JsonObject node = nodes.add(); From 615c5e84394d24175f77ffa94dc20cd9ea0d1ec5 Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 17 Nov 2025 17:49:37 +0100 Subject: [PATCH 02/54] addition --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 827f0754c..dd7688cea 100644 --- a/.gitignore +++ b/.gitignore @@ -74,4 +74,5 @@ sdkconfig.* sdkconfig_tasmota_esp32 pnpm-lock.yaml package.json -.cache/ \ No newline at end of file +.cache/ +interface/.tsbuildinfo From 26d26cf08840d32bfe172205989cd00e5cba13fa Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 17 Nov 2025 17:50:34 +0100 Subject: [PATCH 03/54] formatting --- mock-api/restServer.ts | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/mock-api/restServer.ts b/mock-api/restServer.ts index 7fe7db9f9..12ce11269 100644 --- a/mock-api/restServer.ts +++ b/mock-api/restServer.ts @@ -276,10 +276,10 @@ function updateMask(entity: any, de: any, dd: any) { const old_custom_name = dd.nodes[dd_objIndex].cn; console.log( 'comparing names, old (' + - old_custom_name + - ') with new (' + - new_custom_name + - ')' + old_custom_name + + ') with new (' + + new_custom_name + + ')' ); if (old_custom_name !== new_custom_name) { changed = true; @@ -375,15 +375,15 @@ function check_upgrade(version: string) { console.log( 'Upgrade this version (' + - THIS_VERSION + - ') to dev (' + - dev_version + - ') is ' + - (DEV_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') + - ' and to stable (' + - stable_version + - ') is ' + - (STABLE_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') + THIS_VERSION + + ') to dev (' + + dev_version + + ') is ' + + (DEV_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') + + ' and to stable (' + + stable_version + + ') is ' + + (STABLE_VERSION_IS_UPGRADEABLE ? 'YES' : 'NO') ); data = { emsesp_version: THIS_VERSION, @@ -4543,7 +4543,10 @@ router // Build list of available GPIOs (S3 board pins) excluding used ones // and sort it - const allGPIOs = [2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 21, 33, 34, 35, 36, 37, 38, 45, 46]; + const allGPIOs = [ + 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 21, 33, 34, 35, 36, 37, 38, + 45, 46 + ]; const usedGPIOs = new Set([ settings.led_gpio, settings.dallas_gpio, From 24421a0224698362e47508f90c09de076caa8c26 Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 17 Nov 2025 17:50:43 +0100 Subject: [PATCH 04/54] package update --- interface/pnpm-lock.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/pnpm-lock.yaml b/interface/pnpm-lock.yaml index 87fcb5464..297155a6c 100644 --- a/interface/pnpm-lock.yaml +++ b/interface/pnpm-lock.yaml @@ -1027,8 +1027,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.8.28: - resolution: {integrity: sha512-gYjt7OIqdM0PcttNYP2aVrr2G0bMALkBaoehD4BuRGjAOtipg0b6wHg1yNL+s5zSnLZZrGHOw4IrND8CD+3oIQ==} + baseline-browser-mapping@2.8.29: + resolution: {integrity: sha512-sXdt2elaVnhpDNRDz+1BDx1JQoJRuNk7oVlAlbGiFkLikHCAQiccexF/9e91zVi6RCgqspl04aP+6Cnl9zRLrA==} hasBin: true bin-build@3.0.0: @@ -3963,7 +3963,7 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.8.28: {} + baseline-browser-mapping@2.8.29: {} bin-build@3.0.0: dependencies: @@ -4020,7 +4020,7 @@ snapshots: browserslist@4.28.0: dependencies: - baseline-browser-mapping: 2.8.28 + baseline-browser-mapping: 2.8.29 caniuse-lite: 1.0.30001755 electron-to-chromium: 1.5.254 node-releases: 2.0.27 From 80dd16740d7e57ae4e6ebe91f3a51f56425fb639 Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 17 Nov 2025 23:00:45 +0100 Subject: [PATCH 05/54] some fixes on https://github.com/emsesp/EMS-ESP32/pull/2750 --- .../src/app/main/SensorsAnalogDialog.tsx | 25 +++++++--- interface/src/app/main/types.ts | 2 +- .../components/inputs/ValidatedTextField.tsx | 17 +++++-- src/core/analogsensor.cpp | 7 +-- src/core/system.cpp | 48 ++++++++++--------- src/core/system.h | 4 +- src/web/WebCustomizationService.cpp | 7 +++ src/web/WebDataService.cpp | 3 +- 8 files changed, 75 insertions(+), 38 deletions(-) diff --git a/interface/src/app/main/SensorsAnalogDialog.tsx b/interface/src/app/main/SensorsAnalogDialog.tsx index 179d1fc2b..83e29b635 100644 --- a/interface/src/app/main/SensorsAnalogDialog.tsx +++ b/interface/src/app/main/SensorsAnalogDialog.tsx @@ -115,6 +115,23 @@ const SensorsAnalogDialog = ({ [] ); + const analogGPIOMenuItems = () => + // add selectedItem.g to the list + [ + ...(analogGPIOList?.includes(selectedItem.g) || selectedItem.g === undefined + ? analogGPIOList + : [selectedItem.g, ...analogGPIOList]) + ] + .filter((gpio, idx, arr) => arr.indexOf(gpio) === idx) + .sort((a, b) => a - b) + .map((gpio: number) => { + return ( + + {gpio} + + ); + }); + // Reset form when dialog opens or selectedItem changes useEffect(() => { if (open) { @@ -162,15 +179,11 @@ const SensorsAnalogDialog = ({ label="GPIO" value={editItem.g} sx={{ width: '9ch' }} - disabled={editItem.s} + disabled={editItem.s || !creating} select onChange={updateFormValue} > - {analogGPIOList?.map((gpio: number) => ( - - {gpio} - - ))} + {analogGPIOMenuItems()} = ({ error={!!errors} {...rest} aria-label="Error" - slotProps={{ - inputLabel: { - style: rest.disabled ? { color: 'grey' } : undefined + sx={{ + '& .MuiInputBase-input.Mui-disabled': { + WebkitTextFillColor: 'grey' } }} + {...(rest.disabled && { + slotProps: { + select: { + IconComponent: () => null + }, + inputLabel: { + style: { color: 'grey' } + } + } + })} + color={rest.disabled ? 'secondary' : 'primary'} /> {errors?.map((e) => ( diff --git a/src/core/analogsensor.cpp b/src/core/analogsensor.cpp index 988cca9a6..2a06ef9b5 100644 --- a/src/core/analogsensor.cpp +++ b/src/core/analogsensor.cpp @@ -472,8 +472,9 @@ void AnalogSensor::loop() { measure(); // take the measurements } -// update analog information name and offset +// update analog information name, offset, factor, uom, type, deleted, is_system // a type value of -1 is used to delete the sensor +// the gpio is the key bool AnalogSensor::update(uint8_t gpio, std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted, bool is_system) { // first see if we can find the sensor in our customization list bool found_sensor = false; @@ -521,7 +522,7 @@ bool AnalogSensor::update(uint8_t gpio, std::string & name, double offset, doubl } // we didn't find it, it's new, so create and store it in the customization list - // gpio is already checked in web interface, should never trigger. + // gpio is already checked in web interface if (!found_sensor && EMSESP::system_.is_valid_gpio(gpio)) { found_sensor = true; EMSESP::webCustomizationService.update([&](WebCustomization & settings) { @@ -534,7 +535,7 @@ bool AnalogSensor::update(uint8_t gpio, std::string & name, double offset, doubl newSensor.type = type; newSensor.is_system = is_system; settings.analogCustomizations.push_back(newSensor); - LOG_DEBUG("Adding new customization for analog sensor GPIO %02d", gpio); + LOG_DEBUG("Adding customization for analog sensor GPIO %02d", gpio); return StateUpdateResult::CHANGED; // persist the change }); } diff --git a/src/core/system.cpp b/src/core/system.cpp index f24a3f9e1..f78560fdc 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -415,8 +415,8 @@ void System::reload_settings() { EMSESP::webSettingsService.read([&](WebSettings & settings) { version_ = settings.version; // first check gpios, priority to rx and tx - rx_gpio_ = is_valid_gpio(settings.rx_gpio) ? settings.rx_gpio : 0; - tx_gpio_ = is_valid_gpio(settings.tx_gpio) ? settings.tx_gpio : 0; + rx_gpio_ = is_valid_gpio(settings.rx_gpio); + tx_gpio_ = is_valid_gpio(settings.tx_gpio); pbutton_gpio_ = is_valid_gpio(settings.pbutton_gpio) ? settings.pbutton_gpio : 0; dallas_gpio_ = is_valid_gpio(settings.dallas_gpio) ? settings.dallas_gpio : 0; led_gpio_ = is_valid_gpio(settings.led_gpio) ? settings.led_gpio : 0; @@ -456,9 +456,9 @@ void System::reload_settings() { }); } -// check for valid ESP32 pins -bool System::is_valid_gpio(uint8_t pin) { - auto valid_gpios = valid_gpio_list(); +// check if a pin is valid ESP32 pin and not used by application settings +bool System::is_valid_gpio(uint8_t pin, bool exclude_used) { + auto valid_gpios = valid_gpio_list(exclude_used); return std::find(valid_gpios.begin(), valid_gpios.end(), pin) != valid_gpios.end(); } @@ -2356,12 +2356,12 @@ std::vector System::string_range_to_vector(const std::string & range) { return valid_gpios; } -// return a list of valid GPIOs for the ESP32 board +// return a list of valid GPIOs for the ESP32 board that can be used // notes: -// - we allow 0, which is used sometimes to indicate a disabled pin -// - also allow input only pins are accepted (34-39) on some boards +// - we allow 0, which is used sometimes to indicate a disabled pin (e.g. button, led) +// - we also allow input only pins are accepted (34-39) on some boards, excluding 39 // - and allow pins 33-38 for octal SPI for 32M vchip version on some boards -std::vector System::valid_gpio_list() { +std::vector System::valid_gpio_list(bool exclude_used) { // get free gpios based on board/platform type #if CONFIG_IDF_TARGET_ESP32C3 // https://www.wemos.cc/en/latest/c3/c3_mini.html @@ -2390,21 +2390,25 @@ 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, gpio 0 means disabled, except for pbutton - for (const auto & gpio : valid_gpios) { - 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()); + // filter out GPIOs already used in application settings and analog sensors, if enabled + if (exclude_used) { + // application settings + for (const auto & gpio : valid_gpios) { + 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()); + } } - } - // filter out GPIOs already used in analog sensors, if enabled - if (EMSESP::system_.analog_enabled_) { - for (const auto & sensor : EMSESP::analogsensor_.sensors()) { - if (std::find(valid_gpios.begin(), valid_gpios.end(), sensor.gpio()) != valid_gpios.end()) { - valid_gpios.erase(std::find(valid_gpios.begin(), valid_gpios.end(), sensor.gpio())); + // analog sensors + if (EMSESP::system_.analog_enabled_) { + // TODO: check if core_voltage and supply_voltage are already used + for (const auto & sensor : EMSESP::analogsensor_.sensors()) { + if (std::find(valid_gpios.begin(), valid_gpios.end(), sensor.gpio()) != valid_gpios.end()) { + valid_gpios.erase(std::find(valid_gpios.begin(), valid_gpios.end(), sensor.gpio())); + } } } } diff --git a/src/core/system.h b/src/core/system.h index a73b9700c..bd6e6500f 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -141,7 +141,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); - bool is_valid_gpio(uint8_t pin); + bool is_valid_gpio(uint8_t pin, bool exclude_used = false); static bool load_board_profile(std::vector & data, const std::string & board_profile); static bool readCommand(const char * data); @@ -342,7 +342,7 @@ class System { test_set_all_active_ = n; } - static std::vector valid_gpio_list(); + static std::vector valid_gpio_list(bool exclude_used = false); #if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 float temperature() { diff --git a/src/web/WebCustomizationService.cpp b/src/web/WebCustomizationService.cpp index b05e20947..1005a2ae8 100644 --- a/src/web/WebCustomizationService.cpp +++ b/src/web/WebCustomizationService.cpp @@ -117,6 +117,13 @@ StateUpdateResult WebCustomization::update(JsonObject root, WebCustomization & c auto analogJsons = root["as"].as(); for (const JsonObject analogJson : analogJsons) { // create each of the sensor, overwriting any previous settings + // if the gpio is invalid skip the sensor + if (!EMSESP::system_.is_valid_gpio(analogJson["gpio"].as(), true)) { + EMSESP::logger().warning("Invalid GPIO %d for Sensor %s. Skipping.", + analogJson["gpio"].as(), + analogJson["name"].as().c_str()); + continue; + } auto analog = AnalogCustomization(); analog.gpio = analogJson["gpio"]; analog.name = analogJson["name"].as(); diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index 3db967c7d..f040b883b 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -157,8 +157,9 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) { root["analog_enabled"] = EMSESP::analog_enabled(); root["platform"] = EMSESP_PLATFORM; + // send back a list of valid GPIOs that can be used for analog sensors, excluding those already used JsonArray valid_gpio_list = root["valid_gpio_list"].to(); - for (const auto & gpio : EMSESP::system_.valid_gpio_list()) { + for (const auto & gpio : EMSESP::system_.valid_gpio_list(true)) { valid_gpio_list.add(gpio); } From 5e7768f912d955221e5621ab1f32ecd1f262d183 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 18 Nov 2025 20:39:51 +0100 Subject: [PATCH 06/54] package update --- interface/package.json | 4 +- interface/pnpm-lock.yaml | 240 +++++++++++++++++++-------------------- 2 files changed, 122 insertions(+), 122 deletions(-) diff --git a/interface/package.json b/interface/package.json index 5597e723b..80b1119d7 100644 --- a/interface/package.json +++ b/interface/package.json @@ -53,7 +53,7 @@ "@preact/preset-vite": "^2.10.2", "@trivago/prettier-plugin-sort-imports": "^6.0.0", "@types/node": "^24.10.1", - "@types/react": "^19.2.5", + "@types/react": "^19.2.6", "@types/react-dom": "^19.2.3", "axe-core": "^4.11.0", "concurrently": "^9.2.1", @@ -62,7 +62,7 @@ "prettier": "^3.6.2", "rollup-plugin-visualizer": "^6.0.5", "terser": "^5.44.1", - "typescript-eslint": "^8.46.4", + "typescript-eslint": "^8.47.0", "vite": "^7.2.2", "vite-plugin-imagemin": "^0.6.1", "vite-tsconfig-paths": "^5.1.4" diff --git a/interface/pnpm-lock.yaml b/interface/pnpm-lock.yaml index 297155a6c..9821c7f24 100644 --- a/interface/pnpm-lock.yaml +++ b/interface/pnpm-lock.yaml @@ -13,22 +13,22 @@ importers: version: 2.2.1(alova@3.3.4) '@emotion/react': specifier: ^11.14.0 - version: 11.14.0(@types/react@19.2.5)(react@19.2.0) + version: 11.14.0(@types/react@19.2.6)(react@19.2.0) '@emotion/styled': specifier: ^11.14.1 - version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0) + version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0) '@mui/icons-material': specifier: ^7.3.5 - version: 7.3.5(@mui/material@7.3.5(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@types/react@19.2.5)(react@19.2.0) + version: 7.3.5(@mui/material@7.3.5(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@types/react@19.2.6)(react@19.2.0) '@mui/material': specifier: ^7.3.5 - version: 7.3.5(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 7.3.5(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@preact/compat': specifier: ^18.3.1 version: 18.3.1(preact@10.27.2) '@table-library/react-table-library': specifier: 4.1.15 - version: 4.1.15(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 4.1.15(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) alova: specifier: 3.3.4 version: 3.3.4 @@ -91,11 +91,11 @@ importers: specifier: ^24.10.1 version: 24.10.1 '@types/react': - specifier: ^19.2.5 - version: 19.2.5 + specifier: ^19.2.6 + version: 19.2.6 '@types/react-dom': specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.5) + version: 19.2.3(@types/react@19.2.6) axe-core: specifier: ^4.11.0 version: 4.11.0 @@ -118,8 +118,8 @@ importers: specifier: ^5.44.1 version: 5.44.1 typescript-eslint: - specifier: ^8.46.4 - version: 8.46.4(eslint@9.39.1)(typescript@5.9.3) + specifier: ^8.47.0 + version: 8.47.0(eslint@9.39.1)(typescript@5.9.3) vite: specifier: ^7.2.2 version: 7.2.2(@types/node@24.10.1)(terser@5.44.1) @@ -879,8 +879,8 @@ packages: peerDependencies: '@types/react': '*' - '@types/react@19.2.5': - resolution: {integrity: sha512-keKxkZMqnDicuvFoJbzrhbtdLSPhj/rZThDlKWCDbgXmUg0rEUFtRssDXKYmtXluZlIqiC5VqkCgRwzuyLHKHw==} + '@types/react@19.2.6': + resolution: {integrity: sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==} '@types/responselike@1.0.3': resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} @@ -888,63 +888,63 @@ packages: '@types/svgo@2.6.4': resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==} - '@typescript-eslint/eslint-plugin@8.46.4': - resolution: {integrity: sha512-R48VhmTJqplNyDxCyqqVkFSZIx1qX6PzwqgcXn1olLrzxcSBDlOsbtcnQuQhNtnNiJ4Xe5gREI1foajYaYU2Vg==} + '@typescript-eslint/eslint-plugin@8.47.0': + resolution: {integrity: sha512-fe0rz9WJQ5t2iaLfdbDc9T80GJy0AeO453q8C3YCilnGozvOyCG5t+EZtg7j7D88+c3FipfP/x+wzGnh1xp8ZA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.46.4 + '@typescript-eslint/parser': ^8.47.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.46.4': - resolution: {integrity: sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==} + '@typescript-eslint/parser@8.47.0': + resolution: {integrity: sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.46.4': - resolution: {integrity: sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==} + '@typescript-eslint/project-service@8.47.0': + resolution: {integrity: sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.46.4': - resolution: {integrity: sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==} + '@typescript-eslint/scope-manager@8.47.0': + resolution: {integrity: sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.46.4': - resolution: {integrity: sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==} + '@typescript-eslint/tsconfig-utils@8.47.0': + resolution: {integrity: sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.46.4': - resolution: {integrity: sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ==} + '@typescript-eslint/type-utils@8.47.0': + resolution: {integrity: sha512-QC9RiCmZ2HmIdCEvhd1aJELBlD93ErziOXXlHEZyuBo3tBiAZieya0HLIxp+DoDWlsQqDawyKuNEhORyku+P8A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.46.4': - resolution: {integrity: sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==} + '@typescript-eslint/types@8.47.0': + resolution: {integrity: sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.46.4': - resolution: {integrity: sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==} + '@typescript-eslint/typescript-estree@8.47.0': + resolution: {integrity: sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.46.4': - resolution: {integrity: sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==} + '@typescript-eslint/utils@8.47.0': + resolution: {integrity: sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.46.4': - resolution: {integrity: sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==} + '@typescript-eslint/visitor-keys@8.47.0': + resolution: {integrity: sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} acorn-jsx@5.3.2: @@ -1337,8 +1337,8 @@ packages: duplexer3@0.1.5: resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==} - electron-to-chromium@1.5.254: - resolution: {integrity: sha512-DcUsWpVhv9svsKRxnSCZ86SjD+sp32SGidNB37KpqXJncp1mfUgKbHvBomE89WJDbfVKw1mdv5+ikrvd43r+Bg==} + electron-to-chromium@1.5.255: + resolution: {integrity: sha512-Z9oIp4HrFF/cZkDPMpz2XSuVpc1THDpT4dlmATFlJUIBVCy9Vap5/rIXsASP1CscBacBqhabwh8vLctqBwEerQ==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2927,8 +2927,8 @@ packages: peerDependencies: typescript: '>=3.5.1' - typescript-eslint@8.46.4: - resolution: {integrity: sha512-KALyxkpYV5Ix7UhvjTwJXZv76VWsHG+NjNlt/z+a17SOQSiOcBdUXdbJdyXi7RPxrBFECtFOiPwUJQusJuCqrg==} + typescript-eslint@8.47.0: + resolution: {integrity: sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -3268,7 +3268,7 @@ snapshots: '@emotion/memoize@0.9.0': {} - '@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0)': + '@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 '@emotion/babel-plugin': 11.13.5 @@ -3280,7 +3280,7 @@ snapshots: hoist-non-react-statics: 3.3.2 react: 19.2.0 optionalDependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 transitivePeerDependencies: - supports-color @@ -3294,18 +3294,18 @@ snapshots: '@emotion/sheet@1.4.0': {} - '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0)': + '@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 '@emotion/babel-plugin': 11.13.5 '@emotion/is-prop-valid': 1.4.0 - '@emotion/react': 11.14.0(@types/react@19.2.5)(react@19.2.0) + '@emotion/react': 11.14.0(@types/react@19.2.6)(react@19.2.0) '@emotion/serialize': 1.3.3 '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.2.0) '@emotion/utils': 1.4.2 react: 19.2.0 optionalDependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 transitivePeerDependencies: - supports-color @@ -3489,23 +3489,23 @@ snapshots: '@mui/core-downloads-tracker@7.3.5': {} - '@mui/icons-material@7.3.5(@mui/material@7.3.5(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@types/react@19.2.5)(react@19.2.0)': + '@mui/icons-material@7.3.5(@mui/material@7.3.5(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@types/react@19.2.6)(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 - '@mui/material': 7.3.5(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@mui/material': 7.3.5(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: 19.2.0 optionalDependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 - '@mui/material@7.3.5(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@mui/material@7.3.5(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 '@mui/core-downloads-tracker': 7.3.5 - '@mui/system': 7.3.5(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0) - '@mui/types': 7.4.8(@types/react@19.2.5) - '@mui/utils': 7.3.5(@types/react@19.2.5)(react@19.2.0) + '@mui/system': 7.3.5(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0) + '@mui/types': 7.4.8(@types/react@19.2.6) + '@mui/utils': 7.3.5(@types/react@19.2.6)(react@19.2.0) '@popperjs/core': 2.11.8 - '@types/react-transition-group': 4.4.12(@types/react@19.2.5) + '@types/react-transition-group': 4.4.12(@types/react@19.2.6) clsx: 2.1.1 csstype: 3.2.3 prop-types: 15.8.1 @@ -3514,20 +3514,20 @@ snapshots: react-is: 19.2.0 react-transition-group: 4.4.5(react-dom@19.2.0(react@19.2.0))(react@19.2.0) optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.2.5)(react@19.2.0) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0) - '@types/react': 19.2.5 + '@emotion/react': 11.14.0(@types/react@19.2.6)(react@19.2.0) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0) + '@types/react': 19.2.6 - '@mui/private-theming@7.3.5(@types/react@19.2.5)(react@19.2.0)': + '@mui/private-theming@7.3.5(@types/react@19.2.6)(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 - '@mui/utils': 7.3.5(@types/react@19.2.5)(react@19.2.0) + '@mui/utils': 7.3.5(@types/react@19.2.6)(react@19.2.0) prop-types: 15.8.1 react: 19.2.0 optionalDependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 - '@mui/styled-engine@7.3.5(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0))(react@19.2.0)': + '@mui/styled-engine@7.3.5(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0))(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 '@emotion/cache': 11.14.0 @@ -3537,42 +3537,42 @@ snapshots: prop-types: 15.8.1 react: 19.2.0 optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.2.5)(react@19.2.0) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0) + '@emotion/react': 11.14.0(@types/react@19.2.6)(react@19.2.0) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0) - '@mui/system@7.3.5(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0)': + '@mui/system@7.3.5(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 - '@mui/private-theming': 7.3.5(@types/react@19.2.5)(react@19.2.0) - '@mui/styled-engine': 7.3.5(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0))(react@19.2.0) - '@mui/types': 7.4.8(@types/react@19.2.5) - '@mui/utils': 7.3.5(@types/react@19.2.5)(react@19.2.0) + '@mui/private-theming': 7.3.5(@types/react@19.2.6)(react@19.2.0) + '@mui/styled-engine': 7.3.5(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0))(react@19.2.0) + '@mui/types': 7.4.8(@types/react@19.2.6) + '@mui/utils': 7.3.5(@types/react@19.2.6)(react@19.2.0) clsx: 2.1.1 csstype: 3.2.3 prop-types: 15.8.1 react: 19.2.0 optionalDependencies: - '@emotion/react': 11.14.0(@types/react@19.2.5)(react@19.2.0) - '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(@types/react@19.2.5)(react@19.2.0) - '@types/react': 19.2.5 + '@emotion/react': 11.14.0(@types/react@19.2.6)(react@19.2.0) + '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(@types/react@19.2.6)(react@19.2.0) + '@types/react': 19.2.6 - '@mui/types@7.4.8(@types/react@19.2.5)': + '@mui/types@7.4.8(@types/react@19.2.6)': dependencies: '@babel/runtime': 7.28.4 optionalDependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 - '@mui/utils@7.3.5(@types/react@19.2.5)(react@19.2.0)': + '@mui/utils@7.3.5(@types/react@19.2.6)(react@19.2.0)': dependencies: '@babel/runtime': 7.28.4 - '@mui/types': 7.4.8(@types/react@19.2.5) + '@mui/types': 7.4.8(@types/react@19.2.6) '@types/prop-types': 15.7.15 clsx: 2.1.1 prop-types: 15.8.1 react: 19.2.0 react-is: 19.2.0 optionalDependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 '@noble/hashes@1.8.0': {} @@ -3707,9 +3707,9 @@ snapshots: '@sindresorhus/is@0.7.0': {} - '@table-library/react-table-library@4.1.15(@emotion/react@11.14.0(@types/react@19.2.5)(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@table-library/react-table-library@4.1.15(@emotion/react@11.14.0(@types/react@19.2.6)(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: - '@emotion/react': 11.14.0(@types/react@19.2.5)(react@19.2.0) + '@emotion/react': 11.14.0(@types/react@19.2.6)(react@19.2.0) clsx: 1.1.1 react: 19.2.0 react-dom: 19.2.0(react@19.2.0) @@ -3786,15 +3786,15 @@ snapshots: '@types/prop-types@15.7.15': {} - '@types/react-dom@19.2.3(@types/react@19.2.5)': + '@types/react-dom@19.2.3(@types/react@19.2.6)': dependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 - '@types/react-transition-group@4.4.12(@types/react@19.2.5)': + '@types/react-transition-group@4.4.12(@types/react@19.2.6)': dependencies: - '@types/react': 19.2.5 + '@types/react': 19.2.6 - '@types/react@19.2.5': + '@types/react@19.2.6': dependencies: csstype: 3.2.3 @@ -3806,14 +3806,14 @@ snapshots: dependencies: '@types/node': 24.10.1 - '@typescript-eslint/eslint-plugin@8.46.4(@typescript-eslint/parser@8.46.4(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.46.4(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.46.4 - '@typescript-eslint/type-utils': 8.46.4(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.4(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.46.4 + '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.47.0 + '@typescript-eslint/type-utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.47.0 eslint: 9.39.1 graphemer: 1.4.0 ignore: 7.0.5 @@ -3823,41 +3823,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.46.4(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.46.4 - '@typescript-eslint/types': 8.46.4 - '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.46.4 + '@typescript-eslint/scope-manager': 8.47.0 + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.47.0 debug: 4.4.3 eslint: 9.39.1 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.46.4(typescript@5.9.3)': + '@typescript-eslint/project-service@8.47.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.46.4(typescript@5.9.3) - '@typescript-eslint/types': 8.46.4 + '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.9.3) + '@typescript-eslint/types': 8.47.0 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.46.4': + '@typescript-eslint/scope-manager@8.47.0': dependencies: - '@typescript-eslint/types': 8.46.4 - '@typescript-eslint/visitor-keys': 8.46.4 + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/visitor-keys': 8.47.0 - '@typescript-eslint/tsconfig-utils@8.46.4(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.47.0(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.46.4(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.47.0(eslint@9.39.1)(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.46.4 - '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.4(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) debug: 4.4.3 eslint: 9.39.1 ts-api-utils: 2.1.0(typescript@5.9.3) @@ -3865,14 +3865,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.46.4': {} + '@typescript-eslint/types@8.47.0': {} - '@typescript-eslint/typescript-estree@8.46.4(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.47.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.46.4(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.46.4(typescript@5.9.3) - '@typescript-eslint/types': 8.46.4 - '@typescript-eslint/visitor-keys': 8.46.4 + '@typescript-eslint/project-service': 8.47.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.9.3) + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/visitor-keys': 8.47.0 debug: 4.4.3 fast-glob: 3.3.3 is-glob: 4.0.3 @@ -3883,20 +3883,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.46.4(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/utils@8.47.0(eslint@9.39.1)(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) - '@typescript-eslint/scope-manager': 8.46.4 - '@typescript-eslint/types': 8.46.4 - '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.47.0 + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) eslint: 9.39.1 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.46.4': + '@typescript-eslint/visitor-keys@8.47.0': dependencies: - '@typescript-eslint/types': 8.46.4 + '@typescript-eslint/types': 8.47.0 eslint-visitor-keys: 4.2.1 acorn-jsx@5.3.2(acorn@8.15.0): @@ -4022,7 +4022,7 @@ snapshots: dependencies: baseline-browser-mapping: 2.8.29 caniuse-lite: 1.0.30001755 - electron-to-chromium: 1.5.254 + electron-to-chromium: 1.5.255 node-releases: 2.0.27 update-browserslist-db: 1.1.4(browserslist@4.28.0) @@ -4367,7 +4367,7 @@ snapshots: duplexer3@0.1.5: {} - electron-to-chromium@1.5.254: {} + electron-to-chromium@1.5.255: {} emoji-regex@8.0.0: {} @@ -5919,12 +5919,12 @@ snapshots: dependencies: typescript: 5.9.3 - typescript-eslint@8.46.4(eslint@9.39.1)(typescript@5.9.3): + typescript-eslint@8.47.0(eslint@9.39.1)(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.46.4(@typescript-eslint/parser@8.46.4(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/parser': 8.46.4(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.4(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) eslint: 9.39.1 typescript: 5.9.3 transitivePeerDependencies: From 37db2b95047f252448138b9bed21466d0e79a684 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 18 Nov 2025 20:40:07 +0100 Subject: [PATCH 07/54] add comment --- src/core/temperaturesensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/temperaturesensor.cpp b/src/core/temperaturesensor.cpp index a4f744ecf..a306e58a8 100644 --- a/src/core/temperaturesensor.cpp +++ b/src/core/temperaturesensor.cpp @@ -57,7 +57,7 @@ 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_ = EMSESP::system_.is_valid_gpio(settings.dallas_gpio) ? settings.dallas_gpio : 0; + dallas_gpio_ = EMSESP::system_.is_valid_gpio(settings.dallas_gpio) ? settings.dallas_gpio : 0; // we use 0 for disabled parasite_ = settings.dallas_parasite; }); EMSESP::system_.dallas_gpio(dallas_gpio_); // set to system for checks From 901a27140cbadd368bab8293dfa594e0b8c2298a Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 18 Nov 2025 20:41:30 +0100 Subject: [PATCH 08/54] only dallas and led use GPIO 0 for disabled --- src/core/system.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/core/system.cpp b/src/core/system.cpp index f78560fdc..2af768b5d 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -406,20 +406,14 @@ 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; // first check gpios, priority to rx and tx rx_gpio_ = is_valid_gpio(settings.rx_gpio); tx_gpio_ = is_valid_gpio(settings.tx_gpio); - pbutton_gpio_ = is_valid_gpio(settings.pbutton_gpio) ? settings.pbutton_gpio : 0; - dallas_gpio_ = is_valid_gpio(settings.dallas_gpio) ? settings.dallas_gpio : 0; - led_gpio_ = is_valid_gpio(settings.led_gpio) ? settings.led_gpio : 0; + pbutton_gpio_ = is_valid_gpio(settings.pbutton_gpio); + dallas_gpio_ = is_valid_gpio(settings.dallas_gpio) ? settings.dallas_gpio : 0; // we use 0 for disabled + led_gpio_ = is_valid_gpio(settings.led_gpio) ? settings.led_gpio : 0; // we use 0 for disabled analog_enabled_ = settings.analog_enabled; low_clock_ = settings.low_clock; @@ -2404,7 +2398,6 @@ std::vector System::valid_gpio_list(bool exclude_used) { // analog sensors if (EMSESP::system_.analog_enabled_) { - // TODO: check if core_voltage and supply_voltage are already used for (const auto & sensor : EMSESP::analogsensor_.sensors()) { if (std::find(valid_gpios.begin(), valid_gpios.end(), sensor.gpio()) != valid_gpios.end()) { valid_gpios.erase(std::find(valid_gpios.begin(), valid_gpios.end(), sensor.gpio())); @@ -2413,7 +2406,7 @@ std::vector System::valid_gpio_list(bool exclude_used) { } } - // sort the list of valid GPIOs + // sort the list of valid GPIOs. This is also done in the web interface, so client side. std::sort(valid_gpios.begin(), valid_gpios.end()); return valid_gpios; From 5454e7dd1647015af29b64e7d8143d4aff6139fd Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 18 Nov 2025 21:37:55 +0100 Subject: [PATCH 09/54] warning message formatting so its same as Dashboard --- interface/src/app/main/Devices.tsx | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/interface/src/app/main/Devices.tsx b/interface/src/app/main/Devices.tsx index 84c2b1be8..f96adfb89 100644 --- a/interface/src/app/main/Devices.tsx +++ b/interface/src/app/main/Devices.tsx @@ -533,19 +533,17 @@ const Devices = memo(() => { const renderCoreData = () => ( <> - - - {!coreData.connected && ( - - )} - - {coreData.connected && ( + {!coreData.connected ? ( + + ) : ( + + { )}
- )} -
-
+
+
+ )} ); From 56e8ccdfc4db9580d41e0502af71d2e17b2ad3d6 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 18 Nov 2025 21:38:19 +0100 Subject: [PATCH 10/54] remove gpio checks, as they are performed in supporting functions --- src/core/system.cpp | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/core/system.cpp b/src/core/system.cpp index 2af768b5d..d1f6cb6d7 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -408,12 +408,15 @@ void System::syslog_init() { void System::reload_settings() { EMSESP::webSettingsService.read([&](WebSettings & settings) { version_ = settings.version; - // first check gpios, priority to rx and tx - rx_gpio_ = is_valid_gpio(settings.rx_gpio); - tx_gpio_ = is_valid_gpio(settings.tx_gpio); - pbutton_gpio_ = is_valid_gpio(settings.pbutton_gpio); - dallas_gpio_ = is_valid_gpio(settings.dallas_gpio) ? settings.dallas_gpio : 0; // we use 0 for disabled - led_gpio_ = is_valid_gpio(settings.led_gpio) ? settings.led_gpio : 0; // we use 0 for disabled + + // rx and tx pins are validated in uart_init() + rx_gpio_ = settings.rx_gpio; + tx_gpio_ = settings.tx_gpio; + + pbutton_gpio_ = settings.pbutton_gpio; // validated in System::button_init() + + dallas_gpio_ = is_valid_gpio(settings.dallas_gpio) ? settings.dallas_gpio : 0; // we use 0 for disabled + led_gpio_ = is_valid_gpio(settings.led_gpio) ? settings.led_gpio : 0; // we use 0 for disabled analog_enabled_ = settings.analog_enabled; low_clock_ = settings.low_clock; @@ -551,6 +554,12 @@ void System::button_init(bool refresh) { reload_settings(); } + // validate button gpio + if (!is_valid_gpio(pbutton_gpio_)) { + LOG_WARNING("Invalid button GPIO. Check config."); + return; + } + #ifndef EMSESP_STANDALONE if (!myPButton_.init(pbutton_gpio_, HIGH)) { LOG_WARNING("Multi-functional button not detected"); @@ -602,8 +611,8 @@ void System::uart_init(bool refresh) { } EMSuart::stop(); - // don't start UART if we have invalid GPIOs - if (rx_gpio_ && tx_gpio_) { + // start UART if we have valid rx and tx GPIOs + if (is_valid_gpio(rx_gpio_) && 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."); @@ -2352,7 +2361,7 @@ std::vector System::string_range_to_vector(const std::string & range) { // return a list of valid GPIOs for the ESP32 board that can be used // notes: -// - we allow 0, which is used sometimes to indicate a disabled pin (e.g. button, led) +// - we allow 0, which is used on some board for the button // - we also allow input only pins are accepted (34-39) on some boards, excluding 39 // - and allow pins 33-38 for octal SPI for 32M vchip version on some boards std::vector System::valid_gpio_list(bool exclude_used) { @@ -2385,12 +2394,14 @@ std::vector System::valid_gpio_list(bool exclude_used) { } // filter out GPIOs already used in application settings and analog sensors, if enabled + // if dallas_gpio or led_gpio is disabled (0), don't remove it from the list (as it could be gpio 0 and valid) if (exclude_used) { // application settings for (const auto & gpio : valid_gpios) { if (gpio == EMSESP::system_.pbutton_gpio_ || (gpio - && (gpio == EMSESP::system_.led_gpio_ || gpio == EMSESP::system_.dallas_gpio_ || gpio == EMSESP::system_.rx_gpio_ + && ((EMSESP::system_.led_gpio_ != 0 && gpio == EMSESP::system_.led_gpio_) + || (EMSESP::system_.dallas_gpio_ != 0 && 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()); } From 8c61735579044497c8f4c932a4ee672f12e62665 Mon Sep 17 00:00:00 2001 From: proddy Date: Thu, 20 Nov 2025 14:12:04 +0100 Subject: [PATCH 11/54] package update --- interface/package.json | 2 +- interface/pnpm-lock.yaml | 246 +++++++++++++++++++-------------------- 2 files changed, 124 insertions(+), 124 deletions(-) diff --git a/interface/package.json b/interface/package.json index 80b1119d7..1a5f04492 100644 --- a/interface/package.json +++ b/interface/package.json @@ -63,7 +63,7 @@ "rollup-plugin-visualizer": "^6.0.5", "terser": "^5.44.1", "typescript-eslint": "^8.47.0", - "vite": "^7.2.2", + "vite": "^7.2.4", "vite-plugin-imagemin": "^0.6.1", "vite-tsconfig-paths": "^5.1.4" }, diff --git a/interface/pnpm-lock.yaml b/interface/pnpm-lock.yaml index 9821c7f24..0dda3df55 100644 --- a/interface/pnpm-lock.yaml +++ b/interface/pnpm-lock.yaml @@ -83,7 +83,7 @@ importers: version: 9.39.1 '@preact/preset-vite': specifier: ^2.10.2 - version: 2.10.2(@babel/core@7.28.5)(preact@10.27.2)(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1)) + version: 2.10.2(@babel/core@7.28.5)(preact@10.27.2)(vite@7.2.4(@types/node@24.10.1)(terser@5.44.1)) '@trivago/prettier-plugin-sort-imports': specifier: ^6.0.0 version: 6.0.0(prettier@3.6.2) @@ -113,7 +113,7 @@ importers: version: 3.6.2 rollup-plugin-visualizer: specifier: ^6.0.5 - version: 6.0.5(rollup@4.53.2) + version: 6.0.5(rollup@4.53.3) terser: specifier: ^5.44.1 version: 5.44.1 @@ -121,14 +121,14 @@ importers: specifier: ^8.47.0 version: 8.47.0(eslint@9.39.1)(typescript@5.9.3) vite: - specifier: ^7.2.2 - version: 7.2.2(@types/node@24.10.1)(terser@5.44.1) + specifier: ^7.2.4 + version: 7.2.4(@types/node@24.10.1)(terser@5.44.1) vite-plugin-imagemin: specifier: ^0.6.1 - version: 0.6.1(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1)) + version: 0.6.1(vite@7.2.4(@types/node@24.10.1)(terser@5.44.1)) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1)) + version: 5.1.4(typescript@5.9.3)(vite@7.2.4(@types/node@24.10.1)(terser@5.44.1)) packages: @@ -679,113 +679,113 @@ packages: resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} engines: {node: '>= 8.0.0'} - '@rollup/rollup-android-arm-eabi@4.53.2': - resolution: {integrity: sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==} + '@rollup/rollup-android-arm-eabi@4.53.3': + resolution: {integrity: sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.53.2': - resolution: {integrity: sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==} + '@rollup/rollup-android-arm64@4.53.3': + resolution: {integrity: sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.53.2': - resolution: {integrity: sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==} + '@rollup/rollup-darwin-arm64@4.53.3': + resolution: {integrity: sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.53.2': - resolution: {integrity: sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==} + '@rollup/rollup-darwin-x64@4.53.3': + resolution: {integrity: sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.53.2': - resolution: {integrity: sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==} + '@rollup/rollup-freebsd-arm64@4.53.3': + resolution: {integrity: sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.53.2': - resolution: {integrity: sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==} + '@rollup/rollup-freebsd-x64@4.53.3': + resolution: {integrity: sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.53.2': - resolution: {integrity: sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==} + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': + resolution: {integrity: sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.53.2': - resolution: {integrity: sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==} + '@rollup/rollup-linux-arm-musleabihf@4.53.3': + resolution: {integrity: sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.53.2': - resolution: {integrity: sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==} + '@rollup/rollup-linux-arm64-gnu@4.53.3': + resolution: {integrity: sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.53.2': - resolution: {integrity: sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==} + '@rollup/rollup-linux-arm64-musl@4.53.3': + resolution: {integrity: sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.53.2': - resolution: {integrity: sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==} + '@rollup/rollup-linux-loong64-gnu@4.53.3': + resolution: {integrity: sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.53.2': - resolution: {integrity: sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==} + '@rollup/rollup-linux-ppc64-gnu@4.53.3': + resolution: {integrity: sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.53.2': - resolution: {integrity: sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==} + '@rollup/rollup-linux-riscv64-gnu@4.53.3': + resolution: {integrity: sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.53.2': - resolution: {integrity: sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==} + '@rollup/rollup-linux-riscv64-musl@4.53.3': + resolution: {integrity: sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.53.2': - resolution: {integrity: sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==} + '@rollup/rollup-linux-s390x-gnu@4.53.3': + resolution: {integrity: sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.53.2': - resolution: {integrity: sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==} + '@rollup/rollup-linux-x64-gnu@4.53.3': + resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.53.2': - resolution: {integrity: sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==} + '@rollup/rollup-linux-x64-musl@4.53.3': + resolution: {integrity: sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==} cpu: [x64] os: [linux] - '@rollup/rollup-openharmony-arm64@4.53.2': - resolution: {integrity: sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==} + '@rollup/rollup-openharmony-arm64@4.53.3': + resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.53.2': - resolution: {integrity: sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==} + '@rollup/rollup-win32-arm64-msvc@4.53.3': + resolution: {integrity: sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.53.2': - resolution: {integrity: sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==} + '@rollup/rollup-win32-ia32-msvc@4.53.3': + resolution: {integrity: sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.53.2': - resolution: {integrity: sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==} + '@rollup/rollup-win32-x64-gnu@4.53.3': + resolution: {integrity: sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.53.2': - resolution: {integrity: sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==} + '@rollup/rollup-win32-x64-msvc@4.53.3': + resolution: {integrity: sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==} cpu: [x64] os: [win32] @@ -1117,8 +1117,8 @@ packages: resolution: {integrity: sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==} engines: {node: '>=0.10.0'} - caniuse-lite@1.0.30001755: - resolution: {integrity: sha512-44V+Jm6ctPj7R52Na4TLi3Zri4dWUljJd+RDm+j8LtNCc/ihLCT+X1TzoOAkRETEWqjuLnh9581Tl80FvK7jVA==} + caniuse-lite@1.0.30001756: + resolution: {integrity: sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==} caw@2.0.1: resolution: {integrity: sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==} @@ -1337,8 +1337,8 @@ packages: duplexer3@0.1.5: resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==} - electron-to-chromium@1.5.255: - resolution: {integrity: sha512-Z9oIp4HrFF/cZkDPMpz2XSuVpc1THDpT4dlmATFlJUIBVCy9Vap5/rIXsASP1CscBacBqhabwh8vLctqBwEerQ==} + electron-to-chromium@1.5.258: + resolution: {integrity: sha512-rHUggNV5jKQ0sSdWwlaRDkFc3/rRJIVnOSe9yR4zrR07m3ZxhP4N27Hlg8VeJGGYgFTxK5NqDmWI4DSH72vIJg==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2628,8 +2628,8 @@ packages: rollup: optional: true - rollup@4.53.2: - resolution: {integrity: sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==} + rollup@4.53.3: + resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2999,8 +2999,8 @@ packages: vite: optional: true - vite@7.2.2: - resolution: {integrity: sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==} + vite@7.2.4: + resolution: {integrity: sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -3598,18 +3598,18 @@ snapshots: dependencies: preact: 10.27.2 - '@preact/preset-vite@2.10.2(@babel/core@7.28.5)(preact@10.27.2)(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1))': + '@preact/preset-vite@2.10.2(@babel/core@7.28.5)(preact@10.27.2)(vite@7.2.4(@types/node@24.10.1)(terser@5.44.1))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.5) '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.5) - '@prefresh/vite': 2.4.11(preact@10.27.2)(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1)) + '@prefresh/vite': 2.4.11(preact@10.27.2)(vite@7.2.4(@types/node@24.10.1)(terser@5.44.1)) '@rollup/pluginutils': 4.2.1 babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.28.5) debug: 4.4.3 picocolors: 1.1.1 - vite: 7.2.2(@types/node@24.10.1)(terser@5.44.1) - vite-prerender-plugin: 0.5.12(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1)) + vite: 7.2.4(@types/node@24.10.1)(terser@5.44.1) + vite-prerender-plugin: 0.5.12(vite@7.2.4(@types/node@24.10.1)(terser@5.44.1)) transitivePeerDependencies: - preact - supports-color @@ -3622,7 +3622,7 @@ snapshots: '@prefresh/utils@1.2.1': {} - '@prefresh/vite@2.4.11(preact@10.27.2)(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1))': + '@prefresh/vite@2.4.11(preact@10.27.2)(vite@7.2.4(@types/node@24.10.1)(terser@5.44.1))': dependencies: '@babel/core': 7.28.5 '@prefresh/babel-plugin': 0.5.2 @@ -3630,7 +3630,7 @@ snapshots: '@prefresh/utils': 1.2.1 '@rollup/pluginutils': 4.2.1 preact: 10.27.2 - vite: 7.2.2(@types/node@24.10.1)(terser@5.44.1) + vite: 7.2.4(@types/node@24.10.1)(terser@5.44.1) transitivePeerDependencies: - supports-color @@ -3639,70 +3639,70 @@ snapshots: estree-walker: 2.0.2 picomatch: 2.3.1 - '@rollup/rollup-android-arm-eabi@4.53.2': + '@rollup/rollup-android-arm-eabi@4.53.3': optional: true - '@rollup/rollup-android-arm64@4.53.2': + '@rollup/rollup-android-arm64@4.53.3': optional: true - '@rollup/rollup-darwin-arm64@4.53.2': + '@rollup/rollup-darwin-arm64@4.53.3': optional: true - '@rollup/rollup-darwin-x64@4.53.2': + '@rollup/rollup-darwin-x64@4.53.3': optional: true - '@rollup/rollup-freebsd-arm64@4.53.2': + '@rollup/rollup-freebsd-arm64@4.53.3': optional: true - '@rollup/rollup-freebsd-x64@4.53.2': + '@rollup/rollup-freebsd-x64@4.53.3': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.53.2': + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.53.2': + '@rollup/rollup-linux-arm-musleabihf@4.53.3': optional: true - '@rollup/rollup-linux-arm64-gnu@4.53.2': + '@rollup/rollup-linux-arm64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-arm64-musl@4.53.2': + '@rollup/rollup-linux-arm64-musl@4.53.3': optional: true - '@rollup/rollup-linux-loong64-gnu@4.53.2': + '@rollup/rollup-linux-loong64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.53.2': + '@rollup/rollup-linux-ppc64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.53.2': + '@rollup/rollup-linux-riscv64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-riscv64-musl@4.53.2': + '@rollup/rollup-linux-riscv64-musl@4.53.3': optional: true - '@rollup/rollup-linux-s390x-gnu@4.53.2': + '@rollup/rollup-linux-s390x-gnu@4.53.3': optional: true - '@rollup/rollup-linux-x64-gnu@4.53.2': + '@rollup/rollup-linux-x64-gnu@4.53.3': optional: true - '@rollup/rollup-linux-x64-musl@4.53.2': + '@rollup/rollup-linux-x64-musl@4.53.3': optional: true - '@rollup/rollup-openharmony-arm64@4.53.2': + '@rollup/rollup-openharmony-arm64@4.53.3': optional: true - '@rollup/rollup-win32-arm64-msvc@4.53.2': + '@rollup/rollup-win32-arm64-msvc@4.53.3': optional: true - '@rollup/rollup-win32-ia32-msvc@4.53.2': + '@rollup/rollup-win32-ia32-msvc@4.53.3': optional: true - '@rollup/rollup-win32-x64-gnu@4.53.2': + '@rollup/rollup-win32-x64-gnu@4.53.3': optional: true - '@rollup/rollup-win32-x64-msvc@4.53.2': + '@rollup/rollup-win32-x64-msvc@4.53.3': optional: true '@sindresorhus/is@0.7.0': {} @@ -4021,8 +4021,8 @@ snapshots: browserslist@4.28.0: dependencies: baseline-browser-mapping: 2.8.29 - caniuse-lite: 1.0.30001755 - electron-to-chromium: 1.5.255 + caniuse-lite: 1.0.30001756 + electron-to-chromium: 1.5.258 node-releases: 2.0.27 update-browserslist-db: 1.1.4(browserslist@4.28.0) @@ -4080,7 +4080,7 @@ snapshots: camelcase@2.1.1: {} - caniuse-lite@1.0.30001755: {} + caniuse-lite@1.0.30001756: {} caw@2.0.1: dependencies: @@ -4367,7 +4367,7 @@ snapshots: duplexer3@0.1.5: {} - electron-to-chromium@1.5.255: {} + electron-to-chromium@1.5.258: {} emoji-regex@8.0.0: {} @@ -5621,41 +5621,41 @@ snapshots: dependencies: glob: 7.2.3 - rollup-plugin-visualizer@6.0.5(rollup@4.53.2): + rollup-plugin-visualizer@6.0.5(rollup@4.53.3): dependencies: open: 8.4.2 picomatch: 4.0.3 source-map: 0.7.6 yargs: 17.7.2 optionalDependencies: - rollup: 4.53.2 + rollup: 4.53.3 - rollup@4.53.2: + rollup@4.53.3: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.53.2 - '@rollup/rollup-android-arm64': 4.53.2 - '@rollup/rollup-darwin-arm64': 4.53.2 - '@rollup/rollup-darwin-x64': 4.53.2 - '@rollup/rollup-freebsd-arm64': 4.53.2 - '@rollup/rollup-freebsd-x64': 4.53.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.53.2 - '@rollup/rollup-linux-arm-musleabihf': 4.53.2 - '@rollup/rollup-linux-arm64-gnu': 4.53.2 - '@rollup/rollup-linux-arm64-musl': 4.53.2 - '@rollup/rollup-linux-loong64-gnu': 4.53.2 - '@rollup/rollup-linux-ppc64-gnu': 4.53.2 - '@rollup/rollup-linux-riscv64-gnu': 4.53.2 - '@rollup/rollup-linux-riscv64-musl': 4.53.2 - '@rollup/rollup-linux-s390x-gnu': 4.53.2 - '@rollup/rollup-linux-x64-gnu': 4.53.2 - '@rollup/rollup-linux-x64-musl': 4.53.2 - '@rollup/rollup-openharmony-arm64': 4.53.2 - '@rollup/rollup-win32-arm64-msvc': 4.53.2 - '@rollup/rollup-win32-ia32-msvc': 4.53.2 - '@rollup/rollup-win32-x64-gnu': 4.53.2 - '@rollup/rollup-win32-x64-msvc': 4.53.2 + '@rollup/rollup-android-arm-eabi': 4.53.3 + '@rollup/rollup-android-arm64': 4.53.3 + '@rollup/rollup-darwin-arm64': 4.53.3 + '@rollup/rollup-darwin-x64': 4.53.3 + '@rollup/rollup-freebsd-arm64': 4.53.3 + '@rollup/rollup-freebsd-x64': 4.53.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.53.3 + '@rollup/rollup-linux-arm-musleabihf': 4.53.3 + '@rollup/rollup-linux-arm64-gnu': 4.53.3 + '@rollup/rollup-linux-arm64-musl': 4.53.3 + '@rollup/rollup-linux-loong64-gnu': 4.53.3 + '@rollup/rollup-linux-ppc64-gnu': 4.53.3 + '@rollup/rollup-linux-riscv64-gnu': 4.53.3 + '@rollup/rollup-linux-riscv64-musl': 4.53.3 + '@rollup/rollup-linux-s390x-gnu': 4.53.3 + '@rollup/rollup-linux-x64-gnu': 4.53.3 + '@rollup/rollup-linux-x64-musl': 4.53.3 + '@rollup/rollup-openharmony-arm64': 4.53.3 + '@rollup/rollup-win32-arm64-msvc': 4.53.3 + '@rollup/rollup-win32-ia32-msvc': 4.53.3 + '@rollup/rollup-win32-x64-gnu': 4.53.3 + '@rollup/rollup-win32-x64-msvc': 4.53.3 fsevents: 2.3.3 run-parallel@1.2.0: @@ -5970,7 +5970,7 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - vite-plugin-imagemin@0.6.1(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1)): + vite-plugin-imagemin@0.6.1(vite@7.2.4(@types/node@24.10.1)(terser@5.44.1)): dependencies: '@types/imagemin': 7.0.1 '@types/imagemin-gifsicle': 7.0.4 @@ -5995,11 +5995,11 @@ snapshots: imagemin-webp: 6.1.0 jpegtran-bin: 6.0.1 pathe: 0.2.0 - vite: 7.2.2(@types/node@24.10.1)(terser@5.44.1) + vite: 7.2.4(@types/node@24.10.1)(terser@5.44.1) transitivePeerDependencies: - supports-color - vite-prerender-plugin@0.5.12(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1)): + vite-prerender-plugin@0.5.12(vite@7.2.4(@types/node@24.10.1)(terser@5.44.1)): dependencies: kolorist: 1.8.0 magic-string: 0.30.21 @@ -6007,26 +6007,26 @@ snapshots: simple-code-frame: 1.3.0 source-map: 0.7.6 stack-trace: 1.0.0-pre2 - vite: 7.2.2(@types/node@24.10.1)(terser@5.44.1) + vite: 7.2.4(@types/node@24.10.1)(terser@5.44.1) - vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.1)(terser@5.44.1)): + vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.2.4(@types/node@24.10.1)(terser@5.44.1)): dependencies: debug: 4.4.3 globrex: 0.1.2 tsconfck: 3.1.6(typescript@5.9.3) optionalDependencies: - vite: 7.2.2(@types/node@24.10.1)(terser@5.44.1) + vite: 7.2.4(@types/node@24.10.1)(terser@5.44.1) transitivePeerDependencies: - supports-color - typescript - vite@7.2.2(@types/node@24.10.1)(terser@5.44.1): + vite@7.2.4(@types/node@24.10.1)(terser@5.44.1): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.53.2 + rollup: 4.53.3 tinyglobby: 0.2.15 optionalDependencies: '@types/node': 24.10.1 From b9d96620a4383b0e430a5d82c9f48a69197b941b Mon Sep 17 00:00:00 2001 From: proddy Date: Thu, 20 Nov 2025 14:24:40 +0100 Subject: [PATCH 12/54] show restart needed after changing board profile. also no need to restart sensors. --- src/web/WebSettingsService.cpp | 26 +++++++++++++++++--------- src/web/WebSettingsService.h | 21 ++++++++++----------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/web/WebSettingsService.cpp b/src/web/WebSettingsService.cpp index 609a44308..b4fd1f6b7 100644 --- a/src/web/WebSettingsService.cpp +++ b/src/web/WebSettingsService.cpp @@ -196,24 +196,26 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { System::load_board_profile(data, settings.board_profile.c_str()); } + int prev; + reset_flags(); + + // check if board profile has changed if (org_board_profile != settings.board_profile) { if (org_board_profile.isEmpty()) { EMSESP::logger().info("Setting board profile to %s", settings.board_profile.c_str()); } else { EMSESP::logger().info("Setting board profile to %s (was %s)", settings.board_profile.c_str(), org_board_profile.c_str()); } + add_flags(ChangeFlags::RESTART); } - 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); + check_flag(prev, settings.dallas_gpio, ChangeFlags::TEMPERATURE_SENSOR); prev = settings.rx_gpio; settings.rx_gpio = data[2]; check_flag(prev, settings.rx_gpio, ChangeFlags::RESTART); @@ -269,7 +271,7 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { // temperature sensor prev = settings.dallas_parasite; settings.dallas_parasite = root["dallas_parasite"] | EMSESP_DEFAULT_DALLAS_PARASITE; - check_flag(prev, settings.dallas_parasite, ChangeFlags::SENSOR); + check_flag(prev, settings.dallas_parasite, ChangeFlags::TEMPERATURE_SENSOR); // shower prev = settings.shower_timer; @@ -296,7 +298,7 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { // adc prev = settings.analog_enabled; settings.analog_enabled = root["analog_enabled"] | EMSESP_DEFAULT_ANALOG_ENABLED; - check_flag(prev, settings.analog_enabled, ChangeFlags::ADC); + check_flag(prev, settings.analog_enabled, ChangeFlags::ANALOG_SENSOR); // // these need system restarts first before settings are activated... @@ -400,11 +402,17 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) { // this is called after any of the settings have been persisted to the filesystem // either via the Web UI or via the Console void WebSettingsService::onUpdate() { + // skip if we're restarting anyway + + if (WebSettings::has_flags(WebSettings::ChangeFlags::RESTART)) { + return; + } + if (WebSettings::has_flags(WebSettings::ChangeFlags::SHOWER)) { EMSESP::shower_.start(); } - if (WebSettings::has_flags(WebSettings::ChangeFlags::SENSOR)) { + if (WebSettings::has_flags(WebSettings::ChangeFlags::TEMPERATURE_SENSOR)) { EMSESP::temperaturesensor_.start(); } @@ -416,7 +424,7 @@ void WebSettingsService::onUpdate() { EMSESP::system_.syslog_init(); // re-start (or stop) } - if (WebSettings::has_flags(WebSettings::ChangeFlags::ADC)) { + if (WebSettings::has_flags(WebSettings::ChangeFlags::ANALOG_SENSOR)) { EMSESP::analogsensor_.start(); } @@ -453,7 +461,7 @@ void WebSettingsService::board_profile(AsyncWebServerRequest * request) { auto * response = new AsyncJsonResponse(false); JsonObject root = response->getRoot(); - std::vector data; // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode + std::vector data; // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode, led_type (void)System::load_board_profile(data, board_profile); root["board_profile"] = board_profile; root["led_gpio"] = data[0]; diff --git a/src/web/WebSettingsService.h b/src/web/WebSettingsService.h index ba1e9abc4..addac0149 100644 --- a/src/web/WebSettingsService.h +++ b/src/web/WebSettingsService.h @@ -90,17 +90,16 @@ class WebSettings { enum ChangeFlags : uint8_t { - NONE = 0, - UART = (1 << 0), // 1 - SYSLOG = (1 << 1), // 2 - ADC = (1 << 2), // 4 - analog - SENSOR = (1 << 3), // 8 - SHOWER = (1 << 4), // 16 - LED = (1 << 5), // 32 - BUTTON = (1 << 6), // 64 - MQTT = (1 << 7), // 128 - RESTART = 0xFF - + NONE = 0, + UART = (1 << 0), // 1 - uart + SYSLOG = (1 << 1), // 2 - syslog + ANALOG_SENSOR = (1 << 2), // 4 - analog + TEMPERATURE_SENSOR = (1 << 3), // 8 - dallas sensor + SHOWER = (1 << 4), // 16 - shower timer and alert + LED = (1 << 5), // 32 - led + BUTTON = (1 << 6), // 64 - button + MQTT = (1 << 7), // 128 - mqtt + RESTART = 0xFF // 255 - restart request (all changes) }; static void check_flag(int prev_v, int new_v, uint8_t flag) { From fbfacc5ed521a407efac51cd6b014b3b0f79c931 Mon Sep 17 00:00:00 2001 From: proddy Date: Thu, 20 Nov 2025 14:24:57 +0100 Subject: [PATCH 13/54] 3.7.3-dev.31 --- src/emsesp_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emsesp_version.h b/src/emsesp_version.h index 06a6494a1..4d6bf5788 100644 --- a/src/emsesp_version.h +++ b/src/emsesp_version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.7.3-dev.30" +#define EMSESP_APP_VERSION "3.7.3-dev.31" From 84225219751bfbd4655cf89271b041477b842373 Mon Sep 17 00:00:00 2001 From: proddy Date: Thu, 20 Nov 2025 14:25:25 +0100 Subject: [PATCH 14/54] formatting of error message box to align buttons --- interface/src/app/main/Customizations.tsx | 3 ++- interface/src/app/main/Dashboard.tsx | 2 +- interface/src/app/settings/ApplicationSettings.tsx | 3 ++- interface/src/app/settings/network/NetworkSettings.tsx | 3 ++- interface/src/app/settings/network/WiFiNetworkSelector.tsx | 2 +- interface/src/app/status/SystemMonitor.tsx | 4 ++-- interface/src/components/loading/FormLoader.tsx | 2 +- 7 files changed, 11 insertions(+), 8 deletions(-) diff --git a/interface/src/app/main/Customizations.tsx b/interface/src/app/main/Customizations.tsx index bc1743b5f..b5ea9823c 100644 --- a/interface/src/app/main/Customizations.tsx +++ b/interface/src/app/main/Customizations.tsx @@ -726,8 +726,9 @@ const Customizations = () => { {devices && renderDeviceList()} {selectedDevice !== -1 && !rename && renderDeviceData()} {restartNeeded ? ( - +