From b44c16d86138f61e2d7b69b1e20dc9c002a97219 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 25 Apr 2021 16:51:18 +0200 Subject: [PATCH] Add initial support for optional for template specific commands Add initial support for optional ``Template`` JSON fieldpair ``"CMND":";;..."`` (#11788) --- CHANGELOG.md | 16 ++++++++++------ RELEASENOTES.md | 7 ++----- tasmota/i18n.h | 1 + tasmota/settings.ino | 10 +++++----- tasmota/support.ino | 24 ++++++++++++++++++++++++ tasmota/support_command.ino | 17 +++++++++++++---- tasmota/tasmota_version.h | 2 +- tasmota/xdrv_01_webserver.ino | 8 ++++---- 8 files changed, 60 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c710b9342..c087f80bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,16 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Development -## [9.4.0.1] +## [9.4.0.2] +### Added +- Initial support for optional ``Template`` JSON fieldpair ``"CMND":";;..."`` (#11788) + +## [Released] + +## [9.4.0] 20210423 +- Release Leslie + +## [9.4.0.1] 20210423 ### Added - Command ``Wifi 0/1`` for ESP8266 to turn wifi Off and On. When wifi is Off it is always returned On after a restart except for a wake-up from deepsleep (#11839) @@ -14,11 +23,6 @@ All notable changes to this project will be documented in this file. - Command ``Power`` should not reset pulsetime (#11805) - Teleperiod rule handling regression from v9.3.1.2 (#11851) -## [Released] - -## [9.4.0] 20210422 -- Release Leslie - ## [9.3.1.4] 20210422 ### Added - Command ``TuyaTempSetRes 0..3`` to control Tuya Temperature Set Resolution (#11781) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index aaabcbdf5..574d5cc82 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -76,18 +76,15 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota [Complete list](BUILDS.md) of available feature and sensors. -## Changelog v9.4.0.1 +## Changelog v9.4.0.2 ### Added -- Command ``Wifi 0/1`` for ESP8266 to turn wifi Off and On. When wifi is Off it is always returned On after a restart except for a wake-up from deepsleep [#11839](https://github.com/arendst/Tasmota/issues/11839) +- Initial support for optional ``Template`` JSON fieldpair ``"CMND":";;..."`` [#11788](https://github.com/arendst/Tasmota/issues/11788) ### Breaking Changed ### Changed -- Zigbee refactored storage for device configuration and device last known data [#11838](https://github.com/arendst/Tasmota/issues/11838) ### Fixed -- Command ``Power`` should not reset pulsetime [#11805](https://github.com/arendst/Tasmota/issues/11805) -- Teleperiod rule handling regression from v9.3.1.2 [#11851](https://github.com/arendst/Tasmota/issues/11851) ### Noted - ESP32 single core **tasmota32solo1.bin** binary can only be uploaded using the GUI as OTA upload will trigger the watchdog timer \ No newline at end of file diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 3fe877cb7..ce307c2cb 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -345,6 +345,7 @@ #define D_JSON_GPIO "GPIO" #define D_JSON_FLAG "FLAG" #define D_JSON_BASE "BASE" + #define D_JSON_CMND "CMND" #define D_CMND_TEMPOFFSET "TempOffset" #define D_CMND_HUMOFFSET "HumOffset" #define D_CMND_GLOBAL_TEMP "GlobalTemp" diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 3eb10d608..5691f20a0 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1077,16 +1077,16 @@ void SettingsDefaultSet2(void) { flag4.mqtt_tls |= MQTT_TLS_ENABLED; flag4.mqtt_no_retain |= MQTT_NO_RETAIN; -#ifdef USER_TEMPLATE - String user_template = USER_TEMPLATE; - JsonTemplate((char*)user_template.c_str()); -#endif - Settings.flag = flag; Settings.flag2 = flag2; Settings.flag3 = flag3; Settings.flag4 = flag4; Settings.flag5 = flag5; + +#ifdef USER_TEMPLATE + String user_template = USER_TEMPLATE; + JsonTemplate((char*)user_template.c_str()); +#endif } /********************************************************************************************/ diff --git a/tasmota/support.ino b/tasmota/support.ino index f86cb1f16..1459810eb 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -515,6 +515,14 @@ char* UpperCase_P(char* dest, const char* source) return dest; } +char* StrStr_P(const char* source, const char* search) { + char case_source[strlen(source) +1]; + UpperCase_P(case_source, source); + char case_search[strlen(search) +1]; + UpperCase_P(case_search, search); + return strstr(case_source, case_search); +} + char* Trim(char* p) { if (*p != '\0') { @@ -1645,6 +1653,22 @@ bool JsonTemplate(char* dataBuf) Settings.user_template_base = base -1; // Default WEMOS } + val = root[PSTR(D_JSON_CMND)]; + if (val) { + if ((USER_MODULE == Settings.module) || (StrStr_P(val.getStr(), PSTR(D_CMND_MODULE " 0")))) { // Only execute if current module = USER_MODULE = this template + char* backup_data = XdrvMailbox.data; + XdrvMailbox.data = (char*)val.getStr(); // Backlog commands + uint32_t backup_data_len = XdrvMailbox.data_len; + XdrvMailbox.data_len = 1; // Any data + uint32_t backup_index = XdrvMailbox.index; + XdrvMailbox.index = 0; // Backlog0 - no delay + CmndBacklog(); + XdrvMailbox.index = backup_index; + XdrvMailbox.data_len = backup_data_len; + XdrvMailbox.data = backup_data; + } + } + // AddLog(LOG_LEVEL_DEBUG, PSTR("TPL: Converted")); // AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)&Settings.user_template, sizeof(Settings.user_template) / 2, 2); diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 4cdfcdf6a..f49b78762 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -326,20 +326,27 @@ void CmndBacklog(void) { TasmotaGlobal.backlog_nodelay = true; } -#ifdef SUPPORT_IF_STATEMENT char *blcommand = strtok(XdrvMailbox.data, ";"); +#ifdef SUPPORT_IF_STATEMENT while ((blcommand != nullptr) && (backlog.size() < MAX_BACKLOG)) #else uint32_t bl_pointer = (!TasmotaGlobal.backlog_pointer) ? MAX_BACKLOG -1 : TasmotaGlobal.backlog_pointer; bl_pointer--; - char *blcommand = strtok(XdrvMailbox.data, ";"); while ((blcommand != nullptr) && (TasmotaGlobal.backlog_index != bl_pointer)) #endif { + // Ignore ; within double quotes (") but find ; after first even quote + char *next = strchr(blcommand, '\0') +1; // Prepare for next ; + while ((next != nullptr) && (ChrCount(blcommand, "\"") % 2)) { // Check for even quote count + next--; // Select end of line + *next = ';'; // Restore ; removed by strtok() + next = strtok(nullptr, ";"); // Point to begin of next string up to next ; or nullptr + } + // Skip unnecessary command Backlog at start of blcommand while(true) { blcommand = Trim(blcommand); if (!strncasecmp_P(blcommand, PSTR(D_CMND_BACKLOG), strlen(D_CMND_BACKLOG))) { - blcommand += strlen(D_CMND_BACKLOG); // Skip unnecessary command Backlog + blcommand += strlen(D_CMND_BACKLOG); } else { break; } @@ -352,7 +359,9 @@ void CmndBacklog(void) { #else TasmotaGlobal.backlog[TasmotaGlobal.backlog_index] = blcommand; TasmotaGlobal.backlog_index++; - if (TasmotaGlobal.backlog_index >= MAX_BACKLOG) TasmotaGlobal.backlog_index = 0; + if (TasmotaGlobal.backlog_index >= MAX_BACKLOG) { + TasmotaGlobal.backlog_index = 0; + } #endif } blcommand = strtok(nullptr, ";"); diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index c8df3b7fe..ed8d5d0f2 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x09040001; +const uint32_t VERSION = 0x09040002; #endif // _TASMOTA_VERSION_H_ diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 1e1dece40..c96b80470 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2130,11 +2130,11 @@ void HandleOtherConfiguration(void) { } void OtherSaveSettings(void) { - char tmp1[300]; // Needs to hold complete ESP32 template of minimal 230 chars + char tmp1[400]; // Needs to hold complete ESP32 template of minimal 230 chars WebGetArg(PSTR("dn"), tmp1, sizeof(tmp1)); // Device name char tmp2[TOPSZ]; WebGetArg(PSTR("wp"), tmp2, sizeof(tmp2)); // Web password - char command[500]; + char command[600]; snprintf_P(command, sizeof(command), PSTR(D_CMND_BACKLOG "0 " D_CMND_WEBPASSWORD "2 %s;" D_CMND_SO "3 %d;" D_CMND_DEVICENAME " %s"), (!strlen(tmp2)) ? "\"" : (strlen(tmp2) < 5) ? "" : tmp2, Webserver->hasArg(F("b1")), // SetOption3 - Enable MQTT @@ -2155,8 +2155,8 @@ void OtherSaveSettings(void) { #endif // USE_EMULATION WebGetArg(PSTR("t1"), tmp1, sizeof(tmp1)); // Template - if (strlen(tmp1)) { // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255} - snprintf_P(command, sizeof(command), PSTR("%s;" D_CMND_TEMPLATE " %s%s"), command, tmp1, (Webserver->hasArg(F("t2"))) ? PSTR("; " D_CMND_MODULE " 0") : ""); + if (strlen(tmp1)) { // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255,"CMND":"SO123 1;SO99 0"} + snprintf_P(command, sizeof(command), PSTR("%s;%s" D_CMND_TEMPLATE " %s"), command, (Webserver->hasArg(F("t2"))) ? PSTR(D_CMND_MODULE " 0;") : "", tmp1); } ExecuteWebCommand(command); }