From 6aca98673dba7ab7a03905497f92ff017a7048d7 Mon Sep 17 00:00:00 2001 From: gemu Date: Mon, 26 May 2025 08:05:41 +0200 Subject: [PATCH] fix upd[x] chg[x] (#23477) --- .../tasmota_xdrv_driver/xdrv_10_scripter.ino | 514 ++++++++++++++---- 1 file changed, 409 insertions(+), 105 deletions(-) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino index 6008ec3a5..12a7766f7 100755 --- a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino @@ -42,14 +42,12 @@ keywords if then else endif, or, and are better readable for beginners (others m #define XDRV_10 10 - #ifndef TS_FLOAT #define TS_FLOAT float #endif // float = 4, double = 8 bytes - -const uint8_t SCRIPT_VERS[2] = {5, 4}; +const uint8_t SCRIPT_VERS[2] = {5, 5}; #define SCRIPT_DEBUG 0 @@ -78,7 +76,7 @@ const uint8_t SCRIPT_VERS[2] = {5, 4}; #endif #ifndef SCRIPT_MAXSSIZE -#define SCRIPT_MAXSSIZE 48 +#define SCRIPT_MAXSSIZE 255 #endif //#define SCRIPT_MAX_SBSIZE SCRIPT_MAXSSIZE @@ -191,6 +189,8 @@ char *Get_esc_char(char *cp, char *esc_chr); #ifdef ESP32 #include "driver/i2s_std.h" #include "driver/i2s_pdm.h" +#include "driver/rtc_io.h" +#include "esp_sleep.h" #endif @@ -256,6 +256,7 @@ char *Get_esc_char(char *cp, char *esc_chr); #define USE_SCRIPT_FATFS_EXT #endif + #ifdef USE_SCRIPT_TIMER #include Ticker Script_ticker1; @@ -285,6 +286,13 @@ void Script_ticker4_end(void) { #define HARDWARE_FALLBACK 2 #endif + +#ifdef USE_SCRIPT_GLOBVARS +#ifndef SCRIPT_UDP_BUFFER_SIZE +#define SCRIPT_UDP_BUFFER_SIZE 128 +#endif +#define SCRIPT_UDP_PORT 1999 + // EEPROM MACROS // i2c eeprom #define EEP_WRITE(A,B,C) eeprom_writeBytes(A, B, (uint8_t*)C); @@ -300,9 +308,6 @@ void Script_ticker4_end(void) { #endif #endif -//#if defined(USE_SML_M) && defined (USE_SML_SCRIPT_CMD) -//extern uint8_t sml_options; -//#endif #if defined(EEP_SCRIPT_SIZE) && !defined(ESP32) @@ -311,6 +316,7 @@ void Script_ticker4_end(void) { uint32_t eeprom_block; + // these support only one 4 k block below EEPROM (eeprom @0x402FB000) this steals 4k of application area uint32_t alt_eeprom_init(uint32_t size) { //EEPROM.begin(size); @@ -374,7 +380,7 @@ extern Renderer *renderer; #endif enum {OPER_EQU=1,OPER_PLS,OPER_MIN,OPER_MUL,OPER_DIV,OPER_PLSEQU,OPER_MINEQU,OPER_MULEQU,OPER_DIVEQU,OPER_EQUEQU,OPER_NOTEQU,OPER_GRTEQU,OPER_LOWEQU,OPER_GRT,OPER_LOW,OPER_PERC,OPER_XOR,OPER_AND,OPER_OR,OPER_ANDEQU,OPER_OREQU,OPER_XOREQU,OPER_PERCEQU,OPER_SHLEQU,OPER_SHREQU,OPER_SHL,OPER_SHR}; -enum {SCRIPT_LOGLEVEL=1,SCRIPT_TELEPERIOD,SCRIPT_EVENT_HANDLED,SML_JSON_ENABLE,SCRIPT_EPOFFS,SCRIPT_CBSIZE}; +enum {SCRIPT_LOGLEVEL=1,SCRIPT_TELEPERIOD,SCRIPT_EVENT_HANDLED,SML_JSON_ENABLE,SCRIPT_EPOFFS,SCRIPT_CBSIZE,SCRIPT_UDP_PBS,SCRIPT_UDP_MOD}; #ifdef USE_UFILESYS @@ -489,7 +495,7 @@ typedef union { uint8_t nutu6 : 1; uint8_t nutu5 : 1; uint8_t nutu4 : 1; - uint8_t nutu3 : 1; + uint8_t udp_binary_payload : 1; uint8_t udp_connected : 1; uint8_t udp_used : 1; }; @@ -503,7 +509,7 @@ typedef union { uint8_t nutu6 : 1; uint8_t nutu5 : 1; uint8_t nutu4 : 1; - uint8_t nutu3 : 1; + uint8_t ignore_line : 1; bool fsys : 1; bool eeprom : 1; }; @@ -527,9 +533,9 @@ struct SCRIPT_SPI { }; #endif - #define NUM_RES 0xfe #define STR_RES 0xfd +#define NUM_ARRAY_RES 0xfc #define VAR_NV 0xff #define NTYPE 0 @@ -635,6 +641,8 @@ typedef struct { IPAddress last_udp_ip; WiFiUDP Script_PortUdp; IPAddress script_udp_remote_ip; + char *packet_buffer; + uint16_t pb_size = SCRIPT_UDP_BUFFER_SIZE; #endif // USE_SCRIPT_GLOBVARS char web_mode; char *glob_script = 0; @@ -994,6 +1002,17 @@ char *script; script = glob_script_mem.script_ram; if (!*script) return -999; + glob_script_mem.max_ssize = SCRIPT_SVARSIZE; + + { char *lp = script + 2; + SCRIPT_SKIP_SPACES + if (isdigit(*lp)) { + uint8_t ssize = atoi(lp) + 1; + if (ssize < 10 || ssize > SCRIPT_MAXSSIZE) ssize = SCRIPT_MAXSSIZE; + glob_script_mem.max_ssize = ssize; + } + } + uint32_t xvars = Script_Find_Vars(script + 1); uint16_t maxnvars = xvars & 0xffff; if (maxnvars < 1) { @@ -1034,7 +1053,9 @@ char *script; //char strings[MAXSVARS*SCRIPT_MAXSSIZE]; //char *strings_p = strings; - char *strings_op = (char*)calloc(maxsvars * SCRIPT_MAXSSIZE, 1); + //char *strings_op = (char*)calloc(maxsvars * SCRIPT_MAXSSIZE, 1); + char *strings_op = (char*)calloc(maxsvars * glob_script_mem.max_ssize, 1); + char *strings_p = strings_op; if (!strings_op) { free(imemptr); @@ -1075,7 +1096,6 @@ char *script; uint8_t numflt = 0; uint16_t count; - glob_script_mem.max_ssize = SCRIPT_SVARSIZE; glob_script_mem.scriptptr = 0; char init = 0; @@ -1266,13 +1286,13 @@ char *script; } } else { if (!strncmp(lp, ">D", 2)) { - lp += 2; + /* lp += 2; SCRIPT_SKIP_SPACES if (isdigit(*lp)) { uint8_t ssize = atoi(lp) + 1; if (ssize < 10 || ssize > SCRIPT_MAXSSIZE) ssize = SCRIPT_MAXSSIZE; glob_script_mem.max_ssize = ssize; - } + }*/ init = 1; } } @@ -1522,10 +1542,6 @@ int32_t udp_call(char *url, uint32_t port, char *sbuf) { return 0; } -#ifdef USE_SCRIPT_GLOBVARS -#define SCRIPT_UDP_BUFFER_SIZE 128 -#define SCRIPT_UDP_PORT 1999 - //#define SCRIPT_DEBUG_UDP void Restart_globvars(void) { @@ -1540,6 +1556,11 @@ void Script_Stop_UDP(void) { glob_script_mem.Script_PortUdp.stop(); glob_script_mem.udp_flags.udp_connected = 0; } + if (glob_script_mem.packet_buffer) { + free(glob_script_mem.packet_buffer); + glob_script_mem.packet_buffer = 0; + } + } void Script_Init_UDP() { @@ -1547,6 +1568,9 @@ void Script_Init_UDP() { if (!glob_script_mem.udp_flags.udp_used) return; if (glob_script_mem.udp_flags.udp_connected) return; + glob_script_mem.packet_buffer = (char*)malloc(glob_script_mem.pb_size); + + //if (glob_script_mem.Script_PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), SCRIPT_UDP_PORT)) { #ifdef ESP8266 if (glob_script_mem.Script_PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), SCRIPT_UDP_PORT)) { @@ -1567,37 +1591,49 @@ void Script_Init_UDP() { } } - - void Script_PollUdp(void) { if (TasmotaGlobal.global_state.network_down) return; if (!glob_script_mem.udp_flags.udp_used) return; if (glob_script_mem.udp_flags.udp_connected ) { uint32_t timeout = millis(); - while (glob_script_mem.Script_PortUdp.parsePacket()) { + while (1) { + uint16_t plen = glob_script_mem.Script_PortUdp.parsePacket(); + if (!plen || plen > glob_script_mem.pb_size) { + glob_script_mem.Script_PortUdp.flush(); + break; + } + // not more then 500 ms if (millis() - timeout > 500) { break;} - char packet_buffer[SCRIPT_UDP_BUFFER_SIZE]; - int32_t len = glob_script_mem.Script_PortUdp.read(packet_buffer, SCRIPT_UDP_BUFFER_SIZE - 1); + char *packet_buffer = glob_script_mem.packet_buffer; + int32_t len = glob_script_mem.Script_PortUdp.read(packet_buffer, glob_script_mem.pb_size); packet_buffer[len] = 0; glob_script_mem.script_udp_remote_ip = glob_script_mem.Script_PortUdp.remoteIP(); #ifdef SCRIPT_DEBUG_UDP //AddLog(LOG_LEVEL_DEBUG, PSTR("UDP: Packet %s - %d - %s"), packet_buffer, len, script_udp_remote_ip.toString().c_str()); - AddLog(LOG_LEVEL_DEBUG, PSTR("UDP: Packet %s - %d - %_I"), packet_buffer, len, (uint32_t)glob_script_mem.script_udp_remote_ip); + AddLog(LOG_LEVEL_DEBUG, PSTR("UDP: received Packet %s - %d - %_I"), packet_buffer, len, (uint32_t)glob_script_mem.script_udp_remote_ip); #endif char *lp = packet_buffer; if (!strncmp(lp,"=>", 2)) { lp += 2; - char *cp=strchr(lp, '='); - if (cp) { - char vnam[32]; - for (uint32_t count = 0; count20) pin = 1; + if (pin < 1 || pin > 20) pin = 1; +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + if (pin < 0 || pin > 5) pin = 0; #else - if (pin<32 || pin>39) pin = 32; + if (pin < 32 || pin > 39) pin = 32; #endif } lp++; @@ -3198,9 +3316,30 @@ chknext: TS_FLOAT *fpd; lp = get_array_by_name(lp, &fpd, &alend, 0); SCRIPT_SKIP_SPACES - uint16_t alens; + uint16_t alens = 0; TS_FLOAT *fps; char *slp = lp; +#if (defined(USE_SML_M) || defined(USE_BINPLUGINS)) && defined(USE_SML_SCRIPT_CMD) + if (!strncmp_XP(lp, XPSTR("sml"), 3)) { + lp += 3; + // source is sml array + SML_TABLE *smlp = get_sml_table(); + if (smlp) { + alens = smlp->SML_GetVal(0); + if (alens < alend) { + alend = alens; + } + for (uint32_t cnt = 0; cnt < alend; cnt++ ) { + fpd[cnt] = smlp->SML_GetVal(cnt + 1); + } + fvar = alens; + goto nfuncexit; + } else { + fvar = -1; + goto nfuncexit; + } + } +#endif lp = get_array_by_name(lp, &fps, &alens, 0); if (lp == 0 || fps == 0) { lp = slp; @@ -3341,9 +3480,11 @@ chknext: uint8_t vtype; lp = isvar(lp + 4, &vtype, &ind, 0, 0, gv); if (!ind.bits.constant) { - uint16_t index = glob_script_mem.type[ind.index].index; - fvar = glob_script_mem.fvars[index] != glob_script_mem.s_fvars[index]; - glob_script_mem.s_fvars[index] = glob_script_mem.fvars[index]; + if (!glob_script_mem.FLAGS.ignore_line) { + uint16_t index = glob_script_mem.type[ind.index].index; + fvar = glob_script_mem.fvars[index] != glob_script_mem.s_fvars[index]; + glob_script_mem.s_fvars[index] = glob_script_mem.fvars[index]; + } } else { fvar = 0; } @@ -3425,6 +3566,7 @@ chknext: tind->index = SCRIPT_CBSIZE; goto exit_settable; } + #ifdef USE_W8960 extern void W8960_SetGain(uint8_t sel, uint16_t value); @@ -3511,6 +3653,70 @@ extern void W8960_SetGain(uint8_t sel, uint16_t value); } goto nfuncexit; } +#ifdef ESP32 + if (!strncmp_XP(lp, XPSTR("ds("), 3)) { + lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, gv); + if (fvar == -1) { + fvar = esp_sleep_get_wakeup_cause(); + } else { + if (fvar > 0) { + esp_sleep_enable_timer_wakeup(fvar * 1000000); + } + SCRIPT_SKIP_SPACES + if (*lp != ')') { + lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv); + if (fvar != -1) { + gpio_num_t gpio_num = (gpio_num_t)fvar; + lp = GetNumericArgument(lp, OPER_EQU, &fvar, gv); +#if SOC_PM_SUPPORT_EXT1_WAKEUP + if (fvar == 0) { + esp_sleep_enable_ext1_wakeup_io(1 << gpio_num, ESP_EXT1_WAKEUP_ANY_HIGH); +#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED + rtc_gpio_pullup_dis(gpio_num); + rtc_gpio_pulldown_en(gpio_num); +#else +_Pragma("GCC warning \"'rtc io' not supported\"") +#endif + } else { +#if CONFIG_IDF_TARGET_ESP32 + esp_sleep_enable_ext1_wakeup_io(1 << gpio_num, ESP_EXT1_WAKEUP_ALL_LOW); +#else + esp_sleep_enable_ext1_wakeup_io(1 << gpio_num, ESP_EXT1_WAKEUP_ANY_LOW); +#endif +#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED + rtc_gpio_pullup_en(gpio_num); + rtc_gpio_pulldown_dis(gpio_num); +#else +_Pragma("GCC warning \"'rtc io' not supported\"") +#endif + } +#else +_Pragma("GCC warning \"'EXT 1 wakeup' not supported using gpio mode\"") + + const gpio_config_t config = { + .pin_bit_mask = BIT(gpio_num), + .mode = GPIO_MODE_INPUT, + .pull_up_en = (gpio_pullup_t)!fvar, + .pull_down_en = (gpio_pulldown_t)fvar + + }; + gpio_config(&config); + + if (fvar == 0) { + esp_deep_sleep_enable_gpio_wakeup(1 << gpio_num, ESP_GPIO_WAKEUP_GPIO_LOW); + } else { + esp_deep_sleep_enable_gpio_wakeup(1 << gpio_num, ESP_GPIO_WAKEUP_GPIO_HIGH); + } + +#endif // SOC_PM_SUPPORT_EXT1_WAKEUP + } + } + SettingsSaveAll(); + esp_deep_sleep_start(); + } + goto nfuncexit; + } +#endif // ESP32 break; case 'e': if (!strncmp_XP(vname, XPSTR("epoch"), 5)) { @@ -3930,7 +4136,7 @@ extern void W8960_SetGain(uint8_t sel, uint16_t value); if (!strncmp_XP(lp, XPSTR("fmt("), 4)) { lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv); if (!fvar) { - LittleFS.format(); + fvar = LittleFS.format(); } else { //SD.format(); } @@ -4399,6 +4605,48 @@ extern void W8960_SetGain(uint8_t sel, uint16_t value); } goto nfuncexit; } +#ifdef USE_SCRIPT_GLOBVARS + if (!strncmp_XP(lp, XPSTR("gvrsa("), 6)) { + TS_FLOAT *fpd = 0; + uint16_t alend; + uint16_t ipos; + lp += 6; + SCRIPT_SKIP_SPACES + char vname[32]; + char *cp = lp; + char *vnp = vname; + while (*cp) { + if (*cp == ')') { + break; + } + *vnp++ = *cp++; + } + *vnp = 0; + lp = get_array_by_name(lp, &fpd, &alend, &ipos); + if (fpd) { + uint8_t sv = glob_script_mem.udp_flags.udp_binary_payload; + glob_script_mem.udp_flags.udp_binary_payload = 1; + script_udp_sendvar(vname, fpd, 0, alend); + glob_script_mem.udp_flags.udp_binary_payload = sv; + fvar = ipos; + } else { + fvar = -1; + } + goto nfuncexit; + } + + if (!strncmp_XP(lp, XPSTR("gvrbs"), 5)) { + fvar = glob_script_mem.pb_size; + tind->index = SCRIPT_UDP_PBS; + goto exit_settable; + } + + if (!strncmp_XP(lp, XPSTR("gvrm"), 4)) { + fvar = glob_script_mem.udp_flags.udp_binary_payload; + tind->index = SCRIPT_UDP_MOD; + goto exit_settable; + } +#endif // USE_SCRIPT_GLOBVARS break; case 'h': if (!strncmp_XP(vname, XPSTR("hours"), 5)) { @@ -6315,24 +6563,26 @@ void tmod_directModeOutput(uint32_t pin); goto exit; } if (!strncmp_XP(lp, XPSTR("upd["), 4)) { - // var was updated + // var was updated ? struct T_INDEX ind; uint8_t vtype; - isvar(lp + 4, &vtype, &ind, 0, 0, gv); + lp = isvar(lp + 4, &vtype, &ind, 0, 0, gv); if (!ind.bits.constant) { if (!ind.bits.changed) { fvar = 0; - len++; - goto exit; + goto nfuncexit; } else { - glob_script_mem.type[ind.index].bits.changed = 0; + if (!glob_script_mem.FLAGS.ignore_line) { + glob_script_mem.type[ind.index].bits.changed = 0; + } fvar = 1; - len++; - goto exit; + goto nfuncexit; } } goto notfound; } + +#ifdef USE_SCRIPT_GLOBVARS if (!strncmp_XP(lp, XPSTR("udp("), 4)) { char url[SCRIPT_MAX_SBSIZE]; lp = GetStringArgument(lp + 4, OPER_EQU, url, 0); @@ -6343,6 +6593,7 @@ void tmod_directModeOutput(uint32_t pin); fvar = udp_call(url, port, payload); goto nfuncexit; } +#endif break; case 'w': @@ -7357,7 +7608,7 @@ int32_t UpdVar(char *vname, float *fvar, uint32_t mode) { glob_script_mem.type[ind.index].bits.changed = 1; #ifdef USE_SCRIPT_GLOBVARS if (glob_script_mem.type[ind.index].bits.global) { - script_udp_sendvar(vname, &res, 0); + script_udp_sendvar(vname, &res, 0, 0); } #endif //USE_SCRIPT_GLOBVARS return 0; @@ -7895,6 +8146,7 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) { if_state[ifstck] = 0; if_result[ifstck] = 0; if_exe[ifstck] = 1; + glob_script_mem.FLAGS.ignore_line = 0; char cmpstr[SCRIPT_MAX_SBSIZE]; TS_FLOAT *dfvar; @@ -7954,6 +8206,8 @@ startline: //if (if_state[s_ifstck]==3 && if_result[s_ifstck]) goto next_line; //if (if_state[s_ifstck]==2 && !if_result[s_ifstck]) goto next_line; + glob_script_mem.FLAGS.ignore_line = 0; + if (!strncmp(lp, "if", 2)) { lp += 2; if (ifstck < IF_NEST - 1) ifstck++; @@ -7962,6 +8216,24 @@ startline: if (ifstck == 1) if_exe[ifstck] = 1; else if_exe[ifstck] = if_exe[ifstck - 1]; and_or = 0; + if (if_result[ifstck - 1] == 0) { + // not enabled + glob_script_mem.FLAGS.ignore_line = 1; + /* + while (*lp) { + if (*lp == SCRIPT_EOL) { + break; + } + if (*lp == '{') { + // then + if_state[ifstck] = 2; + break; + } + lp++; + } + goto next_line; + */ + } } else if (!strncmp(lp, "then", 4) && if_state[ifstck] == 1) { lp += 4; if_state[ifstck] = 2; @@ -7972,7 +8244,7 @@ startline: if (if_exe[ifstck - 1]) if_exe[ifstck] = !if_result[ifstck]; } else if (!strncmp(lp, "endif", 5) && if_state[ifstck] >= 2) { lp += 5; - if (ifstck>0) { + if (ifstck > 0) { if_state[ifstck] = 0; ifstck--; } @@ -8280,6 +8552,7 @@ getnext: goto next_line; } #endif // USE_SCRIPT_GLOBVARS + #ifdef USE_LIGHT #ifdef USE_WS2812 else if (!strncmp(lp, "ws2812(", 7)) { @@ -8469,7 +8742,7 @@ getnext: // check for variable result if (if_state[ifstck] == 1) { - // evaluate exxpression + // evaluate expression lp = Evaluate_expression(lp, and_or, &if_result[ifstck], gv); SCRIPT_SKIP_SPACES if (*lp == '{' && if_state[ifstck] == 1) { @@ -8629,7 +8902,7 @@ getnext: #ifdef USE_SCRIPT_GLOBVARS if (globvindex >= 0 ) { if (glob_script_mem.type[globvindex].bits.global) { - script_udp_sendvar(varname, dfvar, 0); + script_udp_sendvar(varname, dfvar, 0, 0); } } #endif //USE_SCRIPT_GLOBVARS @@ -8677,6 +8950,16 @@ getnext: } glob_script_mem.cmdbuffer_size = *dfvar; break; +#ifdef USE_SCRIPT_GLOBVARS + case SCRIPT_UDP_PBS: + glob_script_mem.pb_size = *dfvar; + Restart_globvars(); + break; + case SCRIPT_UDP_MOD: + glob_script_mem.udp_flags.udp_binary_payload = *dfvar; + break; +#endif + #if (defined(USE_SML_M) || defined(USE_BINPLUGINS)) && defined(USE_SML_SCRIPT_CMD) case SML_JSON_ENABLE: //sml_options = *dfvar; @@ -8722,7 +9005,7 @@ getnext: #ifdef USE_SCRIPT_GLOBVARS if (globvindex >= 0) { if (glob_script_mem.type[globvindex].bits.global) { - script_udp_sendvar(varname, 0, str); + script_udp_sendvar(varname, 0, str, 0); } } #endif //USE_SCRIPT_GLOBVARS @@ -9200,7 +9483,6 @@ void script_sort_array(TS_FLOAT *array, uint16_t size) { } while (swapped); } - bool Is_gpio_used(uint8_t gpiopin) { if (gpiopin >= 0 && (gpiopin < nitems(TasmotaGlobal.gpio_pin)) && (TasmotaGlobal.gpio_pin[gpiopin] > 0)) { return true; @@ -10419,6 +10701,44 @@ const char kScriptCommands[] PROGMEM = D_CMND_SCRIPT "|" D_CMND_SUBSCRIBE "|" D_ #endif ; +void list_var(char *lp) { +TS_FLOAT fvar; +char str[SCRIPT_MAX_SBSIZE]; + glob_script_mem.glob_error = 0; + if (check_varname(lp) == NUM_ARRAY_RES && !strchr(lp, '[')) { + TS_FLOAT *fpd = 0; + uint16_t alend; + char *cp = get_array_by_name(lp, &fpd, &alend, 0); + ResponseAppend_P(PSTR("\"%s\":["), lp); + for (uint16_t cnt = 0; cnt < alend; cnt++) { + TS_FLOAT tvar = *fpd++; + ext_snprintf_P(str, sizeof(str), PSTR("%*_f"), -glob_script_mem.script_dprec, &tvar); + if (cnt) { + ResponseAppend_P(PSTR(",%s"), str); + } else { + ResponseAppend_P(PSTR("%s"), str); + } + } + ResponseAppend_P(PSTR("]")); + } else { + glob_script_mem.glob_error = 0; + glob_script_mem.var_not_found = 0; + GetNumericArgument(lp, OPER_EQU, &fvar, 0); + if (glob_script_mem.var_not_found) { + ResponseAppend_P(PSTR("\"%s\":\"???\""), lp); + } else { + if (glob_script_mem.glob_error == 1) { + // was string, not number + GetStringArgument(lp, OPER_EQU, str, 0); + ResponseAppend_P(PSTR("\"%s\":\"%s\""), lp, str); + } else { + ext_snprintf_P(str, sizeof(str), PSTR("%*_f"), -glob_script_mem.script_dprec, &fvar); + ResponseAppend_P(PSTR("\"%s\":%s"), lp, str); + } + } + } +} + bool ScriptCommand(void) { char command[CMDSZ]; bool serviced = true; @@ -10472,38 +10792,22 @@ bool ScriptCommand(void) { if ('?' == XdrvMailbox.data[0]) { char *lp = XdrvMailbox.data; lp++; - while (*lp==' ') lp++; - TS_FLOAT fvar; - char str[SCRIPT_MAX_SBSIZE]; - glob_script_mem.glob_error = 0; - TS_FLOAT *fpd = 0; - uint16_t alend; - char *cp = get_array_by_name(lp, &fpd, &alend, 0); - if (fpd && cp && (!strchr(lp, '[')) ) { - // is array - Response_P(PSTR("{\"script\":{\"%s\":["), lp); - for (uint16_t cnt = 0; cnt < alend; cnt++) { - TS_FLOAT tvar = *fpd++; - ext_snprintf_P(str, sizeof(str), PSTR("%*_f"), -glob_script_mem.script_dprec, &tvar); - if (cnt) { - ResponseAppend_P(PSTR(",%s"), str); - } else { - ResponseAppend_P(PSTR("%s"), str); - } - } - ResponseAppend_P(PSTR("]}}")); - } else { - glob_script_mem.glob_error = 0; - GetNumericArgument(lp, OPER_EQU, &fvar, 0); - if (glob_script_mem.glob_error == 1) { - // was string, not number - GetStringArgument(lp, OPER_EQU, str, 0); - Response_P(PSTR("{\"script\":{\"%s\":\"%s\"}}"), lp, str); + Response_P(PSTR("{\"script\":{")); + while (1) { + while (*lp==' ') lp++; + char *cp = strchr(lp, ';'); + if (cp) { + *cp = 0; + list_var(lp); + ResponseAppend_P(PSTR(",")); + lp = cp + 1; } else { - ext_snprintf_P(str, sizeof(str), PSTR("%*_f"), -glob_script_mem.script_dprec, &fvar); - Response_P(PSTR("{\"script\":{\"%s\":%s}}"), lp, str); + list_var(lp); + ResponseAppend_P(PSTR("}")); + break; } } + ResponseAppend_P(PSTR("}")); } return serviced; }