From 87b95f798ae52fe00081b4468c8a24fe412130a4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 26 Mar 2025 16:43:13 +0100 Subject: [PATCH] Extend command `GPIO` with different display options and allowing updating of module GPIO's in one go --- CHANGELOG.md | 1 + RELEASENOTES.md | 3 +- tasmota/tasmota_support/support_command.ino | 127 +++++++++++++++----- 3 files changed, 99 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7503965f3..e8e071b1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. ## [14.5.0.3] ### Added +- Extend command `GPIO` with different display options and allowing updating of module GPIO's in one go ### Breaking Changed diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0ce748d80..6d5a83564 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -116,9 +116,10 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm ## Changelog v14.5.0.3 ### Added -- Telnet server using command `Telnet <0|1|port>[,]` +- Extend command `GPIO` with different display options and allowing updating of module GPIO's in one go - Support Vango Technologies V924x ultralow power, single-phase, power measurement [#23127](https://github.com/arendst/Tasmota/issues/23127) - Support for HLK-LD2402 24GHz smart wave motion sensor [#23133](https://github.com/arendst/Tasmota/issues/23133) +- Telnet server using command `Telnet <0|1|port>[,]` - Allow acl in mqtt when client certificate is in use with `#define USE_MQTT_CLIENT_CERT` [#22998](https://github.com/arendst/Tasmota/issues/22998) - Berry experimental driver for AXP2101 for M5Core2v1.1 [#23039](https://github.com/arendst/Tasmota/issues/23039) - Berry `tasmota.when_network_up()` and simplified Matter using it [#23057](https://github.com/arendst/Tasmota/issues/23057) diff --git a/tasmota/tasmota_support/support_command.ino b/tasmota/tasmota_support/support_command.ino index 2f759b12e..1c28dc2f6 100644 --- a/tasmota/tasmota_support/support_command.ino +++ b/tasmota/tasmota_support/support_command.ino @@ -1823,46 +1823,86 @@ void CmndModules(void) ResponseJsonEndEnd(); } +bool GpioSensorType(uint32_t gpio, uint32_t sensor_type) { + myio template_gp; + TemplateGpios(&template_gp); + if (ValidGPIO(gpio, template_gp.io[gpio])) { + for (uint32_t i = 0; i < nitems(kGpioNiceList); i++) { + uint32_t midx = pgm_read_word(&kGpioNiceList[i]); + uint32_t max_midx = ((midx & 0x001F) > 0) ? midx : midx +1; + if ((sensor_type >= (midx & 0xFFE0)) && (sensor_type < max_midx)) { + for (uint32_t j = 0; j < nitems(Settings->my_gp.io); j++) { + if (ValidGPIO(j, template_gp.io[j]) && (Settings->my_gp.io[j] == XdrvMailbox.payload)) { + Settings->my_gp.io[j] = GPIO_NONE; + } + } + Settings->my_gp.io[gpio] = sensor_type; + return true; + } + } + } + return false; +} + void CmndGpio(void) { - // Gpio - Show all GPIOs available in module configuration - // Gpio 1 - Show all GPIOs in use in module configuration + // Gpio - Show all GPIOs available in module like {"GPIO0":{"None":0},"GPIO1":{"None":0},"GPIO2":{"Relay1":224},... + // Gpio 1 - Show all GPIOs available in module like {"GPIO":[[0,0,"None"],[1,0,"None"],[2,224,"Relay1"],... + // Gpio 2 - Show all GPIOs available in module like {"GPIO":[[0,0],[1,0],[2,224],... + // Gpio 3 - Show all GPIOs available in module like {"GPIO":[0,0,224,... + // Gpio 10 - Show configured GPIOs in module like {"GPIO2":{"Relay1":224},... + // Gpio 11 - Show configured GPIOs in module like {"GPIO":[[2,224,"Relay1"],... + // Gpio 12 - Show configured GPIOs in module like {"GPIO":[[2,224],... // Gpio 255 - Show all GPIOs available in template configuration - // Gpio2 224 - Set GPIO2 as Relay1 + // Gpio2 224 - Set a single GPIO. GPIO2 as Relay1 + // Gpio {"GPIO":[32,0,448,0,224,225,0,0,0,1792,1824,0,0,0]} - Set all module GPIOs if (XdrvMailbox.index < nitems(Settings->my_gp.io)) { myio template_gp; TemplateGpios(&template_gp); - if (ValidGPIO(XdrvMailbox.index, template_gp.io[XdrvMailbox.index]) && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < AGPIO(GPIO_SENSOR_END))) { - bool present = false; - for (uint32_t i = 0; i < nitems(kGpioNiceList); i++) { - uint32_t midx = pgm_read_word(&kGpioNiceList[i]); - uint32_t max_midx = ((midx & 0x001F) > 0) ? midx : midx +1; - if ((XdrvMailbox.payload >= (midx & 0xFFE0)) && (XdrvMailbox.payload < max_midx)) { - present = true; - break; - } - } - if (present) { - for (uint32_t i = 0; i < nitems(Settings->my_gp.io); i++) { - if (ValidGPIO(i, template_gp.io[i]) && (Settings->my_gp.io[i] == XdrvMailbox.payload)) { - Settings->my_gp.io[i] = GPIO_NONE; - } - } - Settings->my_gp.io[XdrvMailbox.index] = XdrvMailbox.payload; + if (strchr(XdrvMailbox.data, '{') == nullptr) { // If no JSON it must be parameter + // Gpio2 224 + if (XdrvMailbox.usridx && GpioSensorType(XdrvMailbox.index, XdrvMailbox.payload)) { TasmotaGlobal.restart_flag = 2; } + } else { + // Gpio {"GPIO":[32,0,448,0,224,225,0,0,0,1792,1824,0,0,0]} + uint32_t arr_index = 0; + JsonParser parser((char*) XdrvMailbox.data); + JsonParserObject root = parser.getRootObject(); + if (root) { + JsonParserArray arr = root[PSTR(D_JSON_GPIO)]; + if (arr) { + for (uint32_t gpio = 0; gpio < nitems(Settings->my_gp.io); gpio++) { + if (!ValidGPIO(gpio, template_gp.io[gpio])) { continue; } + JsonParserToken val = arr[arr_index++]; + if (!val) { break; } + uint16_t sensor_type = val.getUInt(); + if (GpioSensorType(gpio, sensor_type)) { + TasmotaGlobal.restart_flag = 2; + XdrvMailbox.payload = 3; // Show result as {"GPIO":[32,0,448,0,224,225,0,0,0,1792,1824,0,0,0]} + } + } + } + } } + bool jsflg = false; + bool jsflg1 = false; bool jsflg2 = false; + bool show_sensor_type_only = false; + if ((XdrvMailbox.payload >= 10) && (XdrvMailbox.payload <= 12)) { + XdrvMailbox.payload -= 10; + show_sensor_type_only = true; + } for (uint32_t i = 0; i < nitems(Settings->my_gp.io); i++) { if (ValidGPIO(i, template_gp.io[i]) || ((255 == XdrvMailbox.payload) && !FlashPin(i))) { uint32_t sensor_type = Settings->my_gp.io[i]; if (!ValidGPIO(i, template_gp.io[i])) { sensor_type = template_gp.io[i]; - if (AGPIO(GPIO_USER) == sensor_type) { // A user GPIO equals a not connected (=GPIO_NONE) GPIO here + if (AGPIO(GPIO_USER) == sensor_type) { // A user GPIO equals a not connected (=GPIO_NONE) GPIO here sensor_type = GPIO_NONE; } } - if ((1 == XdrvMailbox.payload) && (GPIO_NONE == sensor_type)) { + if (show_sensor_type_only && (GPIO_NONE == sensor_type)) { continue; } char sindex[4] = { 0 }; @@ -1880,18 +1920,42 @@ void CmndGpio(void) { sensor_name_idx = sensor_name_idx - GPIO_FIX_START -1; sensor_names = kSensorNamesFixed; } - if (!jsflg) { - Response_P(PSTR("{")); + if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 3)) { + if (!jsflg1) { + jsflg1 = true; + Response_P(PSTR("{\"" D_CMND_GPIO "\":[")); + } else { + ResponseAppend_P(PSTR(",")); + } + switch (XdrvMailbox.payload) { + case 1: + char stemp1[TOPSZ]; + ResponseAppend_P(PSTR("[%d,%d,\"%s%s\"]"), i, sensor_type, GetTextIndexed(stemp1, sizeof(stemp1), sensor_name_idx, sensor_names), sindex); + break; + case 2: + ResponseAppend_P(PSTR("[%d,%d]"), i, sensor_type); + break; + case 3: + ResponseAppend_P(PSTR("%d"), sensor_type); + break; + } } else { - ResponseAppend_P(PSTR(",")); + if (!jsflg) { + jsflg = true; + Response_P(PSTR("{")); + } else { + ResponseAppend_P(PSTR(",")); + } + char stemp1[TOPSZ]; + ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":{\"%s%s\":%d}"), i, GetTextIndexed(stemp1, sizeof(stemp1), sensor_name_idx, sensor_names), sindex, sensor_type); } - jsflg = true; - char stemp1[TOPSZ]; - ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":{\"%s%s\":%d}"), i, GetTextIndexed(stemp1, sizeof(stemp1), sensor_name_idx, sensor_names), sindex, sensor_type); jsflg2 = true; } } - if (jsflg) { + if (jsflg1) { + ResponseAppend_P(PSTR("]}")); + } + else if (jsflg) { ResponseJsonEnd(); } else { if (!jsflg2) { @@ -1950,8 +2014,9 @@ void ShowGpios(const uint16_t *NiceList, uint32_t size, uint32_t offset, uint32_ } } -void CmndGpios(void) -{ +void CmndGpios(void) { + // Gpios - Show all compiled supported GPIOs + // Gpio 255 - Show all possible GPIOs uint32_t lines = 1; if (XdrvMailbox.payload == 255) { // DumpConvertTable();