From f759e2698831653083e3cad1d26e9378cb657da8 Mon Sep 17 00:00:00 2001 From: Marcus Date: Fri, 8 Jan 2021 21:36:05 +0100 Subject: [PATCH 01/71] remove backward compatible #define option; ITurned it into an undocumented option to suppress it --- tasmota/xdrv_49_pid.ino | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tasmota/xdrv_49_pid.ino b/tasmota/xdrv_49_pid.ino index 37b8774a3..eda2b633f 100644 --- a/tasmota/xdrv_49_pid.ino +++ b/tasmota/xdrv_49_pid.ino @@ -119,11 +119,6 @@ #define PID_REPORT_MORE_SETTINGS // If defined, the SENSOR output will provide more extensive json // output in the PID section -// #define PID_BACKWARD_COMPATIBLE // Preserve the backward compatible reporting of PID power via - // `%topic%/PID {"power":"0.000"}` This is now available in - // `%topic$/SENSOR {..., "PID":{"PidPower":0.00}}` - // Don't use unless you know that you need it - * Help with using the PID algorithm and with loop tuning can be found at * http://blog.clanlaw.org.uk/2018/01/09/PID-tuning-with-node-red-contrib-pid.html * This is directed towards using the algorithm in the node-red node node-red-contrib-pid but the algorithm here is based on @@ -362,14 +357,14 @@ void PIDShowValues(void) { static void run_pid() { double power = pid.tick(pid_current_time_secs); -#ifdef PID_BACKWARD_COMPATIBLE +#ifdef PID_DONT_USE_PID_TOPIC // This part is left inside to regularly publish the PID Power via // `%topic%/PID {"power":"0.000"}` char str_buf[FLOATSZ]; dtostrfd(power, 3, str_buf); snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"%s\":\"%s\"}"), "power", str_buf); MqttPublishPrefixTopic_P(TELE, "PID", false); -#endif // PID_BACKWARD_COMPATIBLE +#endif // PID_DONT_USE_PID_TOPIC #if defined PID_SHUTTER // send output as a position from 0-100 to defined shutter From aedfe35b017567e28d06fd724699450235d67790 Mon Sep 17 00:00:00 2001 From: Marcus Date: Fri, 8 Jan 2021 21:36:28 +0100 Subject: [PATCH 02/71] re-add code to modify timeprop values via mqtt --- tasmota/xdrv_48_timeprop.ino | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tasmota/xdrv_48_timeprop.ino b/tasmota/xdrv_48_timeprop.ino index 6e8537dbb..a457c8d94 100644 --- a/tasmota/xdrv_48_timeprop.ino +++ b/tasmota/xdrv_48_timeprop.ino @@ -82,6 +82,11 @@ # include "Timeprop.h" +#define D_CMND_TIMEPROP "timeprop_" +#define D_CMND_TIMEPROP_SETPOWER "setpower_" // add index no on end (0:8) and data is power 0:1 + +enum TimepropCommands { CMND_TIMEPROP_SETPOWER }; +const char kTimepropCommands[] PROGMEM = D_CMND_TIMEPROP_SETPOWER; static Timeprop timeprops[TIMEPROP_NUM_OUTPUTS]; static int relayNos[TIMEPROP_NUM_OUTPUTS] = {TIMEPROP_RELAYS}; @@ -143,7 +148,50 @@ void Timeprop_Xdrv_Power() { /* } XdrvMailbox; */ // To get here post with topic cmnd/timeprop_setpower_n where n is index into timeprops 0:7 +bool Timeprop_Command() +{ + char command [CMDSZ]; + bool serviced = true; + uint8_t ua_prefix_len = strlen(D_CMND_TIMEPROP); // to detect prefix of command + /* + snprintf_P(log_data, sizeof(log_data), "Command called: " + "index: %d data_len: %d payload: %d topic: %s data: %s\n", + XdrvMailbox.index, + XdrvMailbox.data_len, + XdrvMailbox.payload, + (XdrvMailbox.payload >= 0 ? XdrvMailbox.topic : ""), + (XdrvMailbox.data_len >= 0 ? XdrvMailbox.data : "")); + AddLog(LOG_LEVEL_INFO); + */ + if (0 == strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_TIMEPROP), ua_prefix_len)) { + // command starts with timeprop_ + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + ua_prefix_len, kTimepropCommands); + if (CMND_TIMEPROP_SETPOWER == command_code) { + /* + snprintf_P(log_data, sizeof(log_data), "Timeprop command timeprop_setpower: " + "index: %d data_len: %d payload: %d topic: %s data: %s", + XdrvMailbox.index, + XdrvMailbox.data_len, + XdrvMailbox.payload, + (XdrvMailbox.payload >= 0 ? XdrvMailbox.topic : ""), + (XdrvMailbox.data_len >= 0 ? XdrvMailbox.data : "")); + AddLog(LOG_LEVEL_INFO); + */ + if (XdrvMailbox.index >=0 && XdrvMailbox.index < TIMEPROP_NUM_OUTPUTS) { + timeprops[XdrvMailbox.index].setPower( atof(XdrvMailbox.data), timeprop_current_time_secs ); + } + snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"" D_CMND_TIMEPROP D_CMND_TIMEPROP_SETPOWER "%d\":\"%s\"}"), + XdrvMailbox.index, XdrvMailbox.data); + } + else { + serviced = false; + } + } else { + serviced = false; + } + return serviced; +} /*********************************************************************************************\ * Interface @@ -162,6 +210,9 @@ bool Xdrv48(byte function) case FUNC_EVERY_SECOND: Timeprop_Every_Second(); break; + case FUNC_COMMAND: + result = Timeprop_Command(); + break; case FUNC_SET_POWER: Timeprop_Xdrv_Power(); break; From d966f1f74f3469567d91997e9b45f5f7f148149c Mon Sep 17 00:00:00 2001 From: Marcus Date: Fri, 8 Jan 2021 21:57:56 +0100 Subject: [PATCH 03/71] add ifndef to ensure "tasmota-minimal" still builds --- tasmota/xdrv_48_timeprop.ino | 3 +++ tasmota/xdrv_49_pid.ino | 2 ++ 2 files changed, 5 insertions(+) diff --git a/tasmota/xdrv_48_timeprop.ino b/tasmota/xdrv_48_timeprop.ino index a457c8d94..f11d5e46b 100644 --- a/tasmota/xdrv_48_timeprop.ino +++ b/tasmota/xdrv_48_timeprop.ino @@ -79,6 +79,7 @@ #ifdef USE_TIMEPROP +#ifndef FIRMWARE_MINIMAL # include "Timeprop.h" @@ -153,6 +154,7 @@ bool Timeprop_Command() char command [CMDSZ]; bool serviced = true; uint8_t ua_prefix_len = strlen(D_CMND_TIMEPROP); // to detect prefix of command + AddLog_P(LOG_LEVEL_ERROR, PSTR("TRP: Timeprop_Command called")); /* snprintf_P(log_data, sizeof(log_data), "Command called: " "index: %d data_len: %d payload: %d topic: %s data: %s\n", @@ -220,4 +222,5 @@ bool Xdrv48(byte function) return result; } +#endif // FIRMWARE_MINIMAL #endif // USE_TIMEPROP diff --git a/tasmota/xdrv_49_pid.ino b/tasmota/xdrv_49_pid.ino index eda2b633f..fdc02ea50 100644 --- a/tasmota/xdrv_49_pid.ino +++ b/tasmota/xdrv_49_pid.ino @@ -129,6 +129,7 @@ #ifdef USE_PID +#ifndef FIRMWARE_MINIMAL #include "PID.h" @@ -410,4 +411,5 @@ bool Xdrv49(byte function) } return result; } +#endif // FIRMWARE_MINIMAL #endif // USE_PID From 2e76946e2daab4c9f968d6931f0641bc79eef8db Mon Sep 17 00:00:00 2001 From: Marcus Date: Sat, 9 Jan 2021 18:05:54 +0100 Subject: [PATCH 04/71] add missing Response to SetPv --- tasmota/xdrv_49_pid.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/xdrv_49_pid.ino b/tasmota/xdrv_49_pid.ino index fdc02ea50..529ca3913 100644 --- a/tasmota/xdrv_49_pid.ino +++ b/tasmota/xdrv_49_pid.ino @@ -237,6 +237,7 @@ void CmndSetPv(void) { // this runs it at the next second run_pid_now = true; } + ResponseCmndNumber(atof(XdrvMailbox.data)); } void CmndSetSp(void) { @@ -358,7 +359,7 @@ void PIDShowValues(void) { static void run_pid() { double power = pid.tick(pid_current_time_secs); -#ifdef PID_DONT_USE_PID_TOPIC +#ifndef PID_DONT_USE_PID_TOPIC // This part is left inside to regularly publish the PID Power via // `%topic%/PID {"power":"0.000"}` char str_buf[FLOATSZ]; From 1fd5c44e6c16d1cadcd2315ca882e748592d10b8 Mon Sep 17 00:00:00 2001 From: Marcus Date: Sat, 9 Jan 2021 18:23:07 +0100 Subject: [PATCH 05/71] add missing response; fix exclusion of PID power --- tasmota/xdrv_49_pid.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/xdrv_49_pid.ino b/tasmota/xdrv_49_pid.ino index fdc02ea50..529ca3913 100644 --- a/tasmota/xdrv_49_pid.ino +++ b/tasmota/xdrv_49_pid.ino @@ -237,6 +237,7 @@ void CmndSetPv(void) { // this runs it at the next second run_pid_now = true; } + ResponseCmndNumber(atof(XdrvMailbox.data)); } void CmndSetSp(void) { @@ -358,7 +359,7 @@ void PIDShowValues(void) { static void run_pid() { double power = pid.tick(pid_current_time_secs); -#ifdef PID_DONT_USE_PID_TOPIC +#ifndef PID_DONT_USE_PID_TOPIC // This part is left inside to regularly publish the PID Power via // `%topic%/PID {"power":"0.000"}` char str_buf[FLOATSZ]; From 5a165962664b4ebf2294465d6433288e99f4b384 Mon Sep 17 00:00:00 2001 From: Marcus Date: Sun, 10 Jan 2021 15:47:26 +0100 Subject: [PATCH 06/71] update code size metrics --- tasmota/my_user_config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 5040f6c09..0eb76da95 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -811,10 +811,10 @@ // -- Prometheus exporter --------------------------- //#define USE_PROMETHEUS // Add support for https://prometheus.io/ metrics exporting over HTTP /metrics endpoint -// -- PID and Timeprop ------------------------------ -// #define use TIMEPROP // Add support for the timeprop feature (+0k8 code) +// -- PID and Timeprop ------------------------------ // Both together will add +12k1 code +// #define use TIMEPROP // Add support for the timeprop feature (+9k1 code) // For details on the configuration please see the header of tasmota/xdrv_48_timeprop.ino -// #define USE_PID // Add suport for the PID feature (+11k1 code) +// #define USE_PID // Add suport for the PID feature (+11k2 code) // For details on the configuration please see the header of tasmota/xdrv_49_pid.ino // -- End of general directives ------------------- From be68e1cdb1dd99aec84469744816a9e5b2a58844 Mon Sep 17 00:00:00 2001 From: Marcus Date: Fri, 8 Jan 2021 21:36:05 +0100 Subject: [PATCH 07/71] remove backward compatible #define option; Turned it into an undocumented option to suppress it --- tasmota/xdrv_49_pid.ino | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tasmota/xdrv_49_pid.ino b/tasmota/xdrv_49_pid.ino index 7da87ac7d..9d851b285 100644 --- a/tasmota/xdrv_49_pid.ino +++ b/tasmota/xdrv_49_pid.ino @@ -117,11 +117,6 @@ #define PID_REPORT_MORE_SETTINGS // If defined, the SENSOR output will provide more extensive json // output in the PID section -// #define PID_BACKWARD_COMPATIBLE // Preserve the backward compatible reporting of PID power via - // `%topic%/PID {"power":"0.000"}` This is now available in - // `%topic$/SENSOR {..., "PID":{"PidPower":0.00}}` - // Don't use unless you know that you need it - * Help with using the PID algorithm and with loop tuning can be found at * http://blog.clanlaw.org.uk/2018/01/09/PID-tuning-with-node-red-contrib-pid.html * This is directed towards using the algorithm in the node-red node node-red-contrib-pid but the algorithm here is based on @@ -391,14 +386,14 @@ void PIDShowValues(void) { void PIDRun(void) { double power = Pid.pid.tick(Pid.current_time_secs); -#ifdef PID_BACKWARD_COMPATIBLE +#ifdef PID_DONT_USE_PID_TOPIC // This part is left inside to regularly publish the PID Power via // `%topic%/PID {"power":"0.000"}` char str_buf[FLOATSZ]; dtostrfd(power, 3, str_buf); snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"%s\":\"%s\"}"), "power", str_buf); MqttPublishPrefixTopic_P(TELE, "PID", false); -#endif // PID_BACKWARD_COMPATIBLE +#endif // PID_DONT_USE_PID_TOPIC #if defined PID_SHUTTER // send output as a position from 0-100 to defined shutter From 405f25db08b055014e0d941edb032f5043f42473 Mon Sep 17 00:00:00 2001 From: Marcus Date: Fri, 8 Jan 2021 21:36:28 +0100 Subject: [PATCH 08/71] re-add code to modify timeprop values via mqtt --- tasmota/xdrv_48_timeprop.ino | 59 +++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/tasmota/xdrv_48_timeprop.ino b/tasmota/xdrv_48_timeprop.ino index bddf2653f..10fd3e843 100644 --- a/tasmota/xdrv_48_timeprop.ino +++ b/tasmota/xdrv_48_timeprop.ino @@ -81,6 +81,16 @@ * Publish values between 0 and 1 to the topic(s) described above \*********************************************************************************************/ +#define D_CMND_TIMEPROP "timeprop_" +#define D_CMND_TIMEPROP_SETPOWER "setpower_" // add index no on end (0:8) and data is power 0:1 + +enum TimepropCommands { CMND_TIMEPROP_SETPOWER }; +const char kTimepropCommands[] PROGMEM = D_CMND_TIMEPROP_SETPOWER; + +static Timeprop timeprops[TIMEPROP_NUM_OUTPUTS]; +static int relayNos[TIMEPROP_NUM_OUTPUTS] = {TIMEPROP_RELAYS}; +static long currentRelayStates = 0; // current actual relay states. Bit 0 first relay + #ifndef TIMEPROP_NUM_OUTPUTS #define TIMEPROP_NUM_OUTPUTS 1 // how many outputs to control (with separate alogorithm for each) #endif @@ -162,7 +172,51 @@ void TimepropXdrvPower(void) { /* char *data; */ /* } XdrvMailbox; */ -// To get here post with topic cmnd/timeprop_setpower_n where n is index into Tprop.timeprops 0:7 +// To get here post with topic cmnd/timeprop_setpower_n where n is index into timeprops 0:7 +bool TimepropCommand() +{ + char command [CMDSZ]; + bool serviced = true; + uint8_t ua_prefix_len = strlen(D_CMND_TIMEPROP); // to detect prefix of command + /* + snprintf_P(log_data, sizeof(log_data), "Command called: " + "index: %d data_len: %d payload: %d topic: %s data: %s\n", + XdrvMailbox.index, + XdrvMailbox.data_len, + XdrvMailbox.payload, + (XdrvMailbox.payload >= 0 ? XdrvMailbox.topic : ""), + (XdrvMailbox.data_len >= 0 ? XdrvMailbox.data : "")); + + AddLog(LOG_LEVEL_INFO); + */ + if (0 == strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_TIMEPROP), ua_prefix_len)) { + // command starts with timeprop_ + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + ua_prefix_len, kTimepropCommands); + if (CMND_TIMEPROP_SETPOWER == command_code) { + /* + snprintf_P(log_data, sizeof(log_data), "Timeprop command timeprop_setpower: " + "index: %d data_len: %d payload: %d topic: %s data: %s", + XdrvMailbox.index, + XdrvMailbox.data_len, + XdrvMailbox.payload, + (XdrvMailbox.payload >= 0 ? XdrvMailbox.topic : ""), + (XdrvMailbox.data_len >= 0 ? XdrvMailbox.data : "")); + AddLog(LOG_LEVEL_INFO); + */ + if (XdrvMailbox.index >=0 && XdrvMailbox.index < TIMEPROP_NUM_OUTPUTS) { + timeprops[XdrvMailbox.index].setPower( atof(XdrvMailbox.data), timeprop_current_time_secs ); + } + snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"" D_CMND_TIMEPROP D_CMND_TIMEPROP_SETPOWER "%d\":\"%s\"}"), + XdrvMailbox.index, XdrvMailbox.data); + } + else { + serviced = false; + } + } else { + serviced = false; + } + return serviced; +} /*********************************************************************************************\ * Interface @@ -180,6 +234,9 @@ bool Xdrv48(byte function) { case FUNC_EVERY_SECOND: TimepropEverySecond(); break; + case FUNC_COMMAND: + result = TimepropCommand(); + break; case FUNC_SET_POWER: TimepropXdrvPower(); break; From 02d8715d3d2534fa19b3f8e44b51c683af18ba23 Mon Sep 17 00:00:00 2001 From: Marcus Date: Fri, 8 Jan 2021 21:57:56 +0100 Subject: [PATCH 09/71] add ifndef to ensure "tasmota-minimal" still builds --- tasmota/xdrv_48_timeprop.ino | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tasmota/xdrv_48_timeprop.ino b/tasmota/xdrv_48_timeprop.ino index 10fd3e843..7bb772f08 100644 --- a/tasmota/xdrv_48_timeprop.ino +++ b/tasmota/xdrv_48_timeprop.ino @@ -79,7 +79,10 @@ #define TIMEPROP_RELAYS 1, 2 // which relay to control 1:8 * Publish values between 0 and 1 to the topic(s) described above -\*********************************************************************************************/ + * +**/ + + #define D_CMND_TIMEPROP "timeprop_" #define D_CMND_TIMEPROP_SETPOWER "setpower_" // add index no on end (0:8) and data is power 0:1 @@ -91,6 +94,7 @@ static Timeprop timeprops[TIMEPROP_NUM_OUTPUTS]; static int relayNos[TIMEPROP_NUM_OUTPUTS] = {TIMEPROP_RELAYS}; static long currentRelayStates = 0; // current actual relay states. Bit 0 first relay + #ifndef TIMEPROP_NUM_OUTPUTS #define TIMEPROP_NUM_OUTPUTS 1 // how many outputs to control (with separate alogorithm for each) #endif @@ -178,6 +182,7 @@ bool TimepropCommand() char command [CMDSZ]; bool serviced = true; uint8_t ua_prefix_len = strlen(D_CMND_TIMEPROP); // to detect prefix of command + AddLog_P(LOG_LEVEL_ERROR, PSTR("TRP: Timeprop_Command called")); /* snprintf_P(log_data, sizeof(log_data), "Command called: " "index: %d data_len: %d payload: %d topic: %s data: %s\n", From d54ee124412670a526106506b3723635d0c0dde8 Mon Sep 17 00:00:00 2001 From: Marcus Date: Sat, 9 Jan 2021 18:05:54 +0100 Subject: [PATCH 10/71] add missing Response to SetPv --- tasmota/xdrv_49_pid.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/xdrv_49_pid.ino b/tasmota/xdrv_49_pid.ino index 9d851b285..e44a7e6f1 100644 --- a/tasmota/xdrv_49_pid.ino +++ b/tasmota/xdrv_49_pid.ino @@ -266,6 +266,7 @@ void CmndSetPv(void) { // this runs it at the next second Pid.run_pid_now = true; } + ResponseCmndNumber(atof(XdrvMailbox.data)); } void CmndSetSp(void) { From dee3864f871f09bdf7aaa49fd806c90bcf433338 Mon Sep 17 00:00:00 2001 From: Marcus Date: Sun, 10 Jan 2021 15:47:26 +0100 Subject: [PATCH 11/71] update code size metrics --- tasmota/my_user_config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index cad1a2e83..12f47d073 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -828,10 +828,10 @@ #define THERMOSTAT_TEMP_BAND_NO_PEAK_DET 1 // Default temperature band in thenths of degrees celsius within no peak will be detected #define THERMOSTAT_TIME_STD_DEV_PEAK_DET_OK 10 // Default standard deviation in minutes of the oscillation periods within the peak detection is successful -// -- PID and Timeprop ------------------------------ -//#define USE_TIMEPROP // Add support for the timeprop feature (+0k8 code) +// -- PID and Timeprop ------------------------------ // Both together will add +12k1 code +// #define use TIMEPROP // Add support for the timeprop feature (+9k1 code) // For details on the configuration please see the header of tasmota/xdrv_48_timeprop.ino -//#define USE_PID // Add suport for the PID feature (+11k1 code) +// #define USE_PID // Add suport for the PID feature (+11k2 code) // For details on the configuration please see the header of tasmota/xdrv_49_pid.ino // -- End of general directives --------------------- From 97f3a7d438d103d7ee38ef68c324dd3802940362 Mon Sep 17 00:00:00 2001 From: Marcus Date: Mon, 11 Jan 2021 18:42:00 +0100 Subject: [PATCH 12/71] readd TimePropCommand --- tasmota/xdrv_48_timeprop.ino | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/tasmota/xdrv_48_timeprop.ino b/tasmota/xdrv_48_timeprop.ino index 93a75efe9..684d6e4b3 100644 --- a/tasmota/xdrv_48_timeprop.ino +++ b/tasmota/xdrv_48_timeprop.ino @@ -87,6 +87,8 @@ #define D_CMND_TIMEPROP "timeprop_" #define D_CMND_TIMEPROP_SETPOWER "setpower_" // add index no on end (0:8) and data is power 0:1 +#include "Timeprop.h" + enum TimepropCommands { CMND_TIMEPROP_SETPOWER }; const char kTimepropCommands[] PROGMEM = D_CMND_TIMEPROP_SETPOWER; @@ -117,8 +119,6 @@ static long currentRelayStates = 0; // current actual relay states. Bit 0 first #define TIMEPROP_RELAYS 1 // which relay to control 1:8 #endif -#include "Timeprop.h" - struct { Timeprop timeprops[TIMEPROP_NUM_OUTPUTS]; int relay_nos[TIMEPROP_NUM_OUTPUTS] = {TIMEPROP_RELAYS}; @@ -209,7 +209,7 @@ bool TimepropCommand() AddLog(LOG_LEVEL_INFO); */ if (XdrvMailbox.index >=0 && XdrvMailbox.index < TIMEPROP_NUM_OUTPUTS) { - timeprops[XdrvMailbox.index].setPower( atof(XdrvMailbox.data), timeprop_current_time_secs ); + timeprops[XdrvMailbox.index].setPower( atof(XdrvMailbox.data), Tprop.current_time_secs ); } snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"" D_CMND_TIMEPROP D_CMND_TIMEPROP_SETPOWER "%d\":\"%s\"}"), XdrvMailbox.index, XdrvMailbox.data); @@ -239,12 +239,9 @@ bool Xdrv48(byte function) { case FUNC_EVERY_SECOND: TimepropEverySecond(); break; - case FUNC_COMMAND: - result = TimepropCommand(); - break; - case FUNC_COMMAND: - result = TimepropCommand(); - break; + case FUNC_COMMAND: + result = TimepropCommand(); + break; case FUNC_SET_POWER: TimepropXdrvPower(); break; @@ -252,5 +249,4 @@ bool Xdrv48(byte function) { return result; } -#endif // FIRMWARE_MINIMAL #endif // USE_TIMEPROP From 611456327d320cb7775b1f219ebc34e960b712f2 Mon Sep 17 00:00:00 2001 From: Marcus Date: Mon, 11 Jan 2021 18:59:20 +0100 Subject: [PATCH 13/71] make sure code compiles with tasmota-minimal --- tasmota/xdrv_48_timeprop.ino | 2 ++ tasmota/xdrv_49_pid.ino | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tasmota/xdrv_48_timeprop.ino b/tasmota/xdrv_48_timeprop.ino index 684d6e4b3..a885f242d 100644 --- a/tasmota/xdrv_48_timeprop.ino +++ b/tasmota/xdrv_48_timeprop.ino @@ -18,6 +18,7 @@ */ #ifdef USE_TIMEPROP +#ifndef FIRMWARE_MINIMAL /*********************************************************************************************\ * Code to drive one or more relays in a time proportioned manner give a * required power value. @@ -249,4 +250,5 @@ bool Xdrv48(byte function) { return result; } +#endif // FIRMWARE_MINIMAL #endif // USE_TIMEPROP diff --git a/tasmota/xdrv_49_pid.ino b/tasmota/xdrv_49_pid.ino index e44a7e6f1..c3341b008 100644 --- a/tasmota/xdrv_49_pid.ino +++ b/tasmota/xdrv_49_pid.ino @@ -18,6 +18,7 @@ */ #ifdef USE_PID +#ifndef FIRMWARE_MINIMAL /*********************************************************************************************\ * Uses the library https://github.com/colinl/process-control.git from Github * In user_config_override.h include code as follows: @@ -439,4 +440,5 @@ bool Xdrv49(byte function) { } return result; } +#endif //FIRMWARE_MINIMAL #endif // USE_PID From 06cc6406dade7946cc71da3c4a5afc2f74b6586f Mon Sep 17 00:00:00 2001 From: Marcus Date: Mon, 11 Jan 2021 19:01:19 +0100 Subject: [PATCH 14/71] remove log entry --- tasmota/xdrv_48_timeprop.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/tasmota/xdrv_48_timeprop.ino b/tasmota/xdrv_48_timeprop.ino index a885f242d..5589868de 100644 --- a/tasmota/xdrv_48_timeprop.ino +++ b/tasmota/xdrv_48_timeprop.ino @@ -183,7 +183,6 @@ bool TimepropCommand() char command [CMDSZ]; bool serviced = true; uint8_t ua_prefix_len = strlen(D_CMND_TIMEPROP); // to detect prefix of command - AddLog_P(LOG_LEVEL_ERROR, PSTR("TRP: Timeprop_Command called")); /* snprintf_P(log_data, sizeof(log_data), "Command called: " "index: %d data_len: %d payload: %d topic: %s data: %s\n", From 9b81f11f17b691b83b6287d13589924146f029be Mon Sep 17 00:00:00 2001 From: BBBits Date: Tue, 12 Jan 2021 09:57:34 +1300 Subject: [PATCH 15/71] Resolve mDNS not restarting on wifi dn/up also changed log prefix for mDNS from DNS: to mDN: --- tasmota/i18n.h | 2 +- tasmota/support_network.ino | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 0d18f016a..3262bef09 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -680,7 +680,7 @@ #define D_LOG_KNX "KNX: " #define D_LOG_LOG "LOG: " // Logging #define D_LOG_MODULE "MOD: " // Module -#define D_LOG_MDNS "DNS: " // mDNS +#define D_LOG_MDNS "mDN: " // mDNS #define D_LOG_MQTT "MQT: " // MQTT #define D_LOG_OTHER "OTH: " // Other #define D_LOG_RESULT "RSL: " // Result diff --git a/tasmota/support_network.ino b/tasmota/support_network.ino index 0a41b933a..b2bb73bf0 100644 --- a/tasmota/support_network.ino +++ b/tasmota/support_network.ino @@ -36,6 +36,7 @@ void StartMdns(void) { // mdns_delayed_start--; // } else { // mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; + MDNS.end(); // close existing or MDNS.begin will fail Mdns.begun = (uint8_t)MDNS.begin(TasmotaGlobal.hostname); AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Mdns.begun) ? D_INITIALIZED : D_FAILED); // } From d7e29f07037ff201f51854c8b64f13028350278d Mon Sep 17 00:00:00 2001 From: Vic Date: Tue, 12 Jan 2021 03:27:06 +0100 Subject: [PATCH 16/71] no-library version, persistent naming option --- tasmota/xsns_81_seesaw_soil.ino | 165 ++++++++++++++++++++++++-------- 1 file changed, 126 insertions(+), 39 deletions(-) diff --git a/tasmota/xsns_81_seesaw_soil.ino b/tasmota/xsns_81_seesaw_soil.ino index aec9054f0..1e37d6608 100644 --- a/tasmota/xsns_81_seesaw_soil.ino +++ b/tasmota/xsns_81_seesaw_soil.ino @@ -20,11 +20,14 @@ #ifdef USE_I2C #ifdef USE_SEESAW_SOIL + /*********************************************************************************************\ * SEESAW_SOIL - Capacitance & Temperature Sensor * * I2C Address: 0x36, 0x37, 0x38, 0x39 * + * Memory footprint: 1296 bytes flash, 64 bytes RAM + * * NOTE: #define SEESAW_SOIL_PUBLISH enables immediate MQTT on soil moisture change * otherwise the moisture value will only be emitted every TelePeriod * #define SEESAW_SOIL_RAW enables displaying analog capacitance input in the @@ -34,19 +37,26 @@ #define XSNS_81 81 #define XI2C_56 56 // See I2CDEVICES.md -#include "Adafruit_seesaw.h" +#include "Adafruit_seesaw.h" // we only use definitions, no code -#define SEESAW_SOIL_MAX_SENSORS 4 -#define SEESAW_SOIL_START_ADDRESS 0x36 +//#define SEESAW_SOIL_RAW // enable raw readings +//#define SEESAW_SOIL_PUBLISH // enable immediate publish +//#define SEESAW_SOIL_PERSISTENT_NAMING // enable naming sensors by i2c address +//#define DEBUG_SEESAW_SOIL // enable debugging + +#define SEESAW_SOIL_MAX_SENSORS 4 +#define SEESAW_SOIL_START_ADDRESS 0x36 const char SeeSoilName[] = "SeeSoil"; // spaces not allowed for Homeassistant integration/mqtt topics uint8_t SeeSoilCount = 0; // global sensor count struct SEESAW_SOIL { - Adafruit_seesaw *ss; // instance pointer - uint16_t capacitance; - float temperature; - uint8_t address; + uint8_t address; // i2c address + float moisture; + float temperature; +#ifdef SEESAW_SOIL_RAW + uint16_t capacitance; // raw analog reading +#endif // SEESAW_SOIL_RAW } SeeSoil[SEESAW_SOIL_MAX_SENSORS]; // Used to convert capacitance into a moisture. @@ -56,48 +66,122 @@ struct SEESAW_SOIL { // So let's make a scale that converts those (apparent) facts into a percentage #define MAX_CAPACITANCE 1020.0f // subject to calibration #define MIN_CAPACITANCE 320 // subject to calibration -#define CAP_TO_MOIST(c) ((max((int)(c),MIN_CAPACITANCE)-MIN_CAPACITANCE)/(MAX_CAPACITANCE-MIN_CAPACITANCE)) +#define CAP_TO_MOIST(c) ((max((int)(c),MIN_CAPACITANCE)-MIN_CAPACITANCE)/(MAX_CAPACITANCE-MIN_CAPACITANCE)*100) -/********************************************************************************************/ +/*********************************************************************************************\ + * i2c routines +\*********************************************************************************************/ void SEESAW_SOILDetect(void) { - Adafruit_seesaw *SSptr=0; + uint8_t buf; + uint32_t i, addr; - for (uint32_t i = 0; i < SEESAW_SOIL_MAX_SENSORS; i++) { - int addr = SEESAW_SOIL_START_ADDRESS + i; - if (!I2cSetDevice(addr)) { continue; } - - if (!SSptr) { // don't have an object, - SSptr = new Adafruit_seesaw(); // allocate one - } - if (SSptr->begin(addr)) { - SeeSoil[SeeSoilCount].ss = SSptr; // save copy of pointer - SSptr = 0; // mark that we took it - SeeSoil[SeeSoilCount].address = addr; - SeeSoil[SeeSoilCount].temperature = NAN; - SeeSoil[SeeSoilCount].capacitance = 0; - I2cSetActiveFound(SeeSoil[SeeSoilCount].address, SeeSoilName); - SeeSoilCount++; - } + for (i = 0; i < SEESAW_SOIL_MAX_SENSORS; i++) { + addr = SEESAW_SOIL_START_ADDRESS + i; + if ( ! I2cSetDevice(addr)) { continue; } + delay(1); + SEESAW_Reset(addr); // reset all seesaw MCUs at once } - if (SSptr) { - delete SSptr; // used object for detection, didn't find anything so we don't need this object + delay(500); // give MCUs time to boot + for (i = 0; i < SEESAW_SOIL_MAX_SENSORS; i++) { + addr = SEESAW_SOIL_START_ADDRESS + i; + if ( ! I2cSetDevice(addr)) { continue; } + if ( ! SEESAW_ValidRead(addr, SEESAW_STATUS_BASE, SEESAW_STATUS_HW_ID, &buf, 1, 0)) { + continue; + } + if (buf != SEESAW_HW_ID_CODE) { +#ifdef DEBUG_SEESAW_SOIL + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SEE: HWID mismatch ADDR=%X, ID=%X"), addr, buf); +#endif // DEBUG_SEESAW_SOIL + continue; + } + SeeSoil[SeeSoilCount].address = addr; + SeeSoil[SeeSoilCount].temperature = NAN; + SeeSoil[SeeSoilCount].moisture = NAN; + #ifdef SEESAW_SOIL_RAW + SeeSoil[SeeSoilCount].capacitance = 0; // raw analog reading +#endif // SEESAW_SOIL_RAW + I2cSetActiveFound(SeeSoil[SeeSoilCount].address, SeeSoilName); + SeeSoilCount++; } } +float SEESAW_Temp(uint8_t addr) { // get temperature from seesaw at addr + uint8_t buf[4]; + + if (SEESAW_ValidRead(addr, SEESAW_STATUS_BASE, SEESAW_STATUS_TEMP, buf, 4, 1000)) { + int32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | + ((uint32_t)buf[2] << 8) | (uint32_t)buf[3]; + return ConvertTemp((1.0 / (1UL << 16)) * ret); + } + return NAN; +} + +float SEESAW_Moist(uint8_t addr) { // get moisture from seesaw at addr + uint8_t buf[2]; + uint16_t ret; + int32_t tries = 2; + + while (tries--) { + delay(1); + if (SEESAW_ValidRead(addr, SEESAW_TOUCH_BASE, SEESAW_TOUCH_CHANNEL_OFFSET, buf, 2, 3000)) { + ret = ((uint16_t)buf[0] << 8) | buf[1]; +#ifdef SEESAW_SOIL_RAW + for (int i=0; i < SeeSoilCount; i++) { + if (SeeSoil[i].address == addr) { + SeeSoil[i].capacitance = ret; + break; + } + } +#endif // SEESAW_SOIL_RAW + if (ret != 0xFFFF) { return (float) CAP_TO_MOIST(ret); } + } + } + return NAN; +} + +bool SEESAW_ValidRead(uint8_t addr, uint8_t regHigh, uint8_t regLow, // read from seesaw sensor + uint8_t *buf, uint8_t num, uint16_t delay) { + + Wire.beginTransmission((uint8_t) addr); + Wire.write((uint8_t) regHigh); + Wire.write((uint8_t) regLow); + int err = Wire.endTransmission(); + if (err) { return false; } + delayMicroseconds(delay); + if (num != Wire.requestFrom((uint8_t) addr, (uint8_t) num)) { + return false; + } + for (int i = 0; i < num; i++) { + buf[i] = (uint8_t) Wire.read(); + } + return true; +} + +bool SEESAW_Reset(uint8_t addr) { // init sensor MCU + Wire.beginTransmission((uint8_t) addr); + Wire.write((uint8_t) SEESAW_STATUS_BASE); + Wire.write((uint8_t) SEESAW_STATUS_SWRST); + return (Wire.endTransmission() == 0); +} + +/*********************************************************************************************\ + * JSON routines +\*********************************************************************************************/ + void SEESAW_SOILEverySecond(void) { // update sensor values and publish if changed #ifdef SEESAW_SOIL_PUBLISH uint32_t old_moist; #endif // SEESAW_SOIL_PUBLISH - for (uint32_t i = 0; i < SeeSoilCount; i++) { - SeeSoil[i].temperature = ConvertTemp(SeeSoil[i].ss->getTemp()); + for (int i = 0; i < SeeSoilCount; i++) { + SeeSoil[i].temperature = SEESAW_Temp(SeeSoil[i].address); #ifdef SEESAW_SOIL_PUBLISH - old_moist = uint32_t (CAP_TO_MOIST(SeeSoil[i].capacitance)*100); + old_moist = (uint32_t) SeeSoil[i].moisture; #endif // SEESAW_SOIL_PUBLISH - SeeSoil[i].capacitance = SeeSoil[i].ss->touchRead(0); + SeeSoil[i].moisture = SEESAW_Moist(SeeSoil[i].address); #ifdef SEESAW_SOIL_PUBLISH - if (uint32_t (CAP_TO_MOIST(SeeSoil[i].capacitance)*100) != old_moist) { + if ((uint32_t) SeeSoil[i].moisture != old_moist) { Response_P(PSTR("{")); // send values to MQTT & rules SEESAW_SOILJson(i); ResponseJsonEnd(); @@ -119,20 +203,19 @@ void SEESAW_SOILShow(bool json) { SEESAW_SOILJson(i); if (0 == TasmotaGlobal.tele_period) { #ifdef USE_DOMOTICZ - DomoticzTempHumPressureSensor(SeeSoil[i].temperature, CAP_TO_MOIST(SeeSoil[i].capacitance)*100, -42.0f); + DomoticzTempHumPressureSensor(SeeSoil[i].temperature, SeeSoil[i].moisture, -42.0f); #endif // USE_DOMOTICZ #ifdef USE_KNX KnxSensor(KNX_TEMPERATURE, SeeSoil[i].temperature); - KnxSensor(KNX_HUMIDITY, CAP_TO_MOIST(SeeSoil[i].capacitance) * 100); + KnxSensor(KNX_HUMIDITY, SeeSoil[i].moisture); #endif // USE_KNX } #ifdef USE_WEBSERVER } else { #ifdef SEESAW_SOIL_RAW - WSContentSend_PD(HTTP_SNS_ANALOG, sensor_name, 0, SeeSoil[i].capacitance); // dump raw value + WSContentSend_PD(HTTP_SNS_ANALOG, sensor_name, 0, SeeSoil[i].capacitance); #endif // SEESAW_SOIL_RAW - WSContentSend_PD(HTTP_SNS_MOISTURE, sensor_name, - uint32_t (CAP_TO_MOIST(SeeSoil[i].capacitance)*100)); // web page formats as integer (%d) percent + WSContentSend_PD(HTTP_SNS_MOISTURE, sensor_name, (uint32_t) SeeSoil[i].moisture); WSContentSend_PD(HTTP_SNS_TEMP, sensor_name, temperature, TempUnit()); #endif // USE_WEBSERVER } @@ -146,17 +229,21 @@ void SEESAW_SOILJson(int no) { // common json SEESAW_SOILName(no, sensor_name, sizeof(sensor_name)); dtostrfd(SeeSoil[no].temperature, Settings.flag2.temperature_resolution, temperature); ResponseAppend_P(PSTR ("\"%s\":{\"" D_JSON_ID "\":\"%02X\",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_MOISTURE "\":%u}"), - sensor_name, SeeSoil[no].address, temperature, uint32_t (CAP_TO_MOIST(SeeSoil[no].capacitance)*100)); + sensor_name, SeeSoil[no].address, temperature, (uint32_t) SeeSoil[no].moisture); } void SEESAW_SOILName(int no, char *name, int len) // generates a sensor name { +#ifdef SEESAW_SOIL_PERSISTENT_NAMING + snprintf_P(name, len, PSTR("%s%c%02X"), SeeSoilName, IndexSeparator(), SeeSoil[no].address); +#else if (SeeSoilCount > 1) { snprintf_P(name, len, PSTR("%s%c%u"), SeeSoilName, IndexSeparator(), no + 1); } else { strlcpy(name, SeeSoilName, len); } +#endif // SEESAW_SOIL_PERSISTENT_NAMING } /*********************************************************************************************\ From 0d81ffe30b21f678ff1d31febe3bbd35bc2784ca Mon Sep 17 00:00:00 2001 From: JohnG Date: Mon, 11 Jan 2021 20:12:46 -0800 Subject: [PATCH 17/71] Added support for multiple arguments to a subroutine. --- tasmota/xdrv_10_scripter.ino | 94 +++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 8f1a3e2be..198e58077 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -4550,53 +4550,59 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonParserObject *jo) { if (*ctype=='#') { // check for parameter ctype += tlen; - if (*ctype=='(' && *(lp+tlen)=='(') { - float fparam; - numeric = 1; - glob_script_mem.glob_error = 0; - GetNumericArgument((char*)ctype, OPER_EQU, &fparam, 0); - if (glob_script_mem.glob_error==1) { - // was string, not number - numeric = 0; - // get the string - GetStringArgument((char*)ctype + 1, OPER_EQU, cmpstr, 0); - } - lp += tlen; - if (*lp=='(') { - // fetch destination - lp++; - lp = isvar(lp, &vtype, &ind, 0, 0, 0); - if (vtype!=VAR_NV) { - // found variable as result - uint8_t index = glob_script_mem.type[ind.index].index; - if ((vtype&STYPE)==0) { - // numeric result - dfvar = &glob_script_mem.fvars[index]; - if (numeric) { - *dfvar = fparam; - } else { - // mismatch - *dfvar = CharToFloat(cmpstr); - } - } else { - // string result - sindex = index; - if (!numeric) { - strlcpy(glob_script_mem.glob_snp + (sindex * glob_script_mem.max_ssize), cmpstr, glob_script_mem.max_ssize); - } else { - // mismatch - dtostrfd(fparam, 6, glob_script_mem.glob_snp + (sindex * glob_script_mem.max_ssize)); - } + char nxttok = '('; + char *argptr = ctype+tlen; + + lp += tlen; + do { + if (*ctype==nxttok && *lp==nxttok) { + float fparam; + numeric = 1; + glob_script_mem.glob_error = 0; + argptr = GetNumericArgument((char*)ctype + 1, OPER_EQU, &fparam, 0); + if (glob_script_mem.glob_error==1) { + // was string, not number + numeric = 0; + // get the string + argptr = GetStringArgument((char*)ctype + 1, OPER_EQU, cmpstr, 0); + } + if (*lp==nxttok) { + // fetch destination + lp++; + lp = isvar(lp, &vtype, &ind, 0, 0, 0); + if (vtype!=VAR_NV) { + // found variable as result + uint8_t index = glob_script_mem.type[ind.index].index; + if ((vtype&STYPE)==0) { + // numeric result + dfvar = &glob_script_mem.fvars[index]; + if (numeric) { + *dfvar = fparam; + } else { + // mismatch + *dfvar = CharToFloat(cmpstr); + } + } else { + // string result + sindex = index; + if (!numeric) { + strlcpy(glob_script_mem.glob_snp + (sindex * glob_script_mem.max_ssize), cmpstr, glob_script_mem.max_ssize); + } else { + // mismatch + dtostrfd(fparam, 6, glob_script_mem.glob_snp + (sindex * glob_script_mem.max_ssize)); + } + } } } + } else { + if (*ctype==nxttok || (*lp!=SCRIPT_EOL && *lp!='?')) { + // revert + section = 0; + } } - } else { - lp += tlen; - if (*ctype=='(' || (*lp!=SCRIPT_EOL && *lp!='?')) { - // revert - section = 0; - } - } + nxttok = ' '; + ctype = argptr; + } while (*lp==' ' && (section == 1) ); } } } From e56a08f4de7a8258a4736a5de94fb6505611c368 Mon Sep 17 00:00:00 2001 From: Marcus Date: Tue, 12 Jan 2021 09:00:17 +0100 Subject: [PATCH 18/71] Change Response to Float, where floats are stored --- tasmota/xdrv_49_pid.ino | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tasmota/xdrv_49_pid.ino b/tasmota/xdrv_49_pid.ino index c3341b008..2773137a5 100644 --- a/tasmota/xdrv_49_pid.ino +++ b/tasmota/xdrv_49_pid.ino @@ -267,27 +267,27 @@ void CmndSetPv(void) { // this runs it at the next second Pid.run_pid_now = true; } - ResponseCmndNumber(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data)); } void CmndSetSp(void) { Pid.pid.setSp(atof(XdrvMailbox.data)); - ResponseCmndNumber(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data)); } void CmndSetPb(void) { Pid.pid.setPb(atof(XdrvMailbox.data)); - ResponseCmndNumber(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data)); } void CmndSetTi(void) { Pid.pid.setTi(atof(XdrvMailbox.data)); - ResponseCmndNumber(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data)); } void CmndSetTd(void) { Pid.pid.setTd(atof(XdrvMailbox.data)); - ResponseCmndNumber(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data)); } void CmndSetInitialInt(void) { @@ -297,7 +297,7 @@ void CmndSetInitialInt(void) { void CmndSetDSmooth(void) { Pid.pid.setDSmooth(atof(XdrvMailbox.data)); - ResponseCmndNumber(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data)); } void CmndSetAuto(void) { @@ -307,7 +307,7 @@ void CmndSetAuto(void) { void CmndSetManualPower(void) { Pid.pid.setManualPower(atof(XdrvMailbox.data)); - ResponseCmndNumber(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data)); } void CmndSetMaxInterval(void) { From e63b3d9ac9bcafda5764eba3725bb575dd8e895b Mon Sep 17 00:00:00 2001 From: Marcus Date: Tue, 12 Jan 2021 09:14:19 +0100 Subject: [PATCH 19/71] add number of digits to ResponseCmndFloat --- tasmota/xdrv_49_pid.ino | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tasmota/xdrv_49_pid.ino b/tasmota/xdrv_49_pid.ino index 2773137a5..15097106b 100644 --- a/tasmota/xdrv_49_pid.ino +++ b/tasmota/xdrv_49_pid.ino @@ -267,27 +267,27 @@ void CmndSetPv(void) { // this runs it at the next second Pid.run_pid_now = true; } - ResponseCmndFloat(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data), 1); } void CmndSetSp(void) { Pid.pid.setSp(atof(XdrvMailbox.data)); - ResponseCmndFloat(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data), 1); } void CmndSetPb(void) { Pid.pid.setPb(atof(XdrvMailbox.data)); - ResponseCmndFloat(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data), 1); } void CmndSetTi(void) { Pid.pid.setTi(atof(XdrvMailbox.data)); - ResponseCmndFloat(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data), 1); } void CmndSetTd(void) { Pid.pid.setTd(atof(XdrvMailbox.data)); - ResponseCmndFloat(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data), 1); } void CmndSetInitialInt(void) { @@ -297,7 +297,7 @@ void CmndSetInitialInt(void) { void CmndSetDSmooth(void) { Pid.pid.setDSmooth(atof(XdrvMailbox.data)); - ResponseCmndFloat(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data), 1); } void CmndSetAuto(void) { @@ -307,7 +307,7 @@ void CmndSetAuto(void) { void CmndSetManualPower(void) { Pid.pid.setManualPower(atof(XdrvMailbox.data)); - ResponseCmndFloat(atof(XdrvMailbox.data)); + ResponseCmndFloat(atof(XdrvMailbox.data), 1); } void CmndSetMaxInterval(void) { From 43e5a2c19e913eb0ae0532eac0c70f8883f40678 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Tue, 12 Jan 2021 09:20:56 +0100 Subject: [PATCH 20/71] Update API doc --- API.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/API.md b/API.md index 7bb77735b..b631172ed 100644 --- a/API.md +++ b/API.md @@ -14,8 +14,8 @@ Callback Id | Bool | xdrv | xsns | xnrg | xlgt | Description ----------------------------|------|------|------|------|------|---------------------------------- FUNC_SETTINGS_OVERRIDE | | x | | | | Override start-up settings FUNC_PIN_STATE | x | 1 | 2 | | | At GPIO configuration -FUNC_MODULE_INIT | x | 1 | | | 2 | Init module specific parameters -FUNC_PRE_INIT | | 1 | | 2 | | Once GPIO have been established +FUNC_MODULE_INIT | x | 3 | 1 | | 2 | Init module specific parameters +FUNC_PRE_INIT | | 1 | 3 | 2 | | Once GPIO have been established FUNC_INIT | | 1 | 3 | 2 | | At end of initialisation FUNC_LOOP | | 1 | 2 | | | In main loop FUNC_EVERY_50_MSECOND | | 1 | 2 | | | @@ -34,7 +34,7 @@ FUNC_COMMAND_SENSOR | x | | x | | | When command Se FUNC_MQTT_SUBSCRIBE | | x | | | | At end of MQTT subscriptions FUNC_MQTT_INIT | | x | | | | Once at end of MQTT connection FUNC_MQTT_DATA | x | x | | | | Before decoding command -FUNC_SET_POWER | | x | | | | Before setting relays +FUNC_SET_POWER | | 1 | 2 | | | Before setting relays FUNC_SET_DEVICE_POWER | x | x | | | | Set relay FUNC_SHOW_SENSOR | | x | | | | When FUNC_JSON_APPEND completes FUNC_ANY_KEY | | x | | | | @@ -49,6 +49,8 @@ FUNC_WEB_ADD_MAIN_BUTTON | | 1 | 2 | | | Add a main butt FUNC_WEB_ADD_HANDLER | | 1 | 2 | | | Add a webserver handler FUNC_SET_CHANNELS | | 2 | | | 1 | FUNC_SET_SCHEME | | | | | x | +FUNC_HOTPLUG_SCAN | | | x | | | +FUNC_DEVICE_GROUP_ITEM | | x | | | | The numbers represent the sequence of execution @@ -89,12 +91,15 @@ CFG: Loaded from flash at FB, Count 1581 xdrv - FUNC_SETTINGS_OVERRIDE xdrv - FUNC_PIN_STATE xsns - FUNC_PIN_STATE +xsns - FUNC_MODULE_INIT xdrv - FUNC_MODULE_INIT xlgt - FUNC_MODULE_INIT xdrv - FUNC_PRE_INIT xnrg - FUNC_PRE_INIT +xsns - FUNC_PRE_INIT SRC: Restart xdrv - FUNC_SET_POWER +xsns - FUNC_SET_POWER xlgt - FUNC_SET_CHANNELS xdrv - FUNC_SET_DEVICE_POWER Project tasmota Wemos 2 Version 7.0.0.3(tasmota)-STAGE From e7c96fbb7897ffd8b11d7213e8793eabef91b0e5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 12 Jan 2021 09:44:18 +0100 Subject: [PATCH 21/71] Support for 2M and 4MB builds --- platformio_override_sample.ini | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 3d624c30f..3d95545ad 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -48,6 +48,17 @@ build_flags = ${core.build_flags} ; -DDEBUG_TASMOTA_DRIVER ; -DDEBUG_TASMOTA_SENSOR +; *** CAUTION *** This setting is ONLY possible since 12.01.2021 with development version !!! +; *** Enable only if you exactly know what are you doing +; *** If you try with earlier builds a serial erase and flash is probably needed +; +; Build variant 1MB = 1MB firmware no filesystem (default) +;board_build.ldscript = eagle.flash.1m.ld +; Build variant 2MB = 1MB firmware, 1MB filesystem (ZigbeeBridge, most Shelly devices) +;board_build.ldscript = eagle.flash.2m1m.ld +; Build variant 4MB = 1MB firmware, 3MB filesystem (WEMOS D1 Mini, NodeMCU, Sonoff POW) +;board_build.ldscript = eagle.flash.4m3m.ld + ; set CPU frequency to 80MHz (default) or 160MHz ;board_build.f_cpu = 160000000L From c1d6d30cabd32e390c7431756a0a6700766cbb70 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 12 Jan 2021 10:27:07 +0100 Subject: [PATCH 22/71] Update I2CDEVICES.md --- I2CDEVICES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2CDEVICES.md b/I2CDEVICES.md index 22616d670..301b48111 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -75,7 +75,7 @@ Index | Define | Driver | Device | Address(es) | Description 50 | USE_VEML7700 | xsns_71 | VEML7700 | 0x10 | Ambient light intensity sensor 51 | USE_MCP9808 | xsns_72 | MCP9808 | 0x18 - 0x1F | Temperature sensor 52 | USE_HP303B | xsns_73 | HP303B | 0x76 - 0x77 | Pressure and temperature sensor - 53 | USE_MLX90640 | xdrv_84 | MLX90640 | 0x33 | IR array temperature sensor + 53 | USE_MLX90640 | xdrv_43 | MLX90640 | 0x33 | IR array temperature sensor 54 | USE_VL53L1X | xsns_77 | VL53L1X | 0x29 | Time-of-flight (ToF) distance sensor 55 | USE_EZOPH | xsns_78 | EZOPH | 0x61 - 0x70 | pH sensor 55 | USE_EZOORP | xsns_78 | EZOORP | 0x61 - 0x70 | ORP sensor From 120ba5cac2fd840ac2bde382aec95f0bcd727e15 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 12 Jan 2021 10:51:46 +0100 Subject: [PATCH 23/71] Add extra recovery option when linker changed --- tasmota/settings.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 518eb03d2..607cbdb44 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -205,14 +205,16 @@ uint32_t SETTINGS_LOCATION = FLASH_EEPROM_START; #endif // ESP32 -const uint8_t CFG_ROTATES = 7; // Number of flash sectors used (handles uploads) +const uint8_t CFG_ROTATES = 7; // Number of flash sectors used (handles uploads) uint32_t settings_location = FLASH_EEPROM_START; uint32_t settings_crc32 = 0; uint8_t *settings_buffer = nullptr; void SettingsInit(void) { - if (SETTINGS_LOCATION > 0xFA) { SETTINGS_LOCATION = 0xFA; } // Skip empty partition part + if (SETTINGS_LOCATION > 0xFA) { + SETTINGS_LOCATION = 0xFD; // Skip empty partition part + } } /********************************************************************************************/ From b62f0ff3cf312d8ea874a0d014429129bc04ffd7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 12 Jan 2021 11:29:13 +0100 Subject: [PATCH 24/71] added eagle.flash.4m2m.ld --- platformio_override_sample.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 3d95545ad..eb550c695 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -58,6 +58,8 @@ build_flags = ${core.build_flags} ;board_build.ldscript = eagle.flash.2m1m.ld ; Build variant 4MB = 1MB firmware, 3MB filesystem (WEMOS D1 Mini, NodeMCU, Sonoff POW) ;board_build.ldscript = eagle.flash.4m3m.ld +; Build variant 4MB = 1MB firmware, 1MB OTA, 2MB filesystem (WEMOS D1 Mini, NodeMCU, Sonoff POW) +;board_build.ldscript = eagle.flash.4m2m.ld ; set CPU frequency to 80MHz (default) or 160MHz ;board_build.f_cpu = 160000000L From ad55e49ed266648b620241a56c916b36da7b2a27 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 12 Jan 2021 12:05:20 +0100 Subject: [PATCH 25/71] Use eagle.flash.2m256.ld for zbbridge --- platformio_tasmota_env.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index f24794b68..442e33b48 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -64,6 +64,7 @@ build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} [env:tasmota-zbbridge] build_flags = ${common.build_flags} -DFIRMWARE_ZBBRIDGE +board_build.ldscript = eagle.flash.2m256.ld board_build.f_cpu = 160000000L lib_extra_dirs = lib/lib_ssl From 4ff1c8daa3fe70cbe7d4af642db4a349ec045abf Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 12 Jan 2021 12:18:32 +0100 Subject: [PATCH 26/71] Update platformio_override_sample.ini --- platformio_override_sample.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index eb550c695..814132fae 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -54,7 +54,7 @@ build_flags = ${core.build_flags} ; ; Build variant 1MB = 1MB firmware no filesystem (default) ;board_build.ldscript = eagle.flash.1m.ld -; Build variant 2MB = 1MB firmware, 1MB filesystem (ZigbeeBridge, most Shelly devices) +; Build variant 2MB = 1MB firmware, 1MB filesystem (most Shelly devices) ;board_build.ldscript = eagle.flash.2m1m.ld ; Build variant 4MB = 1MB firmware, 3MB filesystem (WEMOS D1 Mini, NodeMCU, Sonoff POW) ;board_build.ldscript = eagle.flash.4m3m.ld From 15598d71a902bc0b62331408bdd1facf6571c2ea Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 12 Jan 2021 14:54:12 +0100 Subject: [PATCH 27/71] Fix reset 5 and 6 when filesystem in use --- tasmota/settings.ino | 110 +++++++++++++++++------------------- tasmota/support_esp32.ino | 2 +- tasmota/support_esptool.ino | 2 + tasmota/support_tasmota.ino | 2 +- 4 files changed, 56 insertions(+), 60 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 607cbdb44..2f9bad000 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -154,19 +154,20 @@ bool RtcRebootValid(void) * 0x000xxxxx - Unzipped binary code end * 0x000x1000 - First page used by Core OTA * :::: - * 0x000F2FFF + * 0x000F2FFF 0x000F5FFF 0x000F5FFF ****************************************************************************** * Next 32k is overwritten by OTA - * 0x000F3000 - 4k Tasmota Quick Power Cycle counter (SETTINGS_LOCATION - CFG_ROTATES) - First four bytes only - * 0x000F3FFF - * 0x000F4000 - 4k First Tasmota rotating settings page + * 0x000F3000 0x000F6000 0x000F6000 - 4k Tasmota Quick Power Cycle counter (SETTINGS_LOCATION - CFG_ROTATES) - First four bytes only + * 0x000F3FFF 0x000F6FFF 0x000F6FFF + * 0x000F4000 0x000F7000 0x000F7000 - 4k First Tasmota rotating settings page * :::: - * 0x000FA000 - 4k Last Tasmota rotating settings page = Last page used by Core OTA (SETTINGS_LOCATION) - * 0x000FAFFF + * 0x000FA000 0x000FD000 0x000FD000 - 4k Last Tasmota rotating settings page = Last page used by Core OTA (SETTINGS_LOCATION) + * 0x000FAFFF 0x000FDFFF 0x000FDFFF ****************************************************************************** - * 0x000FB000 0x000FB000 - 15k9 Not used + * 0x000FE000 0x000FE000 - 3k9 Not used * 0x000FEFF0 0x000FEFF0 - 4k1 Empty * 0x000FFFFF 0x000FFFFF + * * 0x000FB000 0x00100000 0x00100000 - 0k, 980k or 2980k Core FS start (LittleFS) * 0x000FB000 0x001FA000 0x003FA000 - 0k, 980k or 2980k Core FS end (LittleFS) * 0x001FAFFF 0x003FAFFF @@ -189,7 +190,8 @@ extern "C" { #ifdef ESP8266 extern "C" uint32_t _FS_start; // 1M = 0x402fb000, 2M = 0x40300000, 4M = 0x40300000 -uint32_t SETTINGS_LOCATION = (((uint32_t)&_FS_start - 0x40200000) / SPI_FLASH_SEC_SIZE) -1; // 0xFA, 0xFF or 0xFF +const uint32_t FLASH_FS_START = (((uint32_t)&_FS_start - 0x40200000) / SPI_FLASH_SEC_SIZE); +uint32_t SETTINGS_LOCATION = FLASH_FS_START -1; // 0xFA, 0x0FF or 0x0FF // From libraries/EEPROM/EEPROM.cpp EEPROMClass extern "C" uint32_t _EEPROM_start; // 1M = 0x402FB000, 2M = 0x403FB000, 4M = 0x405FB000 @@ -213,7 +215,7 @@ uint8_t *settings_buffer = nullptr; void SettingsInit(void) { if (SETTINGS_LOCATION > 0xFA) { - SETTINGS_LOCATION = 0xFD; // Skip empty partition part + SETTINGS_LOCATION = 0xFD; // Skip empty partition part and keep in first 1M } } @@ -536,6 +538,9 @@ void SettingsSave(uint8_t rotate) Settings.cfg_crc32 = GetSettingsCrc32(); #ifdef ESP8266 +#ifdef USE_UFILESYS + TfsSaveFile(TASM_FILE_SETTINGS, (const uint8_t*)&Settings, sizeof(Settings)); +#endif if (ESP.flashEraseSector(settings_location)) { ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); } @@ -561,12 +566,18 @@ void SettingsSave(uint8_t rotate) void SettingsLoad(void) { #ifdef ESP8266 +#ifdef USE_UFILESYS + if (TfsLoadFile(TASM_FILE_SETTINGS, (uint8_t*)&Settings, sizeof(Settings))) { + settings_location = 1; + AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG "Loaded from File, " D_COUNT " %lu"), Settings.save_flag); + } else { +#endif // Load configuration from eeprom or one of 7 slots below if first valid load does not stop_flash_rotate // Activated with version 8.4.0.2 - Fails to read any config before version 6.6.0.11 settings_location = 0; uint32_t save_flag = 0; uint32_t flash_location = FLASH_EEPROM_START; - for (uint32_t i = 0; i < CFG_ROTATES; i++) { // Read all config pages in search of valid and latest + for (uint32_t i = 0; i <= CFG_ROTATES; i++) { // Read all config pages in search of valid and latest if (1 == i) { flash_location = SETTINGS_LOCATION; } ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); if ((Settings.cfg_crc32 != 0xFFFFFFFF) && (Settings.cfg_crc32 != 0x00000000) && (Settings.cfg_crc32 == GetSettingsCrc32())) { @@ -585,9 +596,13 @@ void SettingsLoad(void) { ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); } +#ifdef USE_UFILESYS + } +#endif #endif // ESP8266 #ifdef ESP32 uint32_t source = SettingsRead(&Settings, sizeof(Settings)); + if (source) { settings_location = 1; } AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG "Loaded from %s, " D_COUNT " %lu"), (source)?"File":"Nvm", Settings.save_flag); #endif // ESP32 @@ -606,25 +621,6 @@ uint32_t CfgTime(void) { return Settings.cfg_timestamp; } -void EspErase(uint32_t start_sector, uint32_t end_sector) -{ - bool serial_output = (LOG_LEVEL_DEBUG_MORE <= TasmotaGlobal.seriallog_level); - for (uint32_t sector = start_sector; sector < end_sector; sector++) { - - bool result = ESP.flashEraseSector(sector); // Arduino core - erases flash as seen by SDK -// bool result = !SPIEraseSector(sector); // SDK - erases flash as seen by SDK -// bool result = EsptoolEraseSector(sector); // Esptool - erases flash completely (slow) - - if (serial_output) { - Serial.printf_P(PSTR(D_LOG_APPLICATION D_ERASED_SECTOR " %d %s\n"), sector, (result) ? D_OK : D_ERROR); - delay(10); - } else { - yield(); - } - OsWatchLoop(); - } -} - #ifdef ESP8266 void SettingsErase(uint8_t type) { @@ -637,54 +633,52 @@ void SettingsErase(uint8_t type) The default erase function is EspTool (EsptoolErase) - 0 = Erase from program end until end of flash as seen by SDK - 1 = Erase 16k SDK parameter area near end of flash as seen by SDK (0x0xFCxxx - 0x0xFFFFF) solving possible wifi errors - 2 = Erase Tasmota parameter area (0x0xF3xxx - 0x0xFBFFF) + 0 = Erase from program end until end of flash as seen by SDK including optional filesystem + 1 = Erase 16k SDK parameter area near end of flash as seen by SDK (0x0XFCxxx - 0x0XFFFFF) solving possible wifi errors + 2 = Erase from program end until end of flash as seen by SDK excluding optional filesystem 3 = Erase Tasmota and SDK parameter area (0x0F3xxx - 0x0FFFFF) 4 = Erase SDK parameter area used for wifi calibration (0x0FCxxx - 0x0FCFFF) */ #ifndef FIRMWARE_MINIMAL + // Reset 2 = Erase all flash from program end to end of physical flash uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1; uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE; // Flash size as reported by hardware - if (1 == type) { + if (1 == type) { // Reset 3 = SDK parameter area // source Esp.cpp and core_esp8266_phy.cpp - _sectorStart = (ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE) - 4; // SDK parameter area - } - else if (2 == type) { - _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; // Tasmota parameter area (0x0F3xxx - 0x0FAFFF) - _sectorEnd = SETTINGS_LOCATION; - } - else if (3 == type) { - _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; // Tasmota and SDK parameter area (0x0F3xxx - 0x0FFFFF) - _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; // Flash size as seen by SDK - } - else if (4 == type) { -// _sectorStart = (ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE) - 4; // SDK phy area and Core calibration sector (0x0FC000) - _sectorStart = FLASH_EEPROM_START +1; // SDK phy area and Core calibration sector (0x0FC000) - _sectorEnd = _sectorStart +1; // SDK end of phy area and Core calibration sector (0x0FCFFF) + _sectorStart = (ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE) - 4; } + else if (2 == type) { // Reset 5, 6 = Erase all flash from program end to end of physical flash but skip filesystem /* - else if (5 == type) { - _sectorStart = (ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE) -4; // SDK phy area and Core calibration sector (0xxFC000) - _sectorEnd = _sectorStart +1; // SDK end of phy area and Core calibration sector (0xxFCFFF) - } +#ifdef USE_UFILESYS + TfsDeleteFile(TASM_FILE_SETTINGS); // Not needed as it is recreated by set defaults before restart +#endif */ - else { - return; + EsptoolErase(_sectorStart, FLASH_FS_START); + _sectorStart = FLASH_EEPROM_START; + _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; // Flash size as seen by SDK + } + else if (3 == type) { // QPC Reached = QPC and Tasmota and SDK parameter area (0x0F3xxx - 0x0FFFFF) +#ifdef USE_UFILESYS + TfsDeleteFile(TASM_FILE_SETTINGS); +#endif + EsptoolErase(SETTINGS_LOCATION - CFG_ROTATES, SETTINGS_LOCATION +1); + _sectorStart = FLASH_EEPROM_START; + _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; // Flash size as seen by SDK + } + else if (4 == type) { // WIFI_FORCE_RF_CAL_ERASE = SDK wifi calibration + _sectorStart = FLASH_EEPROM_START +1; // SDK phy area and Core calibration sector (0x0XFC000) + _sectorEnd = _sectorStart +1; // SDK end of phy area and Core calibration sector (0x0XFCFFF) } - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%08X to 0x%08X"), _sectorStart * SPI_FLASH_SEC_SIZE, (_sectorEnd * SPI_FLASH_SEC_SIZE) -1); - -// EspErase(_sectorStart, _sectorEnd); // Arduino core and SDK - erases flash as seen by SDK - EsptoolErase(_sectorStart, _sectorEnd); // Esptool - erases flash completely + EsptoolErase(_sectorStart, _sectorEnd); // Esptool - erases flash completely #endif // FIRMWARE_MINIMAL } #endif // ESP8266 void SettingsSdkErase(void) { - WiFi.disconnect(false); // Delete SDK wifi config + WiFi.disconnect(false); // Delete SDK wifi config SettingsErase(1); delay(1000); } diff --git a/tasmota/support_esp32.ino b/tasmota/support_esp32.ino index 40ef5fe43..d56040b86 100644 --- a/tasmota/support_esp32.ino +++ b/tasmota/support_esp32.ino @@ -138,7 +138,7 @@ int32_t NvmErase(const char *sNvsName) { void SettingsErase(uint8_t type) { // SDK and Tasmota data is held in default NVS partition - // Tasmota data is held also in file /settings on default filesystem + // Tasmota data is held also in file /.settings on default filesystem // cal_data - SDK PHY calibration data as documented in esp_phy_init.h // qpc - Tasmota Quick Power Cycle state // main - Tasmota Settings data diff --git a/tasmota/support_esptool.ino b/tasmota/support_esptool.ino index f100a4706..6551c7912 100644 --- a/tasmota/support_esptool.ino +++ b/tasmota/support_esptool.ino @@ -95,6 +95,8 @@ bool EsptoolEraseSector(uint32_t sector) void EsptoolErase(uint32_t start_sector, uint32_t end_sector) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%06X to 0x%06X"), start_sector * SPI_FLASH_SEC_SIZE, (end_sector * SPI_FLASH_SEC_SIZE) -1); + int next_erase_sector = start_sector; int remaining_erase_sector = end_sector - start_sector; diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 08205d23d..597435e40 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1134,7 +1134,7 @@ void Every250mSeconds(void) // Backup mqtt host, port, client, username and password // } if ((215 == TasmotaGlobal.restart_flag) || (216 == TasmotaGlobal.restart_flag)) { - SettingsErase(0); // Erase all flash from program end to end of physical flash + SettingsErase(2); // Erase all flash from program end to end of physical excluding optional filesystem } SettingsDefault(); // Restore current SSIDs and Passwords From 08033444c5ac1bd8624f91e41cfbffbc140f7d06 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 12 Jan 2021 15:03:06 +0100 Subject: [PATCH 28/71] Fix filetime --- tasmota/support_rtc.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index e9afa4597..990e78666 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -455,7 +455,7 @@ void RtcSecond(void) Rtc.midnight_now = true; } -#ifdef ESP32 +//#ifdef ESP32 if (mutex) { // Time is just synced and is valid // Sync RTOS time to be used by SD Card time stamps struct timeval tv; @@ -463,7 +463,7 @@ void RtcSecond(void) tv.tv_usec = 0; settimeofday(&tv, nullptr); } -#endif // ESP32 +//#endif // ESP32 } From c494c89a1a9cff9e7df9e71f12c2d50ad20a7d91 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 12 Jan 2021 15:13:42 +0100 Subject: [PATCH 29/71] Update support_rtc.ino --- tasmota/support_rtc.ino | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index 990e78666..08f7cfc3d 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -455,16 +455,13 @@ void RtcSecond(void) Rtc.midnight_now = true; } -//#ifdef ESP32 if (mutex) { // Time is just synced and is valid - // Sync RTOS time to be used by SD Card time stamps + // Sync Core/RTOS time to be used by file system time stamps struct timeval tv; tv.tv_sec = Rtc.local_time; tv.tv_usec = 0; settimeofday(&tv, nullptr); } -//#endif // ESP32 - } RtcTime.year += 1970; From 4181a884ebe779ae49f4b6e86f0aface80762edf Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 12 Jan 2021 15:33:15 +0100 Subject: [PATCH 30/71] support littlefs with PlatformIO --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index c03175200..e76901e33 100644 --- a/platformio.ini +++ b/platformio.ini @@ -66,6 +66,7 @@ default_envs = ${build_envs.default_envs} [common] framework = arduino board = esp01_1m +board_build.filesystem = littlefs board_build.flash_mode = dout board_build.ldscript = eagle.flash.1m.ld From 65ba49e59465399e62bb05eb5a61effd6fc80854 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 12 Jan 2021 15:35:08 +0100 Subject: [PATCH 31/71] add littlefs --- platformio_tasmota_env.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index 442e33b48..ce05c138f 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -3,6 +3,7 @@ platform = ${common.platform} platform_packages = ${common.platform_packages} framework = ${common.framework} board = ${common.board} +board_build.filesystem = ${common.board_build.filesystem} board_build.ldscript = ${common.board_build.ldscript} board_build.flash_mode = ${common.board_build.flash_mode} board_build.f_flash = ${common.board_build.f_flash} From a376ff6e532e39c9a2d2518e7fad27aa4c5de74d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 12 Jan 2021 15:36:27 +0100 Subject: [PATCH 32/71] add littlefs --- platformio_tasmota32.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 7234d9417..79c56eb96 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -47,6 +47,7 @@ platform_packages = ${core32.platform_packages} build_unflags = ${core32.build_unflags} build_flags = ${core32.build_flags} board = esp32dev +board_build.filesystem = ${common.board_build.filesystem} board_build.ldscript = esp32_out.ld board_build.partitions = esp32_partition_app1984k_spiffs64k.csv board_build.flash_mode = ${common.board_build.flash_mode} From 9c5e6acdc146257f08a4b66f86b684ce5b3ac092 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 12 Jan 2021 15:44:40 +0100 Subject: [PATCH 33/71] Tasmota supported linker files Lets decide to currently only support these. --- platformio_override_sample.ini | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 814132fae..344faeea3 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -54,12 +54,12 @@ build_flags = ${core.build_flags} ; ; Build variant 1MB = 1MB firmware no filesystem (default) ;board_build.ldscript = eagle.flash.1m.ld -; Build variant 2MB = 1MB firmware, 1MB filesystem (most Shelly devices) -;board_build.ldscript = eagle.flash.2m1m.ld -; Build variant 4MB = 1MB firmware, 3MB filesystem (WEMOS D1 Mini, NodeMCU, Sonoff POW) -;board_build.ldscript = eagle.flash.4m3m.ld -; Build variant 4MB = 1MB firmware, 1MB OTA, 2MB filesystem (WEMOS D1 Mini, NodeMCU, Sonoff POW) +; Build variant 2MB = 1MB firmware, +744k OTA, 256k filesystem (Zigbee Bridge, most Shelly devices) +;board_build.ldscript = eagle.flash.2m256.ld +; Build variant 4MB = 1MB firmware, +1MB OTA, 2MB filesystem (WEMOS D1 Mini, NodeMCU, Sonoff POW) ;board_build.ldscript = eagle.flash.4m2m.ld +; Build variant 16MB = 1MB firmware, +1MB OTA, 14MB filesystem (WEMOS D1 Mini pro, Ledunia (=32MB)) +;board_build.ldscript = eagle.flash.16m14m.ld ; set CPU frequency to 80MHz (default) or 160MHz ;board_build.f_cpu = 160000000L From 37ee4e6d8eefac4ccc69e7f807b57c576773fa6c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 12 Jan 2021 17:18:56 +0100 Subject: [PATCH 34/71] Add optional file to most recent settings check --- tasmota/settings.ino | 45 ++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 2f9bad000..d61f66743 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -566,39 +566,48 @@ void SettingsSave(uint8_t rotate) void SettingsLoad(void) { #ifdef ESP8266 -#ifdef USE_UFILESYS - if (TfsLoadFile(TASM_FILE_SETTINGS, (uint8_t*)&Settings, sizeof(Settings))) { - settings_location = 1; - AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG "Loaded from File, " D_COUNT " %lu"), Settings.save_flag); - } else { -#endif - // Load configuration from eeprom or one of 7 slots below if first valid load does not stop_flash_rotate + // Load configuration from optional file and flash (eeprom and 7 additonal slots) if first valid load does not stop_flash_rotate // Activated with version 8.4.0.2 - Fails to read any config before version 6.6.0.11 settings_location = 0; uint32_t save_flag = 0; - uint32_t flash_location = FLASH_EEPROM_START; - for (uint32_t i = 0; i <= CFG_ROTATES; i++) { // Read all config pages in search of valid and latest - if (1 == i) { flash_location = SETTINGS_LOCATION; } - ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); + uint32_t max_slots = CFG_ROTATES +1; + uint32_t flash_location; + uint32_t slot = 1; +#ifdef USE_UFILESYS + if (TfsLoadFile(TASM_FILE_SETTINGS, (uint8_t*)&Settings, sizeof(Settings))) { + flash_location = 1; + slot = 0; + } +#endif + while (slot <= max_slots) { // Read all config pages in search of valid and latest + if (slot > 0) { + flash_location = (1 == slot) ? FLASH_EEPROM_START : (2 == slot) ? SETTINGS_LOCATION : flash_location -1; + ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); + } if ((Settings.cfg_crc32 != 0xFFFFFFFF) && (Settings.cfg_crc32 != 0x00000000) && (Settings.cfg_crc32 == GetSettingsCrc32())) { - if (Settings.save_flag > save_flag) { // Find latest page based on incrementing save_flag + if (Settings.save_flag > save_flag) { // Find latest page based on incrementing save_flag save_flag = Settings.save_flag; settings_location = flash_location; - if (Settings.flag.stop_flash_rotate && (0 == i)) { // Stop if only eeprom area should be used and it is valid + if (Settings.flag.stop_flash_rotate && (1 == slot)) { // Stop if only eeprom area should be used and it is valid break; } } } - flash_location--; + slot++; delay(1); } if (settings_location > 0) { - ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); - AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); - } #ifdef USE_UFILESYS - } + if (1 == settings_location) { + TfsLoadFile(TASM_FILE_SETTINGS, (uint8_t*)&Settings, sizeof(Settings)); + AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG "Loaded from File, " D_COUNT " %lu"), Settings.save_flag); + } else #endif + { + ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); + AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); + } + } #endif // ESP8266 #ifdef ESP32 uint32_t source = SettingsRead(&Settings, sizeof(Settings)); From 800f86d56e3b85d19cf5344b18c83fa0aceb35bc Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Tue, 12 Jan 2021 19:31:15 +0100 Subject: [PATCH 35/71] Moving more to PROGMEM --- tasmota/support_command.ino | 6 ++-- tasmota/support_tasmota.ino | 2 +- tasmota/xdrv_01_webserver.ino | 32 +++++++++++----------- tasmota/xdrv_02_mqtt.ino | 2 +- tasmota/xdrv_09_timers.ino | 4 +-- tasmota/xdrv_10_scripter.ino | 4 +-- tasmota/xdrv_20_hue.ino | 2 +- tasmota/xdrv_23_zigbee_2a_devices_impl.ino | 4 +-- tasmota/xdrv_23_zigbee_5_converters.ino | 4 +-- tasmota/xdrv_23_zigbee_7_5_map.ino | 2 +- tasmota/xdrv_23_zigbee_A_impl.ino | 2 +- tasmota/xdrv_28_pcf8574.ino | 6 ++-- tasmota/xdrv_50_filesystem.ino | 2 +- 13 files changed, 36 insertions(+), 36 deletions(-) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 7faef10d5..0866d3f84 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -727,12 +727,12 @@ void CmndRestart(void) switch (XdrvMailbox.payload) { case 1: TasmotaGlobal.restart_flag = 2; - ResponseCmndChar(D_JSON_RESTARTING); + ResponseCmndChar(PSTR(D_JSON_RESTARTING)); break; case 2: TasmotaGlobal.restart_flag = 2; TasmotaGlobal.restart_halt = true; - ResponseCmndChar(D_JSON_HALTING); + ResponseCmndChar(PSTR(D_JSON_HALTING)); break; case -1: CmndCrash(); // force a crash @@ -1208,7 +1208,7 @@ void CmndGpio(void) if (jsflg2) { ResponseClear(); } else { - ResponseCmndChar(D_JSON_NOT_SUPPORTED); + ResponseCmndChar(PSTR(D_JSON_NOT_SUPPORTED)); } } } diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 597435e40..a6e0b2104 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1169,7 +1169,7 @@ void Every250mSeconds(void) } TasmotaGlobal.restart_flag--; if (TasmotaGlobal.restart_flag <= 0) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "%s"), (TasmotaGlobal.restart_halt) ? "Halted" : D_RESTARTING); + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "%s"), (TasmotaGlobal.restart_halt) ? PSTR("Halted") : PSTR(D_RESTARTING)); EspRestart(); } } diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 229d9af1d..a86e8586b 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -475,14 +475,14 @@ void StartWebserver(int type, IPAddress ipweb) String ipv6_addr = WifiGetIPv6(); if (ipv6_addr!="") { AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s and IPv6 global address %s "), - NetworkHostname(), (Mdns.begun) ? ".local" : "", ipweb.toString().c_str(), ipv6_addr.c_str()); + NetworkHostname(), (Mdns.begun) ? PSTR(".local") : "", ipweb.toString().c_str(), ipv6_addr.c_str()); } else { AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), - NetworkHostname(), (Mdns.begun) ? ".local" : "", ipweb.toString().c_str()); + NetworkHostname(), (Mdns.begun) ? PSTR(".local") : "", ipweb.toString().c_str()); } #else AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), - NetworkHostname(), (Mdns.begun) ? ".local" : "", ipweb.toString().c_str()); + NetworkHostname(), (Mdns.begun) ? PSTR(".local") : "", ipweb.toString().c_str()); #endif // LWIP_IPV6 = 1 TasmotaGlobal.rules_flag.http_init = 1; } @@ -744,7 +744,7 @@ void WSContentSendStyle_P(const char* formatP, ...) bool sip = (static_cast(WiFi.softAPIP()) != 0); WSContentSend_P(PSTR("

%s%s (%s%s%s)

"), // tasmota.local (192.168.2.12, 192.168.4.1) NetworkHostname(), - (Mdns.begun) ? ".local" : "", + (Mdns.begun) ? PSTR(".local") : "", (lip) ? WiFi.localIP().toString().c_str() : "", (lip && sip) ? ", " : "", (sip) ? WiFi.softAPIP().toString().c_str() : ""); @@ -1230,15 +1230,15 @@ bool HandleRootStatusRefresh(void) uint32_t fsize = (TasmotaGlobal.devices_present < 5) ? 70 - (TasmotaGlobal.devices_present * 8) : 32; #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { - WSContentSend_P(HTTP_DEVICE_STATE, 36, (bitRead(TasmotaGlobal.power, 0)) ? "bold" : "normal", 54, GetStateText(bitRead(TasmotaGlobal.power, 0))); + WSContentSend_P(HTTP_DEVICE_STATE, 36, (bitRead(TasmotaGlobal.power, 0)) ? PSTR("bold") : PSTR("normal"), 54, GetStateText(bitRead(TasmotaGlobal.power, 0))); uint32_t fanspeed = GetFanspeed(); snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fanspeed); - WSContentSend_P(HTTP_DEVICE_STATE, 64, (fanspeed) ? "bold" : "normal", 54, (fanspeed) ? svalue : GetStateText(0)); + WSContentSend_P(HTTP_DEVICE_STATE, 64, (fanspeed) ? PSTR("bold") : PSTR("normal"), 54, (fanspeed) ? svalue : GetStateText(0)); } else { #endif // USE_SONOFF_IFAN for (uint32_t idx = 1; idx <= TasmotaGlobal.devices_present; idx++) { snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(TasmotaGlobal.power, idx -1)); - WSContentSend_P(HTTP_DEVICE_STATE, 100 / TasmotaGlobal.devices_present, (bitRead(TasmotaGlobal.power, idx -1)) ? "bold" : "normal", fsize, (TasmotaGlobal.devices_present < 5) ? GetStateText(bitRead(TasmotaGlobal.power, idx -1)) : svalue); + WSContentSend_P(HTTP_DEVICE_STATE, 100 / TasmotaGlobal.devices_present, (bitRead(TasmotaGlobal.power, idx -1)) ? PSTR("bold") : PSTR("normal"), fsize, (TasmotaGlobal.devices_present < 5) ? GetStateText(bitRead(TasmotaGlobal.power, idx -1)) : svalue); } #ifdef USE_SONOFF_IFAN } @@ -1438,7 +1438,7 @@ void HandleTemplateConfiguration(void) for (uint32_t i = 0; i < MAX_GPIO_PIN; i++) { if (!FlashPin(i)) { WSContentSend_P(PSTR("" D_GPIO "%d"), - ((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:150px'" : "", i, i); + ((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? PSTR(" style='width:150px'") : "", i, i); WSContentSend_P(PSTR(""), i); } } @@ -1824,7 +1824,7 @@ void HandleLoggingConfiguration(void) idx); for (uint32_t i = LOG_LEVEL_NONE; i <= LOG_LEVEL_DEBUG_MORE; i++) { WSContentSend_P(PSTR("%d %s"), - (i == llevel) ? " selected" : "", i, i, + (i == llevel) ? PSTR(" selected") : "", i, i, GetTextIndexed(stemp1, sizeof(stemp1), i, kLoggingLevels)); } WSContentSend_P(PSTR("

")); @@ -1880,8 +1880,8 @@ void HandleOtherConfiguration(void) TemplateJson(); char stemp[strlen(TasmotaGlobal.mqtt_data) +1]; strlcpy(stemp, TasmotaGlobal.mqtt_data, sizeof(stemp)); // Get JSON template - WSContentSend_P(HTTP_FORM_OTHER, stemp, (USER_MODULE == Settings.module) ? " checked disabled" : "", - (Settings.flag.mqtt_enabled) ? " checked" : "", // SetOption3 - Enable MQTT + WSContentSend_P(HTTP_FORM_OTHER, stemp, (USER_MODULE == Settings.module) ? PSTR(" checked disabled") : "", + (Settings.flag.mqtt_enabled) ? PSTR(" checked") : "", // SetOption3 - Enable MQTT SettingsText(SET_FRIENDLYNAME1), SettingsText(SET_DEVICENAME)); uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!TasmotaGlobal.devices_present) ? 1 : TasmotaGlobal.devices_present; @@ -1911,9 +1911,9 @@ void HandleOtherConfiguration(void) if (i < EMUL_MAX) { WSContentSend_P(PSTR("%s %s
"), // Different id only used for labels i, i, - (i == Settings.flag2.emulation) ? " checked" : "", + (i == Settings.flag2.emulation) ? PSTR(" checked") : "", GetTextIndexed(stemp, sizeof(stemp), i, kEmulationOptions), - (i == EMUL_NONE) ? "" : (i == EMUL_WEMO) ? D_SINGLE_DEVICE : D_MULTI_DEVICE); + (i == EMUL_NONE) ? "" : (i == EMUL_WEMO) ? PSTR(D_SINGLE_DEVICE) : PSTR(D_MULTI_DEVICE)); } } WSContentSend_P(PSTR("

")); @@ -2086,7 +2086,7 @@ void HandleInformation(void) #ifdef ESP32 #ifdef USE_ETHERNET if (static_cast(EthernetLocalIP()) != 0) { - WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), EthernetHostname(), (Mdns.begun) ? ".local" : ""); + WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), EthernetHostname(), (Mdns.begun) ? PSTR(".local") : ""); WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), EthernetMacAddress().c_str()); WSContentSend_P(PSTR("}1" D_IP_ADDRESS " (eth)}2%s"), EthernetLocalIP().toString().c_str()); WSContentSend_P(PSTR("}1
}2
")); @@ -2096,7 +2096,7 @@ void HandleInformation(void) if (Settings.flag4.network_wifi) { int32_t rssi = WiFi.RSSI(); WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, HtmlEscape(SettingsText(SET_STASSID1 + Settings.sta_active)).c_str(), WifiGetRssiAsQuality(rssi), rssi); - WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), TasmotaGlobal.hostname, (Mdns.begun) ? ".local" : ""); + WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), TasmotaGlobal.hostname, (Mdns.begun) ? PSTR(".local") : ""); #if LWIP_IPV6 String ipv6_addr = WifiGetIPv6(); if (ipv6_addr != "") { @@ -2788,7 +2788,7 @@ bool CaptivePortal(void) if ((WifiIsInManagerMode()) && !ValidIpAddress(Webserver->hostHeader().c_str())) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); - Webserver->sendHeader(F("Location"), String("http://") + Webserver->client().localIP().toString(), true); + Webserver->sendHeader(F("Location"), String(F("http://")) + Webserver->client().localIP().toString(), true); WSSend(302, CT_PLAIN, ""); // Empty content inhibits Content-length header so we have to close the socket ourselves. Webserver->client().stop(); // Stop is needed because we sent no content length return true; diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index dcd21930f..15e99f352 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -1275,7 +1275,7 @@ void HandleMqttConfiguration(void) SettingsText(SET_MQTT_HOST), Settings.mqtt_port, #ifdef USE_MQTT_TLS - Mqtt.mqtt_tls ? " checked" : "", // SetOption102 - Enable MQTT TLS + Mqtt.mqtt_tls ? PSTR(" checked") : "", // SetOption102 - Enable MQTT TLS #endif // USE_MQTT_TLS Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, SettingsText(SET_MQTT_CLIENT)); WSContentSend_P(HTTP_FORM_MQTT2, diff --git a/tasmota/xdrv_09_timers.ino b/tasmota/xdrv_09_timers.ino index c40045a31..0f6292e13 100644 --- a/tasmota/xdrv_09_timers.ino +++ b/tasmota/xdrv_09_timers.ino @@ -305,7 +305,7 @@ void PrepShowTimer(uint32_t index) char days[8] = { 0 }; for (uint32_t i = 0; i < 7; i++) { uint8_t mask = 1 << i; - snprintf(days, sizeof(days), "%s%d", days, ((xtimer.days & mask) > 0)); + snprintf(days, sizeof(days), PSTR("%s%d"), days, ((xtimer.days & mask) > 0)); } char soutput[80]; @@ -857,7 +857,7 @@ void HandleTimerConfiguration(void) WSContentSend_P(HTTP_TIMER_SCRIPT5, MAX_TIMERS, TasmotaGlobal.devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT6, TasmotaGlobal.devices_present); WSContentSendStyle_P(HTTP_TIMER_STYLE, WebColor(COL_FORM)); - WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : ""); // CMND_TIMERS + WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? PSTR(" checked") : ""); // CMND_TIMERS for (uint32_t i = 0; i < MAX_TIMERS; i++) { WSContentSend_P(PSTR("%s%u"), (i > 0) ? "," : "", Settings.timer[i].data); } diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 198e58077..cd07098f8 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -4979,9 +4979,9 @@ void HandleScriptConfiguration(void) { #ifdef xSCRIPT_STRIP_COMMENTS uint16_t ssize = glob_script_mem.script_size; if (bitRead(Settings.rule_enabled, 1)) ssize *= 2; - WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",ssize); + WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? PSTR(" checked") : "",ssize); #else - WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",glob_script_mem.script_size); + WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? PSTR(" checked") : "",glob_script_mem.script_size); #endif // script is to large for WSContentSend_P diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 84e9ed508..97eafbcba 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -175,7 +175,7 @@ String HueBridgeId(void) String temp = WiFi.macAddress(); temp.replace(":", ""); String bridgeid = temp.substring(0, 6); - bridgeid += "FFFE"; + bridgeid += F("FFFE"); bridgeid += temp.substring(6); return bridgeid; // 5CCF7FFFFE139F3D } diff --git a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino b/tasmota/xdrv_23_zigbee_2a_devices_impl.ino index 80a69441c..ec7d773e4 100644 --- a/tasmota/xdrv_23_zigbee_2a_devices_impl.ino +++ b/tasmota/xdrv_23_zigbee_2a_devices_impl.ino @@ -681,9 +681,9 @@ void Z_Device::jsonAddConfig(Z_attribute_list & attr_list) const { for (auto & data_elt : data) { char key[8]; if (data_elt.validConfig()) { - snprintf_P(key, sizeof(key), "?%02X.%1X", data_elt.getEndpoint(), data_elt.getConfig()); + snprintf_P(key, sizeof(key), PSTR("?%02X.%1X"), data_elt.getEndpoint(), data_elt.getConfig()); } else { - snprintf_P(key, sizeof(key), "?%02X", data_elt.getEndpoint()); + snprintf_P(key, sizeof(key), PSTR("?%02X"), data_elt.getEndpoint()); } key[0] = Z_Data::DataTypeToChar(data_elt.getType()); arr_data.addStr(key); diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 5cfb19d06..fe4d219c0 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -1903,7 +1903,7 @@ void ZCLFrame::syntheticAqaraVibration(class Z_attribute_list &attr_list, class y = buf2.get16(2); x = buf2.get16(4); char temp[32]; - snprintf_P(temp, sizeof(temp), "[%i,%i,%i]", x, y, z); + snprintf_P(temp, sizeof(temp), PSTR("[%i,%i,%i]"), x, y, z); attr.setStrRaw(temp); // calculate angles float X = x; @@ -1912,7 +1912,7 @@ void ZCLFrame::syntheticAqaraVibration(class Z_attribute_list &attr_list, class int32_t Angle_X = 0.5f + atanf(X/sqrtf(z*z+y*y)) * f_180pi; int32_t Angle_Y = 0.5f + atanf(Y/sqrtf(x*x+z*z)) * f_180pi; int32_t Angle_Z = 0.5f + atanf(Z/sqrtf(x*x+y*y)) * f_180pi; - snprintf_P(temp, sizeof(temp), "[%i,%i,%i]", Angle_X, Angle_Y, Angle_Z); + snprintf_P(temp, sizeof(temp), PSTR("[%i,%i,%i]"), Angle_X, Angle_Y, Angle_Z); attr_list.addAttributePMEM(PSTR("AqaraAngles")).setStrRaw(temp); } } diff --git a/tasmota/xdrv_23_zigbee_7_5_map.ino b/tasmota/xdrv_23_zigbee_7_5_map.ino index 790720320..c9013b665 100644 --- a/tasmota/xdrv_23_zigbee_7_5_map.ino +++ b/tasmota/xdrv_23_zigbee_7_5_map.ino @@ -171,7 +171,7 @@ void Z_Mapper::dumpInternals(void) const { char hex[8]; snprintf(hex, sizeof(hex), PSTR("%d"), edge.lqi); - WSContentSend_P("{from:\"0x%04X\",to:\"0x%04X\",label:\"%s\",color:\"#%03X\"},", + WSContentSend_P(PSTR("{from:\"0x%04X\",to:\"0x%04X\",label:\"%s\",color:\"#%03X\"},"), edge.node_1, edge.node_2, (edge.lqi > 0) ? hex : "", lqi_color); } WSContentSend_P(PSTR("],")); diff --git a/tasmota/xdrv_23_zigbee_A_impl.ino b/tasmota/xdrv_23_zigbee_A_impl.ino index ce690c4db..ec9a454ac 100644 --- a/tasmota/xdrv_23_zigbee_A_impl.ino +++ b/tasmota/xdrv_23_zigbee_A_impl.ino @@ -2081,7 +2081,7 @@ void ZigbeeShow(bool json) if (zigbee.permit_end_time) { // PermitJoin in progress - WSContentSend_P(msg[ZB_WEB_PERMITJOIN_ACTIVE], D_ZIGBEE_PERMITJOIN_ACTIVE); + WSContentSend_P(msg[ZB_WEB_PERMITJOIN_ACTIVE], PSTR(D_ZIGBEE_PERMITJOIN_ACTIVE)); } #endif } diff --git a/tasmota/xdrv_28_pcf8574.ino b/tasmota/xdrv_28_pcf8574.ino index 58bb5239c..93e8d825d 100644 --- a/tasmota/xdrv_28_pcf8574.ino +++ b/tasmota/xdrv_28_pcf8574.ino @@ -168,7 +168,7 @@ void HandlePcf8574(void) WSContentStart_P(D_CONFIGURE_PCF8574); WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_I2C_PCF8574_1, (Settings.flag3.pcf8574_ports_inverted) ? " checked" : ""); // SetOption81 - Invert all ports on PCF8574 devices + WSContentSend_P(HTTP_FORM_I2C_PCF8574_1, (Settings.flag3.pcf8574_ports_inverted) ? PST(" checked") : ""); // SetOption81 - Invert all ports on PCF8574 devices WSContentSend_P(HTTP_TABLE100); for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { for (uint32_t idx2 = 0; idx2 < 8; idx2++) { // 8 ports on PCF8574 @@ -177,8 +177,8 @@ void HandlePcf8574(void) idx +1, idx2, idx2 + 8*idx, idx2 + 8*idx, - ((helper & Settings.pcf8574_config[idx]) >> idx2 == 0) ? " selected " : " ", - ((helper & Settings.pcf8574_config[idx]) >> idx2 == 1) ? " selected " : " " + ((helper & Settings.pcf8574_config[idx]) >> idx2 == 0) ? PSTR(" selected ") : " ", + ((helper & Settings.pcf8574_config[idx]) >> idx2 == 1) ? PSTR(" selected ") : " " ); } } diff --git a/tasmota/xdrv_50_filesystem.ino b/tasmota/xdrv_50_filesystem.ino index 56d4ecfd8..dc4e93ab5 100644 --- a/tasmota/xdrv_50_filesystem.ino +++ b/tasmota/xdrv_50_filesystem.ino @@ -502,7 +502,7 @@ void UfsDirectory(void) { WSContentSend_P(UFS_FORM_FILE_UPGc, WebColor(COL_TEXT), ts, fs); if (ufs_dir) { - WSContentSend_P(UFS_FORM_FILE_UPGc1, WiFi.localIP().toString().c_str(),ufs_dir == 1 ? 2:1, ufs_dir == 1 ? "SDCard":"FlashFS"); + WSContentSend_P(UFS_FORM_FILE_UPGc1, WiFi.localIP().toString().c_str(),ufs_dir == 1 ? 2:1, ufs_dir == 1 ? PSTR("SDCard"):PSTR("FlashFS")); } WSContentSend_P(UFS_FORM_FILE_UPGc2); From 35d9ac9042ce91f39fbf8c4af541752ce4f9d071 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Tue, 12 Jan 2021 19:48:28 +0100 Subject: [PATCH 36/71] Removed crash logger from BearSSL It is generally not useful since ESP8266 crashed before we reach this point --- tasmota/StackThunk_light.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tasmota/StackThunk_light.cpp b/tasmota/StackThunk_light.cpp index aea7ae438..8f8b9a23a 100644 --- a/tasmota/StackThunk_light.cpp +++ b/tasmota/StackThunk_light.cpp @@ -121,26 +121,26 @@ uint32_t stack_thunk_light_get_max_usage() } /* Print the stack from the first used 16-byte chunk to the top, decodable by the exception decoder */ -void stack_thunk_light_dump_stack() -{ - uint32_t *pos = stack_thunk_light_top; - while (pos < stack_thunk_light_ptr) { - if ((pos[0] != _stackPaint) || (pos[1] != _stackPaint) || (pos[2] != _stackPaint) || (pos[3] != _stackPaint)) - break; - pos += 4; - } - ets_printf(">>>stack>>>\n"); - while (pos < stack_thunk_light_ptr) { - ets_printf("%08x: %08x %08x %08x %08x\n", (int32_t)pos, pos[0], pos[1], pos[2], pos[3]); - pos += 4; - } - ets_printf("<<>>stack>>>\n"); +// while (pos < stack_thunk_light_ptr) { +// ets_printf("%08x: %08x %08x %08x %08x\n", (int32_t)pos, pos[0], pos[1], pos[2], pos[3]); +// pos += 4; +// } +// ets_printf("<< Date: Tue, 12 Jan 2021 23:04:42 +0100 Subject: [PATCH 37/71] SeeSoil State Machine Flavor --- tasmota/xsns_81_seesaw_soil.ino | 375 ++++++++++++++++++++------------ 1 file changed, 230 insertions(+), 145 deletions(-) diff --git a/tasmota/xsns_81_seesaw_soil.ino b/tasmota/xsns_81_seesaw_soil.ino index 1e37d6608..87c679a1a 100644 --- a/tasmota/xsns_81_seesaw_soil.ino +++ b/tasmota/xsns_81_seesaw_soil.ino @@ -22,16 +22,24 @@ #ifdef USE_SEESAW_SOIL /*********************************************************************************************\ - * SEESAW_SOIL - Capacitance & Temperature Sensor + * SEESAW_SOIL - Capacitice Soil Moisture & Temperature Sensor * * I2C Address: 0x36, 0x37, 0x38, 0x39 * - * Memory footprint: 1296 bytes flash, 64 bytes RAM + * This version of the driver replaces all delay loops by a state machine. So the number + * of instruction cycles consumed has been reduced dramatically. The sensors are reset, + * detected, commanded and read all at once. So the reading times won't increase with the + * number of sensors attached. The detection of sensors does not happen in FUNC_INIT any + * more. All i2c handling happens in the 50ms state machine. + * The memory footprint has suffered a little bit from this redesign, naturally. + * + * Memory footprint: 1444 bytes flash / 68 bytes RAM * * NOTE: #define SEESAW_SOIL_PUBLISH enables immediate MQTT on soil moisture change * otherwise the moisture value will only be emitted every TelePeriod * #define SEESAW_SOIL_RAW enables displaying analog capacitance input in the * web page for calibration purposes + * #define SEESAW_SOIL_PERSISTENT_NAMING to get sensor names indexed by i2c address \*********************************************************************************************/ #define XSNS_81 81 @@ -39,209 +47,281 @@ #include "Adafruit_seesaw.h" // we only use definitions, no code -//#define SEESAW_SOIL_RAW // enable raw readings -//#define SEESAW_SOIL_PUBLISH // enable immediate publish -//#define SEESAW_SOIL_PERSISTENT_NAMING // enable naming sensors by i2c address -//#define DEBUG_SEESAW_SOIL // enable debugging - #define SEESAW_SOIL_MAX_SENSORS 4 #define SEESAW_SOIL_START_ADDRESS 0x36 + // I2C state machine +#define STATE_IDLE 0x00 +#define STATE_RESET 0x01 +#define STATE_INIT 0x02 +#define STATE_DETECT 0x04 +#define STATE_COMMAND_TEMP 0x08 +#define STATE_READ_TEMP 0x10 +#define STATE_COMMAND_MOIST 0x20 +#define STATE_READ_MOIST 0x40 + // I2C commands +#define COMMAND_RESET 0x01 +#define COMMAND_ID 0x02 +#define COMMAND_TEMP 0x04 +#define COMMAND_MOIST 0x08 + // I2C delays +#define DELAY_DETECT 1 // ms delay before reading ID +#define DELAY_TEMP 1 // ms delay between command and reading +#define DELAY_MOIST 5 // ms delay between command and reading +#define DELAY_RESET 500 // ms delay after slave reset -const char SeeSoilName[] = "SeeSoil"; // spaces not allowed for Homeassistant integration/mqtt topics -uint8_t SeeSoilCount = 0; // global sensor count +// Convert capacitance into a moisture. +// From observation, a free air reading is at 320, immersed in tap water, reading is 1014 +// So let's make a scale that converts those (apparent) facts into a percentage +#define MAX_CAPACITANCE 1020.0f // subject to calibration +#define MIN_CAPACITANCE 320 // subject to calibration +#define CAP_TO_MOIST(c) ((max((int)(c),MIN_CAPACITANCE)-MIN_CAPACITANCE)/(MAX_CAPACITANCE-MIN_CAPACITANCE)*100) struct SEESAW_SOIL { - uint8_t address; // i2c address - float moisture; - float temperature; -#ifdef SEESAW_SOIL_RAW - uint16_t capacitance; // raw analog reading -#endif // SEESAW_SOIL_RAW -} SeeSoil[SEESAW_SOIL_MAX_SENSORS]; + const char name[8] = "SeeSoil"; // spaces not allowed for Homeassistant integration/mqtt topics + uint8_t count = 0; // global sensor count (0xFF = not initialized) + uint8_t state = STATE_IDLE; // current state + bool present = false; // driver active +} SeeSoil; -// Used to convert capacitance into a moisture. -// From observation, a free air reading is at 320 -// Immersed in tap water, reading is 1014 -// Appears to be a 10-bit device, readings close to 1020 -// So let's make a scale that converts those (apparent) facts into a percentage -#define MAX_CAPACITANCE 1020.0f // subject to calibration -#define MIN_CAPACITANCE 320 // subject to calibration -#define CAP_TO_MOIST(c) ((max((int)(c),MIN_CAPACITANCE)-MIN_CAPACITANCE)/(MAX_CAPACITANCE-MIN_CAPACITANCE)*100) +struct SEESAW_SOIL_SNS { + uint8_t address; // i2c address + float moisture; + float temperature; +#ifdef SEESAW_SOIL_RAW + uint16_t capacitance; // raw analog reading +#endif // SEESAW_SOIL_RAW +} SeeSoilSNS[SEESAW_SOIL_MAX_SENSORS]; /*********************************************************************************************\ * i2c routines \*********************************************************************************************/ -void SEESAW_SOILDetect(void) { - uint8_t buf; - uint32_t i, addr; - - for (i = 0; i < SEESAW_SOIL_MAX_SENSORS; i++) { - addr = SEESAW_SOIL_START_ADDRESS + i; - if ( ! I2cSetDevice(addr)) { continue; } - delay(1); - SEESAW_Reset(addr); // reset all seesaw MCUs at once +void seeSoilInit(void) { + for (int i = 0; i < SEESAW_SOIL_MAX_SENSORS; i++) { + int addr = SEESAW_SOIL_START_ADDRESS + i; + if ( ! I2cSetDevice(addr) ) { continue; } + seeSoilCommand(COMMAND_RESET); } - delay(500); // give MCUs time to boot - for (i = 0; i < SEESAW_SOIL_MAX_SENSORS; i++) { - addr = SEESAW_SOIL_START_ADDRESS + i; + SeeSoil.state = STATE_RESET; + SeeSoil.present = true; +} + +void seeSoilEvery50ms(void){ // i2c state machine + static uint32_t state_time; + + uint32_t time_diff = millis() - state_time; + + switch (SeeSoil.state) { + case STATE_RESET: // reset was just issued + SeeSoil.state = STATE_INIT; + break; + case STATE_INIT: // wait for sensors to settle + if (time_diff < DELAY_RESET) { return; } + seeSoilCommand(COMMAND_ID); // send hardware id commands + SeeSoil.state = STATE_DETECT; + break; + case STATE_DETECT: // detect sensors + if (time_diff < DELAY_DETECT) { return; } + seeSoilDetect(); + SeeSoil.state=STATE_COMMAND_TEMP; + break; + case STATE_COMMAND_TEMP: // send temperature commands + seeSoilCommand(COMMAND_TEMP); + SeeSoil.state = STATE_READ_TEMP; + break; + case STATE_READ_TEMP: + if (time_diff < DELAY_TEMP) { return; } + seeSoilRead(COMMAND_TEMP); // read temperature values + SeeSoil.state = STATE_COMMAND_MOIST; + break; + case STATE_COMMAND_MOIST: // send moisture commands + seeSoilCommand(COMMAND_MOIST); + SeeSoil.state = STATE_READ_MOIST; + break; + case STATE_READ_MOIST: + if (time_diff < DELAY_MOIST) { return; } + seeSoilRead(COMMAND_MOIST); // read moisture values + SeeSoil.state = STATE_COMMAND_TEMP; + break; + } + state_time = millis(); +} + +void seeSoilDetect(void) { // detect sensors + uint8_t buf; + + SeeSoil.count = 0; + SeeSoil.present = false; + for (int i = 0; i < SEESAW_SOIL_MAX_SENSORS; i++) { + uint32_t addr = SEESAW_SOIL_START_ADDRESS + i; if ( ! I2cSetDevice(addr)) { continue; } - if ( ! SEESAW_ValidRead(addr, SEESAW_STATUS_BASE, SEESAW_STATUS_HW_ID, &buf, 1, 0)) { - continue; - } - if (buf != SEESAW_HW_ID_CODE) { + if (1 != Wire.requestFrom((uint8_t) addr, (uint8_t) 1)) { continue; } + buf = (uint8_t) Wire.read(); + if (buf != SEESAW_HW_ID_CODE) { // check hardware id #ifdef DEBUG_SEESAW_SOIL AddLog_P(LOG_LEVEL_DEBUG, PSTR("SEE: HWID mismatch ADDR=%X, ID=%X"), addr, buf); #endif // DEBUG_SEESAW_SOIL continue; } - SeeSoil[SeeSoilCount].address = addr; - SeeSoil[SeeSoilCount].temperature = NAN; - SeeSoil[SeeSoilCount].moisture = NAN; - #ifdef SEESAW_SOIL_RAW - SeeSoil[SeeSoilCount].capacitance = 0; // raw analog reading -#endif // SEESAW_SOIL_RAW - I2cSetActiveFound(SeeSoil[SeeSoilCount].address, SeeSoilName); - SeeSoilCount++; - } -} - -float SEESAW_Temp(uint8_t addr) { // get temperature from seesaw at addr - uint8_t buf[4]; - - if (SEESAW_ValidRead(addr, SEESAW_STATUS_BASE, SEESAW_STATUS_TEMP, buf, 4, 1000)) { - int32_t ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | - ((uint32_t)buf[2] << 8) | (uint32_t)buf[3]; - return ConvertTemp((1.0 / (1UL << 16)) * ret); - } - return NAN; -} - -float SEESAW_Moist(uint8_t addr) { // get moisture from seesaw at addr - uint8_t buf[2]; - uint16_t ret; - int32_t tries = 2; - - while (tries--) { - delay(1); - if (SEESAW_ValidRead(addr, SEESAW_TOUCH_BASE, SEESAW_TOUCH_CHANNEL_OFFSET, buf, 2, 3000)) { - ret = ((uint16_t)buf[0] << 8) | buf[1]; + SeeSoilSNS[SeeSoil.count].address = addr; + SeeSoilSNS[SeeSoil.count].temperature = NAN; + SeeSoilSNS[SeeSoil.count].moisture = NAN; #ifdef SEESAW_SOIL_RAW - for (int i=0; i < SeeSoilCount; i++) { - if (SeeSoil[i].address == addr) { - SeeSoil[i].capacitance = ret; - break; - } - } + SeeSoilSNS[SeeSoil.count].capacitance = 0; // raw analog reading #endif // SEESAW_SOIL_RAW - if (ret != 0xFFFF) { return (float) CAP_TO_MOIST(ret); } + I2cSetActiveFound(SeeSoilSNS[SeeSoil.count].address, SeeSoil.name); + SeeSoil.count++; + SeeSoil.present = true; +#ifdef DEBUG_SEESAW_SOIL + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SEE: FOUND sensor %u at %02X"), i, addr); +#endif // DEBUG_SEESAW_SOIL + } +} + +void seeSoilCommand(uint32_t command) { // issue commands to sensors + uint8_t regLow; + uint8_t regHigh = SEESAW_STATUS_BASE; + uint32_t count = SeeSoil.count; + + switch (command) { + case COMMAND_RESET: + count = SEESAW_SOIL_MAX_SENSORS; + regLow = SEESAW_STATUS_SWRST; + break; + case COMMAND_ID: + count = SEESAW_SOIL_MAX_SENSORS; + regLow = SEESAW_STATUS_HW_ID; + break; + case COMMAND_TEMP: + regLow = SEESAW_STATUS_TEMP; + break; + case COMMAND_MOIST: + regHigh = SEESAW_TOUCH_BASE; + regLow = SEESAW_TOUCH_CHANNEL_OFFSET; + break; + default: +#ifdef DEBUG_SEESAW_SOIL + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SEE: ILL CMD:%02X"), command); +#endif // DEBUG_SEESAW_SOIL + return; + } + for (int i = 0; i < count; i++) { + uint32_t addr = (command & (COMMAND_RESET|COMMAND_ID)) ? SEESAW_SOIL_START_ADDRESS + i : SeeSoilSNS[i].address; + Wire.beginTransmission((uint8_t) addr); + Wire.write((uint8_t) regHigh); + Wire.write((uint8_t) regLow); + uint32_t err = Wire.endTransmission(); +#ifdef DEBUG_SEESAW_SOIL + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SEE: SNS=%u ADDR=%02X CMD=%02X ERR=%u"), i, addr, command, err); +#endif // DEBUG_SEESAW_SOIL } - } - return NAN; } -bool SEESAW_ValidRead(uint8_t addr, uint8_t regHigh, uint8_t regLow, // read from seesaw sensor - uint8_t *buf, uint8_t num, uint16_t delay) { +void seeSoilRead(uint32_t command) { // read values from sensors + uint8_t buf[4]; + uint32_t num; + int32_t ret; - Wire.beginTransmission((uint8_t) addr); - Wire.write((uint8_t) regHigh); - Wire.write((uint8_t) regLow); - int err = Wire.endTransmission(); - if (err) { return false; } - delayMicroseconds(delay); - if (num != Wire.requestFrom((uint8_t) addr, (uint8_t) num)) { - return false; - } - for (int i = 0; i < num; i++) { - buf[i] = (uint8_t) Wire.read(); - } - return true; -} + num = (command == COMMAND_TEMP) ? 4 : 2; // response size in bytes -bool SEESAW_Reset(uint8_t addr) { // init sensor MCU - Wire.beginTransmission((uint8_t) addr); - Wire.write((uint8_t) SEESAW_STATUS_BASE); - Wire.write((uint8_t) SEESAW_STATUS_SWRST); - return (Wire.endTransmission() == 0); + for (int i = 0; i < SeeSoil.count; i++) { // for all sensors + if (num != Wire.requestFrom((uint8_t) SeeSoilSNS[i].address, (uint8_t) num)) { continue; } + bzero(buf, sizeof(buf)); + for (int b = 0; b < num; b++) { + buf[b] = (uint8_t) Wire.read(); + } + if (command == COMMAND_TEMP) { + ret = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | + ((uint32_t)buf[2] << 8) | (uint32_t)buf[3]; + SeeSoilSNS[i].temperature = ConvertTemp((1.0 / (1UL << 16)) * ret); + } else { // COMMAND_MOIST + ret = (uint32_t)buf[0] << 8 | (uint32_t)buf[1]; + SeeSoilSNS[i].moisture = CAP_TO_MOIST(ret); +#ifdef SEESAW_SOIL_RAW + SeeSoilSNS[i].capacitance = ret; +#endif // SEESAW_SOIL_RAW + } +#ifdef DEBUG_SEESAW_SOIL + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SEE: READ #%u ADDR=%02X NUM=%u RET=%X"), i, SeeSoilSNS[i].address, num, ret); +#endif // DEBUG_SEESAW_SOIL + } } /*********************************************************************************************\ * JSON routines \*********************************************************************************************/ -void SEESAW_SOILEverySecond(void) { // update sensor values and publish if changed #ifdef SEESAW_SOIL_PUBLISH - uint32_t old_moist; -#endif // SEESAW_SOIL_PUBLISH +void seeSoilEverySecond(void) { // update sensor values and publish if changed + static uint16_t old_moist[SEESAW_SOIL_MAX_SENSORS]; + static bool firstcall = true; - for (int i = 0; i < SeeSoilCount; i++) { - SeeSoil[i].temperature = SEESAW_Temp(SeeSoil[i].address); -#ifdef SEESAW_SOIL_PUBLISH - old_moist = (uint32_t) SeeSoil[i].moisture; -#endif // SEESAW_SOIL_PUBLISH - SeeSoil[i].moisture = SEESAW_Moist(SeeSoil[i].address); -#ifdef SEESAW_SOIL_PUBLISH - if ((uint32_t) SeeSoil[i].moisture != old_moist) { - Response_P(PSTR("{")); // send values to MQTT & rules - SEESAW_SOILJson(i); - ResponseJsonEnd(); - MqttPublishTeleSensor(); + for (int i = 0; i < SeeSoil.count; i++) { + if (firstcall) { firstcall = false; } + else { + if ((uint32_t) SeeSoilSNS[i].moisture != old_moist[i]) { + Response_P(PSTR("{")); // send values to MQTT & rules + seeSoilJson(i); + ResponseJsonEnd(); + MqttPublishTeleSensor(); + } } -#endif // SEESAW_SOIL_PUBLISH + old_moist[i] = (uint32_t) SeeSoilSNS[i].moisture; } } +#endif // SEESAW_SOIL_PUBLISH -void SEESAW_SOILShow(bool json) { +void seeSoilShow(bool json) { char temperature[FLOATSZ]; - char sensor_name[sizeof(SeeSoilName) + 3]; + char sensor_name[sizeof(SeeSoil.name) + 3]; - for (uint32_t i = 0; i < SeeSoilCount; i++) { - dtostrfd(SeeSoil[i].temperature, Settings.flag2.temperature_resolution, temperature); - SEESAW_SOILName(i, sensor_name, sizeof(sensor_name)); + for (uint32_t i = 0; i < SeeSoil.count; i++) { + dtostrfd(SeeSoilSNS[i].temperature, Settings.flag2.temperature_resolution, temperature); + seeSoilName(i, sensor_name, sizeof(sensor_name)); if (json) { - ResponseAppend_P(PSTR(",")); // compose tele json - SEESAW_SOILJson(i); + ResponseAppend_P(PSTR(",")); // compose tele json + seeSoilJson(i); if (0 == TasmotaGlobal.tele_period) { #ifdef USE_DOMOTICZ - DomoticzTempHumPressureSensor(SeeSoil[i].temperature, SeeSoil[i].moisture, -42.0f); + DomoticzTempHumPressureSensor(SeeSoilSNS[i].temperature, SeeSoilSNS[i].moisture, -42.0f); #endif // USE_DOMOTICZ #ifdef USE_KNX - KnxSensor(KNX_TEMPERATURE, SeeSoil[i].temperature); - KnxSensor(KNX_HUMIDITY, SeeSoil[i].moisture); + KnxSensor(KNX_TEMPERATURE, SeeSoilSNS[i].temperature); + KnxSensor(KNX_HUMIDITY, SeeSoilSNS[i].moisture); #endif // USE_KNX } #ifdef USE_WEBSERVER } else { #ifdef SEESAW_SOIL_RAW - WSContentSend_PD(HTTP_SNS_ANALOG, sensor_name, 0, SeeSoil[i].capacitance); + WSContentSend_PD(HTTP_SNS_ANALOG, sensor_name, 0, SeeSoilSNS[i].capacitance); #endif // SEESAW_SOIL_RAW - WSContentSend_PD(HTTP_SNS_MOISTURE, sensor_name, (uint32_t) SeeSoil[i].moisture); + WSContentSend_PD(HTTP_SNS_MOISTURE, sensor_name, (uint32_t) SeeSoilSNS[i].moisture); WSContentSend_PD(HTTP_SNS_TEMP, sensor_name, temperature, TempUnit()); #endif // USE_WEBSERVER } } // for each sensor connected } -void SEESAW_SOILJson(int no) { // common json +void seeSoilJson(int no) { // common json char temperature[FLOATSZ]; - char sensor_name[sizeof(SeeSoilName) + 3]; + char sensor_name[sizeof(SeeSoil.name) + 3]; - SEESAW_SOILName(no, sensor_name, sizeof(sensor_name)); - dtostrfd(SeeSoil[no].temperature, Settings.flag2.temperature_resolution, temperature); + seeSoilName(no, sensor_name, sizeof(sensor_name)); + dtostrfd(SeeSoilSNS[no].temperature, Settings.flag2.temperature_resolution, temperature); ResponseAppend_P(PSTR ("\"%s\":{\"" D_JSON_ID "\":\"%02X\",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_MOISTURE "\":%u}"), - sensor_name, SeeSoil[no].address, temperature, (uint32_t) SeeSoil[no].moisture); + sensor_name, SeeSoilSNS[no].address, temperature, (uint32_t) SeeSoilSNS[no].moisture); } -void SEESAW_SOILName(int no, char *name, int len) // generates a sensor name +void seeSoilName(int no, char *name, int len) // generates a sensor name { #ifdef SEESAW_SOIL_PERSISTENT_NAMING - snprintf_P(name, len, PSTR("%s%c%02X"), SeeSoilName, IndexSeparator(), SeeSoil[no].address); + snprintf_P(name, len, PSTR("%s%c%02X"), SeeSoil.name, IndexSeparator(), SeeSoilSNS[no].address); #else - if (SeeSoilCount > 1) { - snprintf_P(name, len, PSTR("%s%c%u"), SeeSoilName, IndexSeparator(), no + 1); + if (SeeSoil.count > 1) { + snprintf_P(name, len, PSTR("%s%c%u"), SeeSoil.name, IndexSeparator(), no + 1); } else { - strlcpy(name, SeeSoilName, len); + strlcpy(name, SeeSoil.name, len); } #endif // SEESAW_SOIL_PERSISTENT_NAMING } @@ -256,19 +336,24 @@ bool Xsns81(uint8_t function) bool result = false; if (FUNC_INIT == function) { - SEESAW_SOILDetect(); + seeSoilInit(); } - else if (SeeSoilCount){ + else if (SeeSoil.present){ switch (function) { - case FUNC_EVERY_SECOND: - SEESAW_SOILEverySecond(); + case FUNC_EVERY_50_MSECOND: + seeSoilEvery50ms(); break; + #ifdef SEESAW_SOIL_PUBLISH + case FUNC_EVERY_SECOND: + seeSoilEverySecond(); + break; + #endif // SEESAW_SOIL_PUBLISH case FUNC_JSON_APPEND: - SEESAW_SOILShow(1); + seeSoilShow(1); break; #ifdef USE_WEBSERVER case FUNC_WEB_SENSOR: - SEESAW_SOILShow(0); + seeSoilShow(0); break; #endif // USE_WEBSERVER } From be531c9c816d0d2558284180fdf43018823a6446 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 13 Jan 2021 08:27:40 +0100 Subject: [PATCH 38/71] Fixing compile error --- tasmota/xdrv_28_pcf8574.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_28_pcf8574.ino b/tasmota/xdrv_28_pcf8574.ino index 93e8d825d..b79f3caa6 100644 --- a/tasmota/xdrv_28_pcf8574.ino +++ b/tasmota/xdrv_28_pcf8574.ino @@ -168,7 +168,7 @@ void HandlePcf8574(void) WSContentStart_P(D_CONFIGURE_PCF8574); WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_I2C_PCF8574_1, (Settings.flag3.pcf8574_ports_inverted) ? PST(" checked") : ""); // SetOption81 - Invert all ports on PCF8574 devices + WSContentSend_P(HTTP_FORM_I2C_PCF8574_1, (Settings.flag3.pcf8574_ports_inverted) ? PSTR(" checked") : ""); // SetOption81 - Invert all ports on PCF8574 devices WSContentSend_P(HTTP_TABLE100); for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { for (uint32_t idx2 = 0; idx2 < 8; idx2++) { // 8 ports on PCF8574 From a1c586b145428bf58156e148411cf1b69815c081 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 13 Jan 2021 09:26:31 +0100 Subject: [PATCH 39/71] Use ESP32 1.0.5rc6 for ESP32 stage --- platformio_override_sample.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 344faeea3..3b82447f2 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -144,11 +144,11 @@ lib_extra_dirs = ${library.lib_extra_dirs} [core32_stage] -platform_packages = framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#2452c1fb539246e47a715b74a3ad25b8a7ebbec7 +platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/arduino-esp32/releases/tag/1.0.5-rc6 platformio/tool-mklittlefs @ ~1.203.200522 build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} - -DESP32_STAGE=true + ;-DESP32_STAGE=true [library] lib_ldf_mode = chain+ From a34f75f44c440f5b68681b25fe5b99271d53fb2c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 13 Jan 2021 12:12:14 +0100 Subject: [PATCH 40/71] Fix locale File Management decimal point --- tasmota/xdrv_01_webserver.ino | 16 ++++++------- tasmota/xdrv_50_filesystem.ino | 44 ++++++---------------------------- 2 files changed, 15 insertions(+), 45 deletions(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index a86e8586b..d68cf9cd0 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2169,15 +2169,15 @@ void HandleInformation(void) #ifdef ESP8266 WSContentSend_P(PSTR("}1" D_FLASH_CHIP_ID "}20x%06X"), ESP.getFlashChipId()); #endif - WSContentSend_P(PSTR("}1" D_FLASH_CHIP_SIZE "}2%dkB"), ESP.getFlashChipRealSize() / 1024); - WSContentSend_P(PSTR("}1" D_PROGRAM_FLASH_SIZE "}2%dkB"), ESP.getFlashChipSize() / 1024); - WSContentSend_P(PSTR("}1" D_PROGRAM_SIZE "}2%dkB"), ESP_getSketchSize() / 1024); - WSContentSend_P(PSTR("}1" D_FREE_PROGRAM_SPACE "}2%dkB"), ESP.getFreeSketchSpace() / 1024); - WSContentSend_P(PSTR("}1" D_FREE_MEMORY "}2%dkB"), freeMem / 1024); + WSContentSend_P(PSTR("}1" D_FLASH_CHIP_SIZE "}2%d kB"), ESP.getFlashChipRealSize() / 1024); + WSContentSend_P(PSTR("}1" D_PROGRAM_FLASH_SIZE "}2%d kB"), ESP.getFlashChipSize() / 1024); + WSContentSend_P(PSTR("}1" D_PROGRAM_SIZE "}2%d kB"), ESP_getSketchSize() / 1024); + WSContentSend_P(PSTR("}1" D_FREE_PROGRAM_SPACE "}2%d kB"), ESP.getFreeSketchSpace() / 1024); + WSContentSend_P(PSTR("}1" D_FREE_MEMORY "}2%d kB"), freeMem / 1024); #ifdef ESP32 if (psramFound()) { - WSContentSend_P(PSTR("}1" D_PSR_MAX_MEMORY "}2%dkB"), ESP.getPsramSize() / 1024); - WSContentSend_P(PSTR("}1" D_PSR_FREE_MEMORY "}2%dkB"), ESP.getFreePsram() / 1024); + WSContentSend_P(PSTR("}1" D_PSR_MAX_MEMORY "}2%d kB"), ESP.getPsramSize() / 1024); + WSContentSend_P(PSTR("}1" D_PSR_FREE_MEMORY "}2%d kB"), ESP.getFreePsram() / 1024); } #endif WSContentSend_P(PSTR("")); @@ -2522,7 +2522,7 @@ void HandleUploadLoop(void) { return; } if (upload.totalSize && !(upload.totalSize % 102400)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "Progress %dkB"), upload.totalSize / 1024); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "Progress %d kB"), upload.totalSize / 1024); } } diff --git a/tasmota/xdrv_50_filesystem.ino b/tasmota/xdrv_50_filesystem.ino index dc4e93ab5..8066a9b93 100644 --- a/tasmota/xdrv_50_filesystem.ino +++ b/tasmota/xdrv_50_filesystem.ino @@ -274,32 +274,6 @@ uint8_t UfsReject(char *name) { return 0; } -// Format number with thousand marker - Not international as '.' is decimal on most countries -void UfsForm1000(uint32_t number, char *dp, char sc) { - char str[32]; - sprintf(str, "%d", number); - char *sp = str; - uint32_t inum = strlen(sp)/3; - uint32_t fnum = strlen(sp)%3; - if (!fnum) { inum--; } - for (uint32_t count = 0; count <= inum; count++) { - if (fnum) { - memcpy(dp, sp, fnum); - dp += fnum; - sp += fnum; - fnum = 0; - } else { - memcpy(dp, sp, 3); - dp += 3; - sp += 3; - } - if (count != inum) { - *dp++ = sc; - } - } - *dp = 0; -} - /*********************************************************************************************\ * Tfs low level functions \*********************************************************************************************/ @@ -418,7 +392,7 @@ const char UFS_FORM_FILE_UPLOAD[] PROGMEM = "
" "
 " D_MANAGE_FILE_SYSTEM " "; const char UFS_FORM_FILE_UPGc[] PROGMEM = - "
" D_FS_SIZE " %s kB - " D_FS_FREE " %s kB"; + "
" D_FS_SIZE " %s MB - " D_FS_FREE " %s MB"; const char UFS_FORM_FILE_UPGc1[] PROGMEM = "   %s"; @@ -451,7 +425,6 @@ const char UFS_FORM_SDC_HREFdel[] PROGMEM = "🔥"; // 🔥 #endif // GUI_TRASH_FILE - void UfsDirectory(void) { if (!HttpCheckPriviledgedAccess()) { return; } @@ -461,8 +434,6 @@ void UfsDirectory(void) { strcpy(ufs_path, "/"); - - if (Webserver->hasArg("download")) { String stmp = Webserver->arg("download"); char *cp = (char*)stmp.c_str(); @@ -494,15 +465,14 @@ void UfsDirectory(void) { WSContentSendStyle(); WSContentSend_P(UFS_FORM_FILE_UPLOAD); - char ts[16]; - char fs[16]; - UfsForm1000(UfsInfo(0, ufs_dir == 2 ? 1:0), ts, '.'); - UfsForm1000(UfsInfo(1, ufs_dir == 2 ? 1:0), fs, '.'); - - WSContentSend_P(UFS_FORM_FILE_UPGc, WebColor(COL_TEXT), ts, fs); + char ts[FLOATSZ]; + dtostrfd((float)UfsInfo(0, ufs_dir == 2 ? 1:0) / 1000, 3, ts); + char fs[FLOATSZ]; + dtostrfd((float)UfsInfo(1, ufs_dir == 2 ? 1:0) / 1000, 3, fs); + WSContentSend_PD(UFS_FORM_FILE_UPGc, WebColor(COL_TEXT), ts, fs); if (ufs_dir) { - WSContentSend_P(UFS_FORM_FILE_UPGc1, WiFi.localIP().toString().c_str(),ufs_dir == 1 ? 2:1, ufs_dir == 1 ? PSTR("SDCard"):PSTR("FlashFS")); + WSContentSend_P(UFS_FORM_FILE_UPGc1, WiFi.localIP().toString().c_str(), (ufs_dir == 1)?2:1, (ufs_dir == 1)?PSTR("SDCard"):PSTR("FlashFS")); } WSContentSend_P(UFS_FORM_FILE_UPGc2); From 861c76bacaf294a88dc10eb185cec5885f7616a9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 13 Jan 2021 12:38:35 +0100 Subject: [PATCH 41/71] Fix ESP32 reset 5,6 regression from yesterday --- tasmota/support_esp32.ino | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tasmota/support_esp32.ino b/tasmota/support_esp32.ino index d56040b86..7bbad6468 100644 --- a/tasmota/support_esp32.ino +++ b/tasmota/support_esp32.ino @@ -144,24 +144,20 @@ void SettingsErase(uint8_t type) { // main - Tasmota Settings data int32_t r1, r2, r3; switch (type) { - case 0: // Reset 2, 5, 6 = Erase all flash from program end to end of physical flash + case 0: // Reset 2 = Erase all flash from program end to end of physical flash + case 2: // Reset 5, 6 = Erase all flash from program end to end of physical flash excluding filesystem // nvs_flash_erase(); // Erase RTC, PHY, sta.mac, ap.sndchan, ap.mac, Tasmota etc. r1 = NvmErase("qpc"); r2 = NvmErase("main"); r3 = TfsDeleteFile(TASM_FILE_SETTINGS); AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " Tasmota data (%d,%d,%d)"), r1, r2, r3); break; - case 1: case 4: // Reset 3 or WIFI_FORCE_RF_CAL_ERASE = SDK parameter area + case 1: // Reset 3 = SDK parameter area + case 4: // WIFI_FORCE_RF_CAL_ERASE = SDK parameter area r1 = esp_phy_erase_cal_data_in_nvs(); // r1 = NvmErase("cal_data"); AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " PHY data (%d)"), r1); break; - case 2: // Not used = QPC and Tasmota parameter area (0x0F3xxx - 0x0FBFFF) - r1 = NvmErase("qpc"); - r2 = NvmErase("main"); - r3 = TfsDeleteFile(TASM_FILE_SETTINGS); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " Tasmota data (%d,%d,%d)"), r1, r2, r3); - break; case 3: // QPC Reached = QPC, Tasmota and SDK parameter area (0x0F3xxx - 0x0FFFFF) // nvs_flash_erase(); // Erase RTC, PHY, sta.mac, ap.sndchan, ap.mac, Tasmota etc. r1 = NvmErase("qpc"); From 8c46e439ca161ed48ddae701f37c2d4d107f3c51 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 13 Jan 2021 13:49:33 +0100 Subject: [PATCH 42/71] Support for download_fs.py --- platformio.ini | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index e76901e33..a95530335 100644 --- a/platformio.ini +++ b/platformio.ini @@ -67,6 +67,7 @@ default_envs = ${build_envs.default_envs} framework = arduino board = esp01_1m board_build.filesystem = littlefs +custom_unpack_dir = unpacked_esp8266_littlefs board_build.flash_mode = dout board_build.ldscript = eagle.flash.1m.ld @@ -77,7 +78,8 @@ build_flags = ${core.build_flags} board_build.f_cpu = 80000000L board_build.f_flash = 40000000L -monitor_speed = 115200 +monitor_speed = 74880 +monitor_port = COM5 upload_speed = 115200 ; *** Upload Serial reset method for Wemos and NodeMCU upload_resetmethod = nodemcu @@ -99,6 +101,7 @@ extra_scripts = pio-tools/strip-floats.py pio-tools/name-firmware.py pio-tools/gzip-firmware.py pio-tools/override_copy.py + pio-tools/download_fs.py [esp_defaults] ; *** remove undesired all warnings From 988ca925dd4343934778ac0b5143bd142517e87c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 13 Jan 2021 13:51:03 +0100 Subject: [PATCH 43/71] PIO file system downloader script --- pio-tools/download_fs.py | 329 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 pio-tools/download_fs.py diff --git a/pio-tools/download_fs.py b/pio-tools/download_fs.py new file mode 100644 index 000000000..ed6426cc7 --- /dev/null +++ b/pio-tools/download_fs.py @@ -0,0 +1,329 @@ +# Written by Maximilian Gerhardt +# 29th December 2020 +# License: Apache +# Expanded from functionality provided by PlatformIO's espressif32 and espressif8266 platforms, credited below. +# This script provides functions to download the filesystem (SPIFFS or LittleFS) from a running ESP32 / ESP8266 +# over the serial bootloader using esptool.py, and mklittlefs / mkspiffs for extracting. +# run by either using the VSCode task "Custom" -> "Download Filesystem" +# or by doing 'pio run -t downloadfs' (with optional '-e ') from the commandline. +# output will be saved, by default, in the "unpacked_fs" of the project. +# this folder can be changed by writing 'custom_unpack_dir = some_other_dir' in the corresponding platformio.ini +# environment. +import re +import sys +from os.path import isfile, join +from enum import Enum +import typing +from platformio.builder.tools.pioupload import AutodetectUploadPort +import os +import subprocess +import shutil + +Import("env") +platform = env.PioPlatform() +board = env.BoardConfig() +mcu = board.get("build.mcu", "esp32") +# needed for later +AutodetectUploadPort(env) + +class FSType(Enum): + SPIFFS="spiffs" + LITTLEFS="littlefs" + FATFS="fatfs" + +class FSInfo: + def __init__(self, fs_type, start, length, page_size, block_size): + self.fs_type = fs_type + self.start = start + self.length = length + self.page_size = page_size + self.block_size = block_size + def __repr__(self): + return f"FS type {self.fs_type} Start {hex(self.start)} Len {self.length} Page size {self.page_size} Block size {self.block_size}" + # extract command supposed to be implemented by subclasses + def get_extract_cmd(self): + raise NotImplementedError() + +class LittleFSInfo(FSInfo): + def __init__(self, start, length, page_size, block_size): + if env["PIOPLATFORM"] == "espressif32": + #for ESP32: retrieve and evaluate, e.g. to mkspiffs_espressif32_arduino + self.tool = env.subst(env["MKSPIFFSTOOL"]) + else: + self.tool = env["MKFSTOOL"] # from mkspiffs package + self.tool = join(platform.get_package_dir("tool-mklittlefs"), self.tool) + super().__init__(FSType.LITTLEFS, start, length, page_size, block_size) + def __repr__(self): + return f"FS type {self.fs_type} Start {hex(self.start)} Len {self.length} Page size {self.page_size} Block size {self.block_size} Tool: {self.tool}" + def get_extract_cmd(self, input_file, output_dir): + return f'"{self.tool}" -b {self.block_size} -p {self.page_size} --unpack "{output_dir}" "{input_file}"' + + +class SPIFFSInfo(FSInfo): + def __init__(self, start, length, page_size, block_size): + if env["PIOPLATFORM"] == "espressif32": + #for ESP32: retrieve and evaluate, e.g. to mkspiffs_espressif32_arduino + self.tool = env.subst(env["MKSPIFFSTOOL"]) + else: + self.tool = env["MKFSTOOL"] # from mkspiffs package + self.tool = join(platform.get_package_dir("tool-mkspiffs"), self.tool) + super().__init__(FSType.SPIFFS, start, length, page_size, block_size) + def __repr__(self): + return f"FS type {self.fs_type} Start {hex(self.start)} Len {self.length} Page size {self.page_size} Block size {self.block_size} Tool: {self.tool}" + def get_extract_cmd(self, input_file, output_dir): + return f'"{self.tool}" -b {self.block_size} -p {self.page_size} --unpack "{output_dir}" "{input_file}"' + +# SPIFFS helpers copied from ESP32, https://github.com/platformio/platform-espressif32/blob/develop/builder/main.py +# Copyright 2014-present PlatformIO +# Licensed under the Apache License, Version 2.0 (the "License"); + +def _parse_size(value): + if isinstance(value, int): + return value + elif value.isdigit(): + return int(value) + elif value.startswith("0x"): + return int(value, 16) + elif value[-1].upper() in ("K", "M"): + base = 1024 if value[-1].upper() == "K" else 1024 * 1024 + return int(value[:-1]) * base + return value + +def _parse_partitions(env): + partitions_csv = env.subst("$PARTITIONS_TABLE_CSV") + if not isfile(partitions_csv): + sys.stderr.write("Could not find the file %s with partitions " + "table.\n" % partitions_csv) + env.Exit(1) + return + + result = [] + next_offset = 0 + with open(partitions_csv) as fp: + for line in fp.readlines(): + line = line.strip() + if not line or line.startswith("#"): + continue + tokens = [t.strip() for t in line.split(",")] + if len(tokens) < 5: + continue + partition = { + "name": tokens[0], + "type": tokens[1], + "subtype": tokens[2], + "offset": tokens[3] or next_offset, + "size": tokens[4], + "flags": tokens[5] if len(tokens) > 5 else None + } + result.append(partition) + next_offset = (_parse_size(partition['offset']) + + _parse_size(partition['size'])) + return result + +def esp32_fetch_spiffs_size(env): + spiffs = None + for p in _parse_partitions(env): + if p['type'] == "data" and p['subtype'] == "spiffs": + spiffs = p + if not spiffs: + sys.stderr.write( + env.subst("Could not find the `spiffs` section in the partitions " + "table $PARTITIONS_TABLE_CSV\n")) + env.Exit(1) + return + env["SPIFFS_START"] = _parse_size(spiffs['offset']) + env["SPIFFS_SIZE"] = _parse_size(spiffs['size']) + env["SPIFFS_PAGE"] = int("0x100", 16) + env["SPIFFS_BLOCK"] = int("0x1000", 16) + +## FS helpers for ESP8266 +# copied from https://github.com/platformio/platform-espressif8266/blob/develop/builder/main.py +# Copyright 2014-present PlatformIO +# Licensed under the Apache License, Version 2.0 (the "License"); + +def _get_board_f_flash(env): + frequency = env.subst("$BOARD_F_FLASH") + frequency = str(frequency).replace("L", "") + return int(int(frequency) / 1000000) + +def _parse_ld_sizes(ldscript_path): + assert ldscript_path + result = {} + # get flash size from board's manifest + result['flash_size'] = int(env.BoardConfig().get("upload.maximum_size", 0)) + # get flash size from LD script path + match = re.search(r"\.flash\.(\d+[mk]).*\.ld", ldscript_path) + if match: + result['flash_size'] = _parse_size(match.group(1)) + + appsize_re = re.compile( + r"irom0_0_seg\s*:.+len\s*=\s*(0x[\da-f]+)", flags=re.I) + filesystem_re = re.compile( + r"PROVIDE\s*\(\s*_%s_(\w+)\s*=\s*(0x[\da-f]+)\s*\)" % "FS" + if "arduino" in env.subst("$PIOFRAMEWORK") + else "SPIFFS", + flags=re.I, + ) + with open(ldscript_path) as fp: + for line in fp.readlines(): + line = line.strip() + if not line or line.startswith("/*"): + continue + match = appsize_re.search(line) + if match: + result['app_size'] = _parse_size(match.group(1)) + continue + match = filesystem_re.search(line) + if match: + result['fs_%s' % match.group(1)] = _parse_size( + match.group(2)) + return result + +def _get_flash_size(env): + ldsizes = _parse_ld_sizes(env.GetActualLDScript()) + if ldsizes['flash_size'] < 1048576: + return "%dK" % (ldsizes['flash_size'] / 1024) + return "%dM" % (ldsizes['flash_size'] / 1048576) + +def esp8266_fetch_fs_size(env): + ldsizes = _parse_ld_sizes(env.GetActualLDScript()) + for key in ldsizes: + if key.startswith("fs_"): + env[key.upper()] = ldsizes[key] + + assert all([ + k in env + for k in ["FS_START", "FS_END", "FS_PAGE", "FS_BLOCK"] + ]) + + # esptool flash starts from 0 + for k in ("FS_START", "FS_END"): + _value = 0 + if env[k] < 0x40300000: + _value = env[k] & 0xFFFFF + elif env[k] < 0x411FB000: + _value = env[k] & 0xFFFFFF + _value -= 0x200000 # correction + else: + _value = env[k] & 0xFFFFFF + _value += 0xE00000 # correction + + env[k] = _value + +def esp8266_get_esptoolpy_reset_flags(resetmethod): + # no dtr, no_sync + resets = ("no_reset_no_sync", "soft_reset") + if resetmethod == "nodemcu": + # dtr + resets = ("default_reset", "hard_reset") + elif resetmethod == "ck": + # no dtr + resets = ("no_reset", "soft_reset") + + return ["--before", resets[0], "--after", resets[1]] + +## Script interface functions + +def get_fs_type_start_and_length(): + platform = env["PIOPLATFORM"] + if platform == "espressif32": + print("Retrieving filesystem info for ESP32. Assuming SPIFFS.") + print("Partition file: " + str(env.subst("$PARTITIONS_TABLE_CSV"))) + esp32_fetch_spiffs_size(env) + return SPIFFSInfo(env["SPIFFS_START"], env["SPIFFS_SIZE"], env["SPIFFS_PAGE"], env["SPIFFS_BLOCK"]) + elif platform == "espressif8266": + print("Retrieving filesystem info for ESP8266.") + filesystem = board.get("build.filesystem", "spiffs") + if filesystem not in ("spiffs", "littlefs"): + print("Unrecognized board_build.filesystem option '" + str(filesystem) + "'.") + env.Exit(1) + # fetching sizes is the same for all filesystems + esp8266_fetch_fs_size(env) + print("FS_START: " + hex(env["FS_START"])) + print("FS_END: " + hex(env["FS_END"])) + print("FS_PAGE: " + hex(env["FS_PAGE"])) + print("FS_BLOCK: " + hex(env["FS_BLOCK"])) + if filesystem == "spiffs": + print("Recognized SPIFFS filesystem.") + return SPIFFSInfo(env["FS_START"], env["FS_END"] - env["FS_START"], env["FS_PAGE"], env["FS_BLOCK"]) + elif filesystem == "littlefs": + print("Recognized LittleFS filesystem.") + return LittleFSInfo(env["FS_START"], env["FS_END"] - env["FS_START"], env["FS_PAGE"], env["FS_BLOCK"]) + else: + print("Unrecongized configuration.") + pass + +def download_fs(fs_info: FSInfo): + esptoolpy = join(platform.get_package_dir("tool-esptoolpy") or "", "esptool.py") + fs_file = join(env["PROJECT_DIR"], f"downloaded_fs_{hex(fs_info.start)}_{hex(fs_info.length)}.bin") + esptoolpy_flags = [ + "--chip", mcu, + "--port", '"' + env.subst("$UPLOAD_PORT") + '"', + "--baud", env.subst("$UPLOAD_SPEED"), + "--before", "default_reset", + "--after", "hard_reset", + "read_flash", + hex(fs_info.start), + hex(fs_info.length), + '"' + fs_file + '"' + ] + esptoolpy_cmd = '"' + env["PYTHONEXE"]+ '"' + ' "' + esptoolpy + '" ' + " ".join(esptoolpy_flags) + print("Executing flash download command.") + print(esptoolpy_cmd) + try: + returncode = subprocess.call(esptoolpy_cmd, shell=False) + print("Downloaded filesystem binary.") + return (True, fs_file) + except subprocess.CalledProcessError as exc: + print("Downloading failed with " + str(exc)) + return (False, "") + +def unpack_fs(fs_info: FSInfo, downloaded_file: str): + # by writing custom_unpack_dir = some_dir in the platformio.ini, one can + # control the unpack directory + unpack_dir = env.GetProjectOption("custom_unpack_dir", "unpacked_fs") + #unpack_dir = "unpacked_fs" + try: + if os.path.exists(unpack_dir): + shutil.rmtree(unpack_dir) + except Exception as exc: + print("Exception while attempting to remove the folder '" + str(unpack_dir) + "': " + str(exc)) + if not os.path.exists(unpack_dir): + os.makedirs(unpack_dir) + + cmd = fs_info.get_extract_cmd(downloaded_file, unpack_dir) + print("Executing extraction command: " + str(cmd)) + try: + returncode = subprocess.call(cmd, shell=False) + print("Unpacked filesystem.") + return (True, unpack_dir) + except subprocess.CalledProcessError as exc: + print("Unpacking filesystem failed with " + str(exc)) + return (False, "") + +def display_fs(extracted_dir): + # extract command already nicely lists all extracted files. + # no need to display that ourselves. just display a summary + file_count = sum([len(files) for r, d, files in os.walk(extracted_dir)]) + print("Extracted " + str(file_count) + " file(s) from filesystem.") + +def command_download_fs(*args, **kwargs): + print("Entrypoint") + #print(env.Dump()) + info = get_fs_type_start_and_length() + print("Parsed FS info: " + str(info)) + download_ok, downloaded_file = download_fs(info) + print("Download was okay: " + str(download_ok) + ". File at: "+ str(downloaded_file)) + unpack_ok, unpacked_dir = unpack_fs(info, downloaded_file) + if unpack_ok is True: + display_fs(unpacked_dir) + +env.AddCustomTarget( + name="downloadfs", + dependencies=None, + actions=[ + command_download_fs + ], + title="Download Filesystem", + description="Downloads and displays files stored in the target ESP32/ESP8266" +) \ No newline at end of file From a21acebdb447ec29a2a720df133ae4012ca3e846 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 13 Jan 2021 13:51:49 +0100 Subject: [PATCH 44/71] Add support for Last Known Good Settings --- tasmota/settings.ino | 16 ++++++++++++---- tasmota/support_tasmota.ino | 9 +++++++++ tasmota/tasmota_globals.h | 5 +++-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index d61f66743..b2d438df6 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -540,7 +540,7 @@ void SettingsSave(uint8_t rotate) #ifdef ESP8266 #ifdef USE_UFILESYS TfsSaveFile(TASM_FILE_SETTINGS, (const uint8_t*)&Settings, sizeof(Settings)); -#endif +#endif // USE_UFILESYS if (ESP.flashEraseSector(settings_location)) { ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); } @@ -578,7 +578,7 @@ void SettingsLoad(void) { flash_location = 1; slot = 0; } -#endif +#endif // USE_UFILESYS while (slot <= max_slots) { // Read all config pages in search of valid and latest if (slot > 0) { flash_location = (1 == slot) ? FLASH_EEPROM_START : (2 == slot) ? SETTINGS_LOCATION : flash_location -1; @@ -602,7 +602,7 @@ void SettingsLoad(void) { TfsLoadFile(TASM_FILE_SETTINGS, (uint8_t*)&Settings, sizeof(Settings)); AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG "Loaded from File, " D_COUNT " %lu"), Settings.save_flag); } else -#endif +#endif // USE_UFILESYS { ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); @@ -617,7 +617,15 @@ void SettingsLoad(void) { #ifndef FIRMWARE_MINIMAL if ((0 == settings_location) || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { // Init defaults if cfg_holder differs from user settings in my_user_config.h - SettingsDefault(); +#ifdef USE_UFILESYS + if (TfsLoadFile(TASM_FILE_SETTINGS_LKG, (uint8_t*)&Settings, sizeof(Settings)) && (Settings.cfg_crc32 == GetSettingsCrc32())) { + settings_location = 1; + AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG "Loaded from LKG File, " D_COUNT " %lu"), Settings.save_flag); + } else +#endif // USE_UFILESYS + { + SettingsDefault(); + } } settings_crc32 = GetSettingsCrc32(); #endif // FIRMWARE_MINIMAL diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index a6e0b2104..3ac17a490 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -886,6 +886,15 @@ void PerformEverySecond(void) ESP_getSketchSize(); // Init sketchsize as it can take up to 2 seconds } #endif + +#ifdef USE_UFILESYS + static bool settings_lkg = false; // Settings saved as Last Known Good + // Copy Settings as Last Known Good if no changes have been saved since 30 minutes + if (!settings_lkg && (UtcTime() > START_VALID_TIME) && (Settings.cfg_timestamp < UtcTime() - (30 * 60))) { + TfsSaveFile(TASM_FILE_SETTINGS_LKG, (const uint8_t*)&Settings, sizeof(Settings)); + settings_lkg = true; + } +#endif } /*-------------------------------------------------------------------------------------------*\ diff --git a/tasmota/tasmota_globals.h b/tasmota/tasmota_globals.h index 330a1a87e..4524410dd 100644 --- a/tasmota/tasmota_globals.h +++ b/tasmota/tasmota_globals.h @@ -225,8 +225,9 @@ const uint16_t LOG_BUFFER_SIZE = 4000; // Max number of characters in lo #error "Arduino ESP8266 Core versions before 2.7.1 are not supported" #endif -#define TASM_FILE_SETTINGS "/.settings" -#define TASM_FILE_ZIGBEE "/zb" +#define TASM_FILE_SETTINGS "/.settings" // Settings binary blob +#define TASM_FILE_SETTINGS_LKG "/.settings.lkg" // Last Known Good Settings binary blob +#define TASM_FILE_ZIGBEE "/zb" // Zigbee settings blob as used by CC2530 on ESP32 #ifndef MQTT_MAX_PACKET_SIZE #define MQTT_MAX_PACKET_SIZE 1200 // Bytes From 669aa6a45ac6e19bc9b184e8c569ee418ddacd8b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 13 Jan 2021 13:52:32 +0100 Subject: [PATCH 45/71] fix copy&paste --- platformio_override_sample.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 3b82447f2..d82b7f45d 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -144,7 +144,7 @@ lib_extra_dirs = ${library.lib_extra_dirs} [core32_stage] -platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/arduino-esp32/releases/tag/1.0.5-rc6 +platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/arduino-esp32/releases/download/1.0.5-rc6/esp32-1.0.5-rc6.zip platformio/tool-mklittlefs @ ~1.203.200522 build_unflags = ${esp32_defaults.build_unflags} build_flags = ${esp32_defaults.build_flags} From 3810251658a29c41856e409f000764309e32a621 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 13 Jan 2021 14:18:39 +0100 Subject: [PATCH 46/71] Update support_esptool.ino --- tasmota/support_esptool.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/support_esptool.ino b/tasmota/support_esptool.ino index 6551c7912..a066838af 100644 --- a/tasmota/support_esptool.ino +++ b/tasmota/support_esptool.ino @@ -95,7 +95,7 @@ bool EsptoolEraseSector(uint32_t sector) void EsptoolErase(uint32_t start_sector, uint32_t end_sector) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%06X to 0x%06X"), start_sector * SPI_FLASH_SEC_SIZE, (end_sector * SPI_FLASH_SEC_SIZE) -1); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%08X to 0x%08X"), start_sector * SPI_FLASH_SEC_SIZE, (end_sector * SPI_FLASH_SEC_SIZE) -1); int next_erase_sector = start_sector; int remaining_erase_sector = end_sector - start_sector; From 40007bbae991366f8b6f0b89ffd81eaff4801295 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 13 Jan 2021 15:54:43 +0100 Subject: [PATCH 47/71] Add WIFI_NONE_SLEEP when sleep = 0 and SO60 = 0 --- tasmota/support_wifi.ino | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 845e115e6..95380cd74 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -153,11 +153,22 @@ void WiFiSetSleepMode(void) */ // Sleep explanation: https://github.com/esp8266/Arduino/blob/3f0c601cfe81439ce17e9bd5d28994a7ed144482/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp#L255 +/* if (TasmotaGlobal.sleep && Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times } else { WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default) } +*/ + if (TasmotaGlobal.sleep && Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep + WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times + } else { + if (0 == TasmotaGlobal.sleep) { + WiFi.setSleepMode(WIFI_NONE_SLEEP); // Disable sleep + } else { + WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Sleep (Esp8288/Arduino core and sdk default) + } + } WifiSetOutputPower(); } From fa4326b6b0eac4a119577f5d2bb1c0d0af147c98 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 13 Jan 2021 16:57:04 +0100 Subject: [PATCH 48/71] Fix ESP32 compilation --- tasmota/support_wifi.ino | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 95380cd74..b281b0c51 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -163,9 +163,12 @@ void WiFiSetSleepMode(void) if (TasmotaGlobal.sleep && Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times } else { +#ifdef ESP8266 if (0 == TasmotaGlobal.sleep) { WiFi.setSleepMode(WIFI_NONE_SLEEP); // Disable sleep - } else { + } else +#endif + { WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Sleep (Esp8288/Arduino core and sdk default) } } From fdbd1dcc0ab98042c6d4dbc14308450d29eefa19 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:03:01 +0100 Subject: [PATCH 49/71] Changed command ``Sleep 0`` Changed command ``Sleep 0`` removes any sleep from wifi modem except when ESP32 BLE is active --- CHANGELOG.md | 1 + RELEASENOTES.md | 1 + tasmota/support_command.ino | 5 ++-- tasmota/support_wifi.ino | 15 +++++------ tasmota/tasmota.ino | 1 + tasmota/xsns_52_ibeacon.ino | 11 +++----- tasmota/xsns_62_MI_ESP32.ino | 51 +++++++++++++++++------------------- 7 files changed, 41 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4eb29802..e7e207f17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file. ### Changed - Force initial default state ``SetOption57 1`` to scan wifi network every 44 minutes for strongest signal (#10395) +- Command ``Sleep 0`` removes any sleep from wifi modem except when ESP32 BLE is active ## [9.2.0.2] 20210105 ### Added diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5981c4022..b3f8e38a0 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -96,6 +96,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota - Replaced RA8876 GPIO selection from ``SPI CS`` by ``RA8876 CS`` ### Changed +- Command ``Sleep 0`` removes any sleep from wifi modem except when ESP32 BLE is active - Logging from heap to stack freeing 700 bytes RAM - Disabled ``USE_LIGHT`` light support for ZBBridge saving 17.6kB [#10374](https://github.com/arendst/Tasmota/issues/10374) - Force initial default state ``SetOption57 1`` to scan wifi network every 44 minutes for strongest signal [#10395](https://github.com/arendst/Tasmota/issues/10395) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 0866d3f84..1c5e32474 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -967,8 +967,9 @@ void CmndSetoption(void) bitWrite(Settings.flag5.data, pindex, XdrvMailbox.payload); switch (pindex) { case 1: // SetOption115 - Enable ESP32 MI32 - Settings.flag3.sleep_normal = 1; // SetOption60 - Enable normal sleep instead of dynamic sleep - TasmotaGlobal.restart_flag = 2; + if (0 == XdrvMailbox.payload) { + TasmotaGlobal.restart_flag = 2; + } break; } } diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index b281b0c51..2b5101174 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -160,15 +160,14 @@ void WiFiSetSleepMode(void) WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default) } */ - if (TasmotaGlobal.sleep && Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep - WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times - } else { -#ifdef ESP8266 - if (0 == TasmotaGlobal.sleep) { + if (0 == TasmotaGlobal.sleep) { + if (!TasmotaGlobal.wifi_stay_asleep) { WiFi.setSleepMode(WIFI_NONE_SLEEP); // Disable sleep - } else -#endif - { + } + } else { + if (Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep + WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times + } else { WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Sleep (Esp8288/Arduino core and sdk default) } } diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 36511aa9e..2407e61b1 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -125,6 +125,7 @@ struct { bool skip_light_fade; // Temporarily skip light fading bool restart_halt; // Do not restart but stay in wait loop bool module_changed; // Indicate module changed since last restart + bool wifi_stay_asleep; // Allow sleep only incase of ESP32 BLE StateBitfield global_state; // Global states (currently Wifi and Mqtt) (8 bits) uint8_t spi_enabled; // SPI configured diff --git a/tasmota/xsns_52_ibeacon.ino b/tasmota/xsns_52_ibeacon.ino index 731189827..723446700 100755 --- a/tasmota/xsns_52_ibeacon.ino +++ b/tasmota/xsns_52_ibeacon.ino @@ -279,16 +279,13 @@ void ESP32Init() { if (TasmotaGlobal.global_state.wifi_down) { return; } + TasmotaGlobal.wifi_stay_asleep = true; if (WiFi.getSleep() == false) { - if (0 == Settings.flag3.sleep_normal) { - AddLog_P(LOG_LEVEL_DEBUG,PSTR("%s: About to restart to put WiFi modem in sleep mode"),"BLE"); - Settings.flag3.sleep_normal = 1; // SetOption60 - Enable normal sleep instead of dynamic sleep - TasmotaGlobal.restart_flag = 2; - } - return; + AddLog_P(LOG_LEVEL_DEBUG,PSTR("%s: Put WiFi modem in sleep mode"),"BLE"); + WiFi.setSleep(true); // Sleep } - AddLog_P(LOG_LEVEL_DEBUG,PSTR("%s: Initializing Blueetooth..."),"BLE"); + AddLog_P(LOG_LEVEL_DEBUG,PSTR("%s: Initializing Bluetooth..."),"BLE"); if (!ESP32BLE.mode.init) { NimBLEDevice::init(""); diff --git a/tasmota/xsns_62_MI_ESP32.ino b/tasmota/xsns_62_MI_ESP32.ino index 9e9c70dc5..689b5a72a 100644 --- a/tasmota/xsns_62_MI_ESP32.ino +++ b/tasmota/xsns_62_MI_ESP32.ino @@ -589,17 +589,17 @@ int MI32_decryptPacket(char *_buf, uint16_t _bufSize, uint32_t _type){ MI32_ReverseMAC(packet->MAC); uint8_t _bindkey[16] = {0x0}; bool foundNoKey = true; - AddLog_P(LOG_LEVEL_DEBUG,PSTR("MI32: search key for MAC: %02x %02x %02x %02x %02x %02x"), packet->MAC[0], packet->MAC[1], packet->MAC[2], packet->MAC[3], packet->MAC[4], packet->MAC[5]); + AddLog_P(LOG_LEVEL_DEBUG,PSTR("M32: Search key for MAC: %02x %02x %02x %02x %02x %02x"), packet->MAC[0], packet->MAC[1], packet->MAC[2], packet->MAC[3], packet->MAC[4], packet->MAC[5]); for(uint32_t i=0; iMAC,MIBLEbindKeys[i].MAC,sizeof(packet->MAC))==0){ memcpy(_bindkey,MIBLEbindKeys[i].key,sizeof(_bindkey)); - AddLog_P(LOG_LEVEL_DEBUG,PSTR("MI32: decryption Key found")); + AddLog_P(LOG_LEVEL_DEBUG,PSTR("M32: Decryption Key found")); foundNoKey = false; break; } } if(foundNoKey){ - AddLog_P(LOG_LEVEL_DEBUG,PSTR("MI32: no Key found !!")); + AddLog_P(LOG_LEVEL_DEBUG,PSTR("M32: No Key found !!")); return -2; } @@ -619,7 +619,7 @@ int MI32_decryptPacket(char *_buf, uint16_t _bufSize, uint32_t _type){ ret = br_ccm_check_tag(&ctx, &tag); - AddLog_P(LOG_LEVEL_DEBUG,PSTR("MI32: Err:%i, Decrypted : %02x %02x %02x %02x %02x "), ret, packet->payload[1],packet->payload[2],packet->payload[3],packet->payload[4],packet->payload[5]); + AddLog_P(LOG_LEVEL_DEBUG,PSTR("M32: Err:%i, Decrypted : %02x %02x %02x %02x %02x "), ret, packet->payload[1],packet->payload[2],packet->payload[3],packet->payload[4],packet->payload[5]); return ret-1; } #endif // USE_MI_DECRYPTION @@ -660,7 +660,7 @@ uint32_t MIBLEgetSensorSlot(uint8_t (&_MAC)[6], uint16_t _type, uint8_t counter) bool _success = false; for (uint32_t i=0;i19) { - AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: Scan buffer full")); + AddLog_P(LOG_LEVEL_INFO,PSTR("M32: Scan buffer full")); MI32.state.beaconScanCounter = 1; return; } for(auto _scanResult : MIBLEscanResult){ if(memcmp(addr,_scanResult.MAC,6)==0){ - // AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: known device")); + // AddLog_P(LOG_LEVEL_INFO,PSTR("M32: known device")); return; } } @@ -1585,12 +1582,12 @@ void MI32addBeacon(uint8_t index, char* data){ _new.time = 0; if(memcmp(_empty,_new.MAC,6) == 0){ _new.active = false; - AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: beacon%u deactivated"), index); + AddLog_P(LOG_LEVEL_INFO,PSTR("M32: Beacon%u deactivated"), index); } else{ _new.active = true; MI32.mode.activeBeacon = 1; - AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: beacon added with MAC: %s"), _MAC); + AddLog_P(LOG_LEVEL_INFO,PSTR("M32: Beacon added with MAC: %s"), _MAC); } } @@ -1845,7 +1842,7 @@ void CmndMi32Time(void) { if (XdrvMailbox.data_len > 0) { if (MIBLEsensors.size() > XdrvMailbox.payload) { if ((LYWSD02 == MIBLEsensors[XdrvMailbox.payload].type) || (MHOC303 == MIBLEsensors[XdrvMailbox.payload].type)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("MI32: will set Time")); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("M32: Will set Time")); MI32.state.sensor = XdrvMailbox.payload; MI32.mode.canScan = 0; MI32.mode.canConnect = 0; @@ -1875,7 +1872,7 @@ void CmndMi32Unit(void) { if (XdrvMailbox.data_len > 0) { if (MIBLEsensors.size() > XdrvMailbox.payload) { if ((LYWSD02 == MIBLEsensors[XdrvMailbox.payload].type) || (MHOC303 == MIBLEsensors[XdrvMailbox.payload].type)) { - AddLog_P(LOG_LEVEL_DEBUG,PSTR("MI32: will set Unit")); + AddLog_P(LOG_LEVEL_DEBUG,PSTR("M32: Will set Unit")); MI32.state.sensor = XdrvMailbox.payload; MI32.mode.canScan = 0; MI32.mode.canConnect = 0; @@ -1925,11 +1922,11 @@ void CmndMi32Block(void){ switch (XdrvMailbox.index) { case 0: MIBLEBlockList.clear(); - // AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: size of ilist: %u"), MIBLEBlockList.size()); - ResponseCmndIdxChar(PSTR("block list cleared")); + // AddLog_P(LOG_LEVEL_INFO,PSTR("M32: Size of ilist: %u"), MIBLEBlockList.size()); + ResponseCmndIdxChar(PSTR("Block list cleared")); break; case 1: - ResponseCmndIdxChar(PSTR("show block list")); + ResponseCmndIdxChar(PSTR("Show block list")); break; } } @@ -1955,7 +1952,7 @@ void CmndMi32Block(void){ ResponseCmndIdxChar(XdrvMailbox.data); MI32removeMIBLEsensor(_MACasBytes.buf); } - // AddLog_P(LOG_LEVEL_INFO,PSTR("MI32: size of ilist: %u"), MIBLEBlockList.size()); + // AddLog_P(LOG_LEVEL_INFO,PSTR("M32: Size of ilist: %u"), MIBLEBlockList.size()); break; } } From e891c4e4901025a381454df76ebe1107b90f7972 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 14 Jan 2021 17:04:54 +0100 Subject: [PATCH 50/71] Update setSleepMode --- .../ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp | 31 +++++++------------ .../ESP32-to-ESP8266-compat/src/ESP8266WiFi.h | 1 + 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp index 0e26883ba..9f932040c 100644 --- a/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp +++ b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP32Wifi.cpp @@ -28,14 +28,12 @@ #undef WiFi #endif -void WiFiClass32::setSleepMode(int iSleepMode) -{ - // WIFI_MODEM_SLEEP - WiFi.setSleep(iSleepMode != WIFI_MODEM_SLEEP); +void WiFiClass32::setSleepMode(int iSleepMode) { + // WIFI_LIGHT_SLEEP and WIFI_MODEM_SLEEP + WiFi.setSleep(iSleepMode != WIFI_NONE_SLEEP); } -int WiFiClass32::getPhyMode() -{ +int WiFiClass32::getPhyMode() { int phy_mode = 0; // " BGNL" uint8_t protocol_bitmap; if (esp_wifi_get_protocol(WIFI_IF_STA, &protocol_bitmap) == ESP_OK) { @@ -47,12 +45,10 @@ int WiFiClass32::getPhyMode() return phy_mode; } -void WiFiClass32::wps_disable() -{ +void WiFiClass32::wps_disable() { } -void WiFiClass32::setOutputPower(int n) -{ +void WiFiClass32::setOutputPower(int n) { wifi_power_t p = WIFI_POWER_2dBm; if (n > 19) p = WIFI_POWER_19_5dBm; @@ -75,28 +71,23 @@ void WiFiClass32::setOutputPower(int n) WiFi.setTxPower(p); } -void WiFiClass32::forceSleepBegin() -{ +void WiFiClass32::forceSleepBegin() { } -void WiFiClass32::forceSleepWake() -{ +void WiFiClass32::forceSleepWake() { } -bool WiFiClass32::getNetworkInfo(uint8_t i, String &ssid, uint8_t &encType, int32_t &rssi, uint8_t *&bssid, int32_t &channel, bool &hidden_scan) -{ +bool WiFiClass32::getNetworkInfo(uint8_t i, String &ssid, uint8_t &encType, int32_t &rssi, uint8_t *&bssid, int32_t &channel, bool &hidden_scan) { hidden_scan = false; return WiFi.getNetworkInfo(i, ssid, encType, rssi, bssid, channel); } -void wifi_station_disconnect() -{ +void wifi_station_disconnect() { // erase ap: empty ssid, ... WiFi.disconnect(true, true); } -void wifi_station_dhcpc_start() -{ +void wifi_station_dhcpc_start() { } WiFiClass32 WiFi32; diff --git a/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h index 9649f49f5..4a7c3ccc9 100644 --- a/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h +++ b/lib/libesp32/ESP32-to-ESP8266-compat/src/ESP8266WiFi.h @@ -28,6 +28,7 @@ #define ENC_TYPE_TKIP WIFI_AUTH_WPA_WPA2_PSK #define ENC_TYPE_AUTO WIFI_AUTH_MAX + 1 +#define WIFI_NONE_SLEEP 0 #define WIFI_LIGHT_SLEEP 1 #define WIFI_MODEM_SLEEP 2 From d60b69a712fd4f741be6fcbffd233d756b53d01b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 14 Jan 2021 18:09:45 +0100 Subject: [PATCH 51/71] Try next NTP server on error --- tasmota/support_wifi.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 2b5101174..f16a641fe 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -819,6 +819,8 @@ uint32_t WifiGetNtp(void) { // Leap-Indicator: unknown (clock unsynchronized) // See: https://github.com/letscontrolit/ESPEasy/issues/2886#issuecomment-586656384 AddLog_P(LOG_LEVEL_DEBUG, PSTR("NTP: IP %s unsynched"), time_server_ip.toString().c_str()); + ntp_server_id++; + if (ntp_server_id > 2) { ntp_server_id = 0; } // Next server next time return 0; } @@ -829,6 +831,8 @@ uint32_t WifiGetNtp(void) { secs_since_1900 |= (uint32_t)packet_buffer[42] << 8; secs_since_1900 |= (uint32_t)packet_buffer[43]; if (0 == secs_since_1900) { // No time stamp received + ntp_server_id++; + if (ntp_server_id > 2) { ntp_server_id = 0; } // Next server next time return 0; } return secs_since_1900 - 2208988800UL; From 339e78538795fe6fce1a1633fa4ad9f843ef51ba Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 14 Jan 2021 18:40:59 +0100 Subject: [PATCH 52/71] Fix Hue emulation for ESP32 (#10564) * Fix Hue emulation for ESP32 * Fix compilation for Zigbee Co-authored-by: Stephan Hadinger --- tasmota/support_udp.ino | 31 ++++++++++++++----------------- tasmota/xdrv_20_hue.ino | 2 -- tasmota/xdrv_21_wemo.ino | 2 -- tasmota/xdrv_21_wemo_multi.ino | 2 -- 4 files changed, 14 insertions(+), 23 deletions(-) diff --git a/tasmota/support_udp.ino b/tasmota/support_udp.ino index 0462513d3..07aa6736e 100644 --- a/tasmota/support_udp.ino +++ b/tasmota/support_udp.ino @@ -32,7 +32,6 @@ IPAddress udp_remote_ip; // M-Search remote IP address uint16_t udp_remote_port; // M-Search remote port bool udp_connected = false; -bool udp_response_mutex = false; // M-Search response mutex to control re-entry #ifdef ESP8266 #ifndef UDP_MAX_PACKETS @@ -89,14 +88,12 @@ bool UdpConnect(void) if (UdpCtx.listen(&addr, 1900)) { // port 1900 // OK AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED)); - udp_response_mutex = false; udp_connected = true; } #endif // ESP8266 #ifdef ESP32 if (PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), 1900)) { AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED)); - udp_response_mutex = false; udp_connected = true; #endif // ESP32 } @@ -123,28 +120,29 @@ void PollUdp(void) packet->buf[packet->len] = 0; // add NULL at the end of the packet char * packet_buffer = (char*) &packet->buf; int32_t len = packet->len; + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); #endif // ESP8266 #ifdef ESP32 - while (PortUdp.parsePacket()) { + while (uint32_t pack_len = PortUdp.parsePacket()) { char packet_buffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP/SSDP packet int32_t len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1); packet_buffer[len] = 0; + PortUdp.flush(); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d/%d)"), len, pack_len); #endif // ESP32 - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); + // AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); // Simple Service Discovery Protocol (SSDP) if (Settings.flag2.emulation) { #if defined(USE_SCRIPT_HUE) || defined(USE_ZIGBEE) - if (!udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { + if (TasmotaGlobal.devices_present && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { #else - if (TasmotaGlobal.devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { + if (TasmotaGlobal.devices_present && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { #endif if (0 == udp_last_received) { udp_last_received = millis(); - udp_response_mutex = true; - #ifdef ESP8266 udp_remote_ip = packet->srcaddr; udp_remote_port = packet->srcport; @@ -159,35 +157,34 @@ void PollUdp(void) LowerCase(packet_buffer, packet_buffer); RemoveSpace(packet_buffer); + bool udp_proccessed = false; // make sure we process the packet only once #ifdef USE_EMULATION_WEMO - if (EMUL_WEMO == Settings.flag2.emulation) { + if (!udp_proccessed && (EMUL_WEMO == Settings.flag2.emulation)) { if (strstr_P(packet_buffer, URN_BELKIN_DEVICE) != nullptr) { // type1 echo dot 2g, echo 1g's WemoRespondToMSearch(1); - return; + udp_proccessed = true; } else if ((strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || // type2 Echo 2g (echo & echo plus) (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { WemoRespondToMSearch(2); - return; + udp_proccessed = true; } } #endif // USE_EMULATION_WEMO #ifdef USE_EMULATION_HUE - if (EMUL_HUE == Settings.flag2.emulation) { + if (!udp_proccessed && (EMUL_HUE == Settings.flag2.emulation)) { + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: HUE")); if ((strstr_P(packet_buffer, PSTR(":device:basic:1")) != nullptr) || (strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { HueRespondToMSearch(); - return; + udp_proccessed = true; } } #endif // USE_EMULATION_HUE - - udp_response_mutex = false; - continue; } } } diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 97eafbcba..4da625847 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -225,8 +225,6 @@ void HueRespondToMSearch(void) // Do not use AddLog_P( here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9 AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_HUE " %s " D_TO " %s:%d"), message, udp_remote_ip.toString().c_str(), udp_remote_port); - - udp_response_mutex = false; } /*********************************************************************************************\ diff --git a/tasmota/xdrv_21_wemo.ino b/tasmota/xdrv_21_wemo.ino index 96e937d21..18f793824 100644 --- a/tasmota/xdrv_21_wemo.ino +++ b/tasmota/xdrv_21_wemo.ino @@ -76,8 +76,6 @@ void WemoRespondToMSearch(int echo_type) // Do not use AddLog_P( here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9 AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"), echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port); - - udp_response_mutex = false; } /*********************************************************************************************\ diff --git a/tasmota/xdrv_21_wemo_multi.ino b/tasmota/xdrv_21_wemo_multi.ino index ec3fb7d42..1a0b3ac6c 100644 --- a/tasmota/xdrv_21_wemo_multi.ino +++ b/tasmota/xdrv_21_wemo_multi.ino @@ -422,8 +422,6 @@ void WemoRespondToMSearch(int echo_type) { for (uint32_t i = 0; i < numOfWemoSwitch; i++) { wemoDevice[i]->WemoRespondToMSearch(echo_type); } - - udp_response_mutex = false; } /*********************************************************************************************\ From f100ad5d032ac8ba9e974b959e6a406df30ca16a Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Thu, 14 Jan 2021 21:36:08 +0100 Subject: [PATCH 53/71] Include SetOption117 in discovery message --- tasmota/xdrv_12_home_assistant.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index 8ef33c91f..bf4664886 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -197,7 +197,7 @@ const char HASS_DISCOVER_DEVICE[] PROGMEM = // Basic par "\"tp\":[\"%s\",\"%s\",\"%s\"]," // Topics for command, stat and tele "\"rl\":[%s],\"swc\":[%s],\"swn\":[%s],\"btn\":[%s]," // Inputs / Outputs "\"so\":{\"4\":%d,\"11\":%d,\"13\":%d,\"17\":%d,\"20\":%d," // SetOptions - "\"30\":%d,\"68\":%d,\"73\":%d,\"82\":%d,\"114\":%d}," + "\"30\":%d,\"68\":%d,\"73\":%d,\"82\":%d,\"114\":%d,\"117\":%d}," "\"lk\":%d,\"lt_st\":%d,\"sho\":[%s],\"ver\":1}"; // Light SubType, Shutter Options and Discovery version typedef struct HASS { @@ -341,7 +341,7 @@ void NewHAssDiscovery(void) TasmotaGlobal.version, TasmotaGlobal.mqtt_topic, SettingsText(SET_MQTT_FULLTOPIC), SUB_PREFIX, PUB_PREFIX, PUB_PREFIX2, Hass.RelLst, stemp3, stemp4, stemp5, Settings.flag.mqtt_response, Settings.flag.button_swap, Settings.flag.button_single, Settings.flag.decimal_text, Settings.flag.not_power_linked, Settings.flag.hass_light, Settings.flag3.pwm_multi_channels, Settings.flag3.mqtt_buttons, Settings.flag4.alexa_ct_range, Settings.flag5.mqtt_switches, - light_controller.isCTRGBLinked(), Light.subtype, stemp6); + Settings.flag5.fade_fixed_duration, light_controller.isCTRGBLinked(), Light.subtype, stemp6); } MqttPublish(stopic, true); From 46bf60ac1551ab3ccffeeb7fd76f65ab68f8ec48 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 15 Jan 2021 10:43:58 +0100 Subject: [PATCH 54/71] Small refactor NTP --- tasmota/support_wifi.ino | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index f16a641fe..15f5e10c2 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -748,6 +748,7 @@ uint32_t WifiGetNtp(void) { char* ntp_server; bool resolved_ip = false; for (uint32_t i = 0; i <= MAX_NTP_SERVERS; i++) { + if (ntp_server_id > 2) { ntp_server_id = 0; } if (i < MAX_NTP_SERVERS) { ntp_server = SettingsText(SET_NTPSERVER1 + ntp_server_id); } else { @@ -760,7 +761,6 @@ uint32_t WifiGetNtp(void) { if (resolved_ip) { break; } } ntp_server_id++; - if (ntp_server_id > 2) { ntp_server_id = 0; } } if (!resolved_ip) { // AddLog_P(LOG_LEVEL_DEBUG, PSTR("NTP: No server found")); @@ -798,8 +798,7 @@ uint32_t WifiGetNtp(void) { packet_buffer[15] = 52; if (udp.beginPacket(time_server_ip, 123) == 0) { // NTP requests are to port 123 - ntp_server_id++; - if (ntp_server_id > 2) { ntp_server_id = 0; } // Next server next time + ntp_server_id++; // Next server next time udp.stop(); return 0; } @@ -819,8 +818,7 @@ uint32_t WifiGetNtp(void) { // Leap-Indicator: unknown (clock unsynchronized) // See: https://github.com/letscontrolit/ESPEasy/issues/2886#issuecomment-586656384 AddLog_P(LOG_LEVEL_DEBUG, PSTR("NTP: IP %s unsynched"), time_server_ip.toString().c_str()); - ntp_server_id++; - if (ntp_server_id > 2) { ntp_server_id = 0; } // Next server next time + ntp_server_id++; // Next server next time return 0; } @@ -831,8 +829,7 @@ uint32_t WifiGetNtp(void) { secs_since_1900 |= (uint32_t)packet_buffer[42] << 8; secs_since_1900 |= (uint32_t)packet_buffer[43]; if (0 == secs_since_1900) { // No time stamp received - ntp_server_id++; - if (ntp_server_id > 2) { ntp_server_id = 0; } // Next server next time + ntp_server_id++; // Next server next time return 0; } return secs_since_1900 - 2208988800UL; @@ -842,6 +839,7 @@ uint32_t WifiGetNtp(void) { // Timeout. AddLog_P(LOG_LEVEL_DEBUG, PSTR("NTP: No reply")); udp.stop(); + ntp_server_id++; // Next server next time return 0; } From d64a6a1b1081b821de9c456c74ba60ed3eebbfa4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 15 Jan 2021 11:45:04 +0100 Subject: [PATCH 55/71] Increase sensor support --- tasmota/xsns_interface.ino | 135 ++++++++++++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 10 deletions(-) diff --git a/tasmota/xsns_interface.ino b/tasmota/xsns_interface.ino index 21918f22c..f41de7920 100644 --- a/tasmota/xsns_interface.ino +++ b/tasmota/xsns_interface.ino @@ -825,27 +825,144 @@ const uint8_t kXsnsList[] = { #endif #ifdef XSNS_99 - XSNS_99 + XSNS_99, #endif + +#ifdef XSNS_100 + XSNS_100, +#endif + +#ifdef XSNS_101 + XSNS_101, +#endif + +#ifdef XSNS_102 + XSNS_102, +#endif + +#ifdef XSNS_103 + XSNS_103, +#endif + +#ifdef XSNS_104 + XSNS_104, +#endif + +#ifdef XSNS_105 + XSNS_105, +#endif + +#ifdef XSNS_106 + XSNS_106, +#endif + +#ifdef XSNS_107 + XSNS_107, +#endif + +#ifdef XSNS_108 + XSNS_108, +#endif + +#ifdef XSNS_109 + XSNS_109, +#endif + +#ifdef XSNS_110 + XSNS_110, +#endif + +#ifdef XSNS_111 + XSNS_111, +#endif + +#ifdef XSNS_112 + XSNS_112, +#endif + +#ifdef XSNS_113 + XSNS_113, +#endif + +#ifdef XSNS_114 + XSNS_114, +#endif + +#ifdef XSNS_115 + XSNS_115, +#endif + +#ifdef XSNS_116 + XSNS_116, +#endif + +#ifdef XSNS_117 + XSNS_117, +#endif + +#ifdef XSNS_118 + XSNS_118, +#endif + +#ifdef XSNS_119 + XSNS_119, +#endif + +#ifdef XSNS_120 + XSNS_120, +#endif + +#ifdef XSNS_121 + XSNS_121, +#endif + +#ifdef XSNS_122 + XSNS_122, +#endif + +#ifdef XSNS_123 + XSNS_123, +#endif + +#ifdef XSNS_124 + XSNS_124, +#endif + +#ifdef XSNS_125 + XSNS_125, +#endif + +#ifdef XSNS_126 + XSNS_126, +#endif + +#ifdef XSNS_127 + XSNS_127, +#endif + +#ifdef XSNS_128 + XSNS_128 +#endif + }; /*********************************************************************************************/ -bool XsnsEnabled(uint32_t sns_index) -{ +bool XsnsEnabled(uint32_t sns_index) { if (sns_index < sizeof(kXsnsList)) { #ifdef XFUNC_PTR_IN_ROM uint32_t index = pgm_read_byte(kXsnsList + sns_index); #else uint32_t index = kXsnsList[sns_index]; #endif - return bitRead(Settings.sensors[index / 32], index % 32); + if (index < MAX_XSNS_DRIVERS) { + return bitRead(Settings.sensors[index / 32], index % 32); + } } return true; } -void XsnsSensorState(void) -{ +void XsnsSensorState(void) { ResponseAppend_P(PSTR("\"")); // Use string for enable/disable signal for (uint32_t i = 0; i < sizeof(kXsnsList); i++) { #ifdef XFUNC_PTR_IN_ROM @@ -866,8 +983,7 @@ void XsnsSensorState(void) * Function call to all xsns \*********************************************************************************************/ -bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index) -{ +bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index) { if (0 == xsns_present) { xsns_index = 0; return false; @@ -891,8 +1007,7 @@ bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index) return xsns_func_ptr[xsns_index](Function); } -bool XsnsCall(uint8_t Function) -{ +bool XsnsCall(uint8_t Function) { bool result = false; DEBUG_TRACE_LOG(PSTR("SNS: %d"), Function); From 2c9203d6625506eda3715c85a8805895239cac2d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 15 Jan 2021 12:01:15 +0100 Subject: [PATCH 56/71] Increase driver and display support --- tasmota/xdrv_interface.ino | 236 ++++++++++++++++++++++++++++++++++++- tasmota/xdsp_interface.ino | 66 ++++++++++- 2 files changed, 299 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_interface.ino b/tasmota/xdrv_interface.ino index a5e0f6479..77c93c6da 100644 --- a/tasmota/xdrv_interface.ino +++ b/tasmota/xdrv_interface.ino @@ -416,7 +416,123 @@ bool (* const xdrv_func_ptr[])(uint8_t) = { // Driver Function Pointers #endif #ifdef XDRV_99 - &Xdrv99 + &Xdrv99, +#endif + +#ifdef XDRV_100 + &Xdrv100, +#endif + +#ifdef XDRV_101 + &Xdrv101, +#endif + +#ifdef XDRV_102 + &Xdrv102, +#endif + +#ifdef XDRV_103 + &Xdrv103, +#endif + +#ifdef XDRV_104 + &Xdrv104, +#endif + +#ifdef XDRV_105 + &Xdrv105, +#endif + +#ifdef XDRV_106 + &Xdrv106, +#endif + +#ifdef XDRV_107 + &Xdrv107, +#endif + +#ifdef XDRV_108 + &Xdrv108, +#endif + +#ifdef XDRV_109 + &Xdrv109, +#endif + +#ifdef XDRV_110 + &Xdrv110, +#endif + +#ifdef XDRV_111 + &Xdrv111, +#endif + +#ifdef XDRV_112 + &Xdrv112, +#endif + +#ifdef XDRV_113 + &Xdrv113, +#endif + +#ifdef XDRV_114 + &Xdrv114, +#endif + +#ifdef XDRV_115 + &Xdrv115, +#endif + +#ifdef XDRV_116 + &Xdrv116, +#endif + +#ifdef XDRV_117 + &Xdrv117, +#endif + +#ifdef XDRV_118 + &Xdrv118, +#endif + +#ifdef XDRV_119 + &Xdrv119, +#endif + +#ifdef XDRV_120 + &Xdrv120, +#endif + +#ifdef XDRV_121 + &Xdrv121, +#endif + +#ifdef XDRV_122 + &Xdrv122, +#endif + +#ifdef XDRV_123 + &Xdrv123, +#endif + +#ifdef XDRV_124 + &Xdrv124, +#endif + +#ifdef XDRV_125 + &Xdrv125, +#endif + +#ifdef XDRV_126 + &Xdrv126, +#endif + +#ifdef XDRV_127 + &Xdrv127, +#endif + +#ifdef XDRV_128 + &Xdrv128 #endif }; @@ -825,7 +941,123 @@ const uint8_t kXdrvList[] = { #endif #ifdef XDRV_99 - XDRV_99 + XDRV_99, +#endif + +#ifdef XDRV_100 + Xdrv100, +#endif + +#ifdef XDRV_101 + Xdrv101, +#endif + +#ifdef XDRV_102 + Xdrv102, +#endif + +#ifdef XDRV_103 + Xdrv103, +#endif + +#ifdef XDRV_104 + Xdrv104, +#endif + +#ifdef XDRV_105 + Xdrv105, +#endif + +#ifdef XDRV_106 + Xdrv106, +#endif + +#ifdef XDRV_107 + Xdrv107, +#endif + +#ifdef XDRV_108 + Xdrv108, +#endif + +#ifdef XDRV_109 + Xdrv109, +#endif + +#ifdef XDRV_110 + Xdrv110, +#endif + +#ifdef XDRV_111 + Xdrv111, +#endif + +#ifdef XDRV_112 + Xdrv112, +#endif + +#ifdef XDRV_113 + Xdrv113, +#endif + +#ifdef XDRV_114 + Xdrv114, +#endif + +#ifdef XDRV_115 + Xdrv115, +#endif + +#ifdef XDRV_116 + Xdrv116, +#endif + +#ifdef XDRV_117 + Xdrv117, +#endif + +#ifdef XDRV_118 + Xdrv118, +#endif + +#ifdef XDRV_119 + Xdrv119, +#endif + +#ifdef XDRV_120 + Xdrv120, +#endif + +#ifdef XDRV_121 + Xdrv121, +#endif + +#ifdef XDRV_122 + Xdrv122, +#endif + +#ifdef XDRV_123 + Xdrv123, +#endif + +#ifdef XDRV_124 + Xdrv124, +#endif + +#ifdef XDRV_125 + Xdrv125, +#endif + +#ifdef XDRV_126 + Xdrv126, +#endif + +#ifdef XDRV_127 + Xdrv127, +#endif + +#ifdef XDRV_128 + Xdrv128 #endif }; diff --git a/tasmota/xdsp_interface.ino b/tasmota/xdsp_interface.ino index 1ce18ff6c..3ca49f3d6 100644 --- a/tasmota/xdsp_interface.ino +++ b/tasmota/xdsp_interface.ino @@ -87,7 +87,71 @@ bool (* const xdsp_func_ptr[])(uint8_t) = { // Display Function Pointers #endif #ifdef XDSP_16 - &Xdsp16 + &Xdsp16, +#endif + +#ifdef XDSP_17 + &Xdsp17, +#endif + +#ifdef XDSP_18 + &Xdsp18, +#endif + +#ifdef XDSP_19 + &Xdsp19, +#endif + +#ifdef XDSP_20 + &Xdsp20, +#endif + +#ifdef XDSP_21 + &Xdsp21, +#endif + +#ifdef XDSP_22 + &Xdsp22, +#endif + +#ifdef XDSP_23 + &Xdsp23, +#endif + +#ifdef XDSP_24 + &Xdsp24, +#endif + +#ifdef XDSP_25 + &Xdsp25, +#endif + +#ifdef XDSP_26 + &Xdsp26, +#endif + +#ifdef XDSP_27 + &Xdsp27, +#endif + +#ifdef XDSP_28 + &Xdsp28, +#endif + +#ifdef XDSP_29 + &Xdsp29, +#endif + +#ifdef XDSP_30 + &Xdsp30, +#endif + +#ifdef XDSP_31 + &Xdsp31, +#endif + +#ifdef XDSP_32 + &Xdsp32 #endif }; From 89a9c049d6ae99cc478cbfeff8ba6c9064fced61 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 15 Jan 2021 14:31:25 +0100 Subject: [PATCH 57/71] Add debug message regarding energy reset --- tasmota/xdrv_03_energy.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino index 7c7ba932e..f57431203 100644 --- a/tasmota/xdrv_03_energy.ino +++ b/tasmota/xdrv_03_energy.ino @@ -537,6 +537,7 @@ void EnergyEverySecond(void) } if (!data_valid) { Energy.start_energy = 0; + AddLog_P(LOG_LEVEL_DEBUG, PSTR("NRG: Energy reset by " STR(ENERGY_WATCHDOG) " seconds invalid data")); XnrgCall(FUNC_ENERGY_RESET); } From 6a2016f56834ee21189a3a72343a621c8f98de6b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 15 Jan 2021 15:09:49 +0100 Subject: [PATCH 58/71] Remove redundant entrys --- platformio_override_sample.ini | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index d82b7f45d..e46754e7a 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -116,33 +116,21 @@ build_flags = ${esp82xx_defaults.build_flags} -DWAVEFORM_LOCKED_PWM -Wno-switch-unreachable - [common32] -platform = ${core32.platform} platform_packages = ${core32.platform_packages} build_unflags = ${core32.build_unflags} build_flags = ${core32.build_flags} -board = esp32dev -board_build.ldscript = esp32_out.ld -board_build.partitions = esp32_partition_app1984k_spiffs64k.csv -board_build.flash_mode = ${common.board_build.flash_mode} -board_build.f_flash = ${common.board_build.f_flash} -board_build.f_cpu = ${common.board_build.f_cpu} -monitor_speed = ${common.monitor_speed} -upload_port = ${common.upload_port} -upload_resetmethod = ${common.upload_resetmethod} -upload_speed = 921600 -extra_scripts = ${common.extra_scripts} +upload_port = COM4 lib_extra_dirs = ${library.lib_extra_dirs} ; *** ESP32 lib. ALWAYS needed for ESP32 !!! lib/libesp32 + [core32] ; Activate Stage Core32 by removing ";" in next 3 lines, if you want to override the standard core32 ;platform_packages = ${core32_stage.platform_packages} ;build_unflags = ${core32_stage.build_unflags} ;build_flags = ${core32_stage.build_flags} - [core32_stage] platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/arduino-esp32/releases/download/1.0.5-rc6/esp32-1.0.5-rc6.zip platformio/tool-mklittlefs @ ~1.203.200522 From 7fc0c42e0490ead2ec22bc4fc42c54d5dcaadb41 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 15 Jan 2021 15:15:04 +0100 Subject: [PATCH 59/71] change from string to list and hack for using littlefs for ESP32 instead of SPIFFS --- pio-tools/download_fs.py | 44 ++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/pio-tools/download_fs.py b/pio-tools/download_fs.py index ed6426cc7..f43bec128 100644 --- a/pio-tools/download_fs.py +++ b/pio-tools/download_fs.py @@ -1,14 +1,14 @@ # Written by Maximilian Gerhardt # 29th December 2020 # License: Apache -# Expanded from functionality provided by PlatformIO's espressif32 and espressif8266 platforms, credited below. -# This script provides functions to download the filesystem (SPIFFS or LittleFS) from a running ESP32 / ESP8266 +# Expanded from functionality provided by PlatformIO's espressif32 and espressif8266 platforms, credited below. +# This script provides functions to download the filesystem (SPIFFS or LittleFS) from a running ESP32 / ESP8266 # over the serial bootloader using esptool.py, and mklittlefs / mkspiffs for extracting. -# run by either using the VSCode task "Custom" -> "Download Filesystem" -# or by doing 'pio run -t downloadfs' (with optional '-e ') from the commandline. +# run by either using the VSCode task "Custom" -> "Download Filesystem" +# or by doing 'pio run -t downloadfs' (with optional '-e ') from the commandline. # output will be saved, by default, in the "unpacked_fs" of the project. -# this folder can be changed by writing 'custom_unpack_dir = some_other_dir' in the corresponding platformio.ini -# environment. +# this folder can be changed by writing 'custom_unpack_dir = some_other_dir' in the corresponding platformio.ini +# environment. import re import sys from os.path import isfile, join @@ -23,25 +23,29 @@ Import("env") platform = env.PioPlatform() board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") +# Hack for using mklittlefs instead of mkspiffs -> needed since littlefs is not supported with this for ESP32 +#print("Replace MKSPIFFSTOOL with mklittlefs") +env.Replace( MKSPIFFSTOOL=platform.get_package_dir("tool-mklittlefs") + '/mklittlefs' ) + # needed for later AutodetectUploadPort(env) -class FSType(Enum): +class FSType(Enum): SPIFFS="spiffs" LITTLEFS="littlefs" - FATFS="fatfs" + FATFS="fatfs" class FSInfo: - def __init__(self, fs_type, start, length, page_size, block_size): + def __init__(self, fs_type, start, length, page_size, block_size): self.fs_type = fs_type - self.start = start + self.start = start self.length = length self.page_size = page_size self.block_size = block_size def __repr__(self): return f"FS type {self.fs_type} Start {hex(self.start)} Len {self.length} Page size {self.page_size} Block size {self.block_size}" # extract command supposed to be implemented by subclasses - def get_extract_cmd(self): + def get_extract_cmd(self, input_file, output_dir): raise NotImplementedError() class LittleFSInfo(FSInfo): @@ -53,10 +57,10 @@ class LittleFSInfo(FSInfo): self.tool = env["MKFSTOOL"] # from mkspiffs package self.tool = join(platform.get_package_dir("tool-mklittlefs"), self.tool) super().__init__(FSType.LITTLEFS, start, length, page_size, block_size) - def __repr__(self): + def __repr__(self): return f"FS type {self.fs_type} Start {hex(self.start)} Len {self.length} Page size {self.page_size} Block size {self.block_size} Tool: {self.tool}" def get_extract_cmd(self, input_file, output_dir): - return f'"{self.tool}" -b {self.block_size} -p {self.page_size} --unpack "{output_dir}" "{input_file}"' + return [self.tool, "-b", str(self.block_size), "-p", str(self.page_size), "--unpack", output_dir, input_file] class SPIFFSInfo(FSInfo): @@ -68,7 +72,7 @@ class SPIFFSInfo(FSInfo): self.tool = env["MKFSTOOL"] # from mkspiffs package self.tool = join(platform.get_package_dir("tool-mkspiffs"), self.tool) super().__init__(FSType.SPIFFS, start, length, page_size, block_size) - def __repr__(self): + def __repr__(self): return f"FS type {self.fs_type} Start {hex(self.start)} Len {self.length} Page size {self.page_size} Block size {self.block_size} Tool: {self.tool}" def get_extract_cmd(self, input_file, output_dir): return f'"{self.tool}" -b {self.block_size} -p {self.page_size} --unpack "{output_dir}" "{input_file}"' @@ -258,16 +262,16 @@ def download_fs(fs_info: FSInfo): fs_file = join(env["PROJECT_DIR"], f"downloaded_fs_{hex(fs_info.start)}_{hex(fs_info.length)}.bin") esptoolpy_flags = [ "--chip", mcu, - "--port", '"' + env.subst("$UPLOAD_PORT") + '"', + "--port", env.subst("$UPLOAD_PORT"), "--baud", env.subst("$UPLOAD_SPEED"), "--before", "default_reset", "--after", "hard_reset", - "read_flash", + "read_flash", hex(fs_info.start), hex(fs_info.length), - '"' + fs_file + '"' + fs_file ] - esptoolpy_cmd = '"' + env["PYTHONEXE"]+ '"' + ' "' + esptoolpy + '" ' + " ".join(esptoolpy_flags) + esptoolpy_cmd = [env["PYTHONEXE"], esptoolpy] + esptoolpy_flags print("Executing flash download command.") print(esptoolpy_cmd) try: @@ -302,7 +306,7 @@ def unpack_fs(fs_info: FSInfo, downloaded_file: str): return (False, "") def display_fs(extracted_dir): - # extract command already nicely lists all extracted files. + # extract command already nicely lists all extracted files. # no need to display that ourselves. just display a summary file_count = sum([len(files) for r, d, files in os.walk(extracted_dir)]) print("Extracted " + str(file_count) + " file(s) from filesystem.") @@ -326,4 +330,4 @@ env.AddCustomTarget( ], title="Download Filesystem", description="Downloads and displays files stored in the target ESP32/ESP8266" -) \ No newline at end of file +) From a16306fbf6c7b61d7be8ac5b27040c22c1f0fd96 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 15 Jan 2021 15:16:41 +0100 Subject: [PATCH 60/71] add custom_unpack_dir --- platformio_tasmota32.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_tasmota32.ini b/platformio_tasmota32.ini index 79c56eb96..a41222bb4 100644 --- a/platformio_tasmota32.ini +++ b/platformio_tasmota32.ini @@ -48,6 +48,7 @@ build_unflags = ${core32.build_unflags} build_flags = ${core32.build_flags} board = esp32dev board_build.filesystem = ${common.board_build.filesystem} +custom_unpack_dir = ${common.custom_unpack_dir} board_build.ldscript = esp32_out.ld board_build.partitions = esp32_partition_app1984k_spiffs64k.csv board_build.flash_mode = ${common.board_build.flash_mode} From 129af59a9db58dc9b57506d62cd786262ed912df Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 15 Jan 2021 15:19:01 +0100 Subject: [PATCH 61/71] change unpack_dir --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index a95530335..12ccfcc90 100644 --- a/platformio.ini +++ b/platformio.ini @@ -67,7 +67,7 @@ default_envs = ${build_envs.default_envs} framework = arduino board = esp01_1m board_build.filesystem = littlefs -custom_unpack_dir = unpacked_esp8266_littlefs +custom_unpack_dir = unpacked_littlefs board_build.flash_mode = dout board_build.ldscript = eagle.flash.1m.ld From c74cce1c4e9d3c8b1866dfe7342e2fdb7392dfe9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 15 Jan 2021 15:20:39 +0100 Subject: [PATCH 62/71] add filesystems directorys --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 96c63651b..503ccf780 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,8 @@ .clang_complete .gcc-flags.json .cache +data +unpacked_fs tasmota/user_config_override.h build build_output From 43fd9ee1f23f742cf84162cef81f40a3fe4447cc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 15 Jan 2021 16:17:25 +0100 Subject: [PATCH 63/71] Fix dual filesystem commands --- tasmota/xdrv_50_filesystem.ino | 71 +++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/tasmota/xdrv_50_filesystem.ino b/tasmota/xdrv_50_filesystem.ino index 8066a9b93..0b7fc53d2 100644 --- a/tasmota/xdrv_50_filesystem.ino +++ b/tasmota/xdrv_50_filesystem.ino @@ -72,25 +72,28 @@ ufsfree free size in kB #include "FS.h" #endif // ESP32 -// global file system pointer +// Global file system pointer FS *ufsp; -// flash file system pointer on esp32 +// Flash file system pointer FS *ffsp; -// local pointer for file managment +// Local pointer for file managment FS *dfsp; char ufs_path[48]; File ufs_upload_file; uint8_t ufs_dir; -// 0 = none, 1 = SD, 2 = ffat, 3 = littlefs +// 0 = None, 1 = SD, 2 = ffat, 3 = littlefs uint8_t ufs_type; uint8_t ffs_type; bool download_busy; + + + /*********************************************************************************************/ -// init flash file system +// Init flash file system void UfsInitOnce(void) { ufs_type = 0; ffsp = 0; @@ -130,21 +133,13 @@ void UfsInitOnce(void) { void UfsInit(void) { UfsInitOnce(); if (ufs_type) { - AddLog_P(LOG_LEVEL_INFO, PSTR("UFS: Type %d mounted with %d kB free"), ufs_type, UfsInfo(1, 0)); + AddLog_P(LOG_LEVEL_INFO, PSTR("UFS: FlashFS mounted with %d kB free"), UfsInfo(1, 0)); } } - #ifdef USE_SDCARD void UfsCheckSDCardInit(void) { - -#ifdef ESP8266 - if (PinUsed(GPIO_SPI_CLK) && PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_MISO)) { -#endif // ESP8266 - -#ifdef ESP32 if (TasmotaGlobal.spi_enabled) { -#endif // ESP32 int8_t cs = SDCARD_CS_PIN; if (PinUsed(GPIO_SDCARD_CS)) { cs = Pin(GPIO_SDCARD_CS); @@ -172,10 +167,10 @@ void UfsCheckSDCardInit(void) { // make sd card the global filesystem #ifdef ESP8266 // on esp8266 sdcard info takes several seconds !!!, so we ommit it here - AddLog_P(LOG_LEVEL_INFO, PSTR("UFS: SDCARD mounted")); + AddLog_P(LOG_LEVEL_INFO, PSTR("UFS: SDCard mounted")); #endif // ESP8266 #ifdef ESP32 - AddLog_P(LOG_LEVEL_INFO, PSTR("UFS: SDCARD mounted with %d kB free"), UfsInfo(1, 0)); + AddLog_P(LOG_LEVEL_INFO, PSTR("UFS: SDCard mounted with %d kB free"), UfsInfo(1, 0)); #endif // ESP32 } } @@ -279,7 +274,7 @@ uint8_t UfsReject(char *name) { \*********************************************************************************************/ bool TfsFileExists(const char *fname){ - if (!ufs_type) { return false; } + if (!ffs_type) { return false; } bool yes = ffsp->exists(fname); if (!yes) { @@ -289,7 +284,7 @@ bool TfsFileExists(const char *fname){ } bool TfsSaveFile(const char *fname, const uint8_t *buf, uint32_t len) { - if (!ufs_type) { return false; } + if (!ffs_type) { return false; } File file = ffsp->open(fname, "w"); if (!file) { @@ -303,7 +298,7 @@ bool TfsSaveFile(const char *fname, const uint8_t *buf, uint32_t len) { } bool TfsInitFile(const char *fname, uint32_t len, uint8_t init_value) { - if (!ufs_type) { return false; } + if (!ffs_type) { return false; } File file = ffsp->open(fname, "w"); if (!file) { @@ -319,7 +314,7 @@ bool TfsInitFile(const char *fname, uint32_t len, uint8_t init_value) { } bool TfsLoadFile(const char *fname, uint8_t *buf, uint32_t len) { - if (!ufs_type) { return false; } + if (!ffs_type) { return false; } if (!TfsFileExists(fname)) { return false; } File file = ffsp->open(fname, "r"); @@ -334,7 +329,7 @@ bool TfsLoadFile(const char *fname, uint8_t *buf, uint32_t len) { } bool TfsDeleteFile(const char *fname) { - if (!ufs_type) { return false; } + if (!ffs_type) { return false; } if (!ffsp->remove(fname)) { AddLog_P(LOG_LEVEL_INFO, PSTR("TFS: Delete failed")); @@ -354,24 +349,48 @@ void (* const kUFSCommand[])(void) PROGMEM = { &UFSInfo, &UFSType, &UFSSize, &UFSFree, &UFSDelete}; void UFSInfo(void) { - Response_P(PSTR("{\"Ufs\":{\"Type\":%d,\"Size\":%d,\"Free\":%d}}"), ufs_type, UfsInfo(0, 0), UfsInfo(1, 0)); + Response_P(PSTR("{\"Ufs\":{\"Type\":%d,\"Size\":%d,\"Free\":%d}"), ufs_type, UfsInfo(0, 0), UfsInfo(1, 0)); + if (ffs_type && (ffs_type != ufs_type)) { + ResponseAppend_P(PSTR(",{\"Type\":%d,\"Size\":%d,\"Free\":%d}"), ffs_type, UfsInfo(0, 1), UfsInfo(1, 1)); + } + ResponseJsonEnd(); } void UFSType(void) { - ResponseCmndNumber(ufs_type); + if (ffs_type && (ffs_type != ufs_type)) { + Response_P(PSTR("{\"%s\":[%d,%d]}"), XdrvMailbox.command, ufs_type, ffs_type); + } else { + ResponseCmndNumber(ufs_type); + } } void UFSSize(void) { - ResponseCmndNumber(UfsInfo(0, 0)); + if (ffs_type && (ffs_type != ufs_type)) { + Response_P(PSTR("{\"%s\":[%d,%d]}"), XdrvMailbox.command, UfsInfo(0, 0), UfsInfo(0, 1)); + } else { + ResponseCmndNumber(UfsInfo(0, 0)); + } } void UFSFree(void) { - ResponseCmndNumber(UfsInfo(1, 0)); + if (ffs_type && (ffs_type != ufs_type)) { + Response_P(PSTR("{\"%s\":[%d,%d]}"), XdrvMailbox.command, UfsInfo(1, 0), UfsInfo(1, 1)); + } else { + ResponseCmndNumber(UfsInfo(1, 0)); + } } void UFSDelete(void) { + // UfsDelete sdcard or flashfs file if only one of them available + // UfsDelete2 flashfs file if available if (XdrvMailbox.data_len > 0) { - if (!TfsDeleteFile(XdrvMailbox.data)) { + bool result = false; + if (ffs_type && (ffs_type != ufs_type) && (2 == XdrvMailbox.index)) { + result = TfsDeleteFile(XdrvMailbox.data); + } else { + result = (ufs_type && ufsp->remove(XdrvMailbox.data)); + } + if (!result) { ResponseCmndChar(D_JSON_FAILED); } else { ResponseCmndDone(); From f1d15c015c927decdeef687de92d8b54bfbe299d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 15 Jan 2021 16:19:56 +0100 Subject: [PATCH 64/71] Fix ESP8266 SPI detection --- tasmota/support_tasmota.ino | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 3ac17a490..e4ae34177 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1625,8 +1625,8 @@ void GpioInit(void) if (!TasmotaGlobal.soft_spi_enabled) { bool valid_cs = (ValidSpiPinUsed(GPIO_SPI_CS) || ValidSpiPinUsed(GPIO_RC522_CS) || - ValidSpiPinUsed(GPIO_NRF24_CS) || - ValidSpiPinUsed(GPIO_ILI9341_CS) || + (ValidSpiPinUsed(GPIO_NRF24_CS) && ValidSpiPinUsed(GPIO_NRF24_DC)) || + (ValidSpiPinUsed(GPIO_ILI9341_CS) && ValidSpiPinUsed(GPIO_ILI9341_DC)) || ValidSpiPinUsed(GPIO_EPAPER29_CS) || ValidSpiPinUsed(GPIO_EPAPER42_CS) || ValidSpiPinUsed(GPIO_ILI9488_CS) || @@ -1634,17 +1634,11 @@ void GpioInit(void) ValidSpiPinUsed(GPIO_RA8876_CS) || ValidSpiPinUsed(GPIO_ST7789_DC) || // ST7789 CS may be omitted so chk DC too ValidSpiPinUsed(GPIO_ST7789_CS) || - ValidSpiPinUsed(GPIO_SSD1331_CS) || + (ValidSpiPinUsed(GPIO_SSD1331_CS) && ValidSpiPinUsed(GPIO_SSD1331_DC)) || ValidSpiPinUsed(GPIO_SDCARD_CS) ); - bool valid_dc = (ValidSpiPinUsed(GPIO_SPI_DC) || - ValidSpiPinUsed(GPIO_NRF24_DC) || - ValidSpiPinUsed(GPIO_ILI9341_DC) || - ValidSpiPinUsed(GPIO_ST7789_DC) || - ValidSpiPinUsed(GPIO_SSD1331_DC) - ); // If SPI_CS and/or SPI_DC is used they must be valid - TasmotaGlobal.spi_enabled = (valid_cs && valid_dc) ? SPI_MOSI_MISO : SPI_NONE; + TasmotaGlobal.spi_enabled = (valid_cs) ? SPI_MOSI_MISO : SPI_NONE; if (TasmotaGlobal.spi_enabled) { TasmotaGlobal.my_module.io[12] = AGPIO(GPIO_SPI_MISO); SetPin(12, AGPIO(GPIO_SPI_MISO)); From 86cd22e95f60d27a148ebe77108efdd6695cde58 Mon Sep 17 00:00:00 2001 From: Vic Date: Fri, 15 Jan 2021 16:44:59 +0100 Subject: [PATCH 65/71] D_COUNT is used as a noun, not as a verb --- tasmota/language/de_DE.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index 3ae7a842d..161f31482 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -73,7 +73,7 @@ #define D_COMMAND "Befehl" #define D_CONNECTED "verbunden" #define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "zählen" +#define D_COUNT "Anzahl" // used as a noun throughout #define D_COUNTER "Zähler" #define D_CT_POWER "CT Power" #define D_CURRENT "Strom" // As in Voltage and Current From cc43530639e7eab46a560dccea9e90aaae6a9123 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 15 Jan 2021 18:23:05 +0100 Subject: [PATCH 66/71] ESP32 support for TLS MQTT using BearSSL (same as ESP8266) --- CHANGELOG.md | 1 + tasmota/StackThunk_light.cpp | 3 ++ tasmota/WiFiClientSecureLightBearSSL.cpp | 55 +++++++++++++++++++++--- tasmota/WiFiClientSecureLightBearSSL.h | 10 +++++ tasmota/xdrv_02_mqtt.ino | 5 +++ 5 files changed, 68 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7e207f17..79e41be9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. - Support for BS814A-2 8-button touch buttons by Peter Franck (#10447) - Support for up to 4 I2C SEESAW_SOIL Capacitance & Temperature sensors by Peter Franck (#10481) - ESP8266 Support for 2MB and up linker files with 1MB and up LittleFS +- ESP32 support for TLS MQTT using BearSSL (same as ESP8266) ### Breaking Changed - ESP32 switch from default SPIFFS to default LittleFS file system loosing current (zigbee) files diff --git a/tasmota/StackThunk_light.cpp b/tasmota/StackThunk_light.cpp index 8f8b9a23a..b85e19033 100644 --- a/tasmota/StackThunk_light.cpp +++ b/tasmota/StackThunk_light.cpp @@ -28,6 +28,7 @@ #include "my_user_config.h" #include "tasmota_configurations.h" +#if defined(ESP8266) && defined(USE_TLS) #include #include #include "StackThunk_light.h" @@ -145,3 +146,5 @@ void stack_thunk_light_fatal_overflow() } }; + +#endif \ No newline at end of file diff --git a/tasmota/WiFiClientSecureLightBearSSL.cpp b/tasmota/WiFiClientSecureLightBearSSL.cpp index f91d96cfc..6d7ed37b4 100755 --- a/tasmota/WiFiClientSecureLightBearSSL.cpp +++ b/tasmota/WiFiClientSecureLightBearSSL.cpp @@ -22,7 +22,7 @@ #include "my_user_config.h" #include "tasmota_configurations.h" -#if defined(ESP8266) && defined(USE_TLS) +#if defined(USE_TLS) // #define DEBUG_TLS // #define DEBUG_ESP_SSL @@ -47,7 +47,9 @@ extern "C" { #include "lwip/tcp.h" #include "lwip/inet.h" #include "lwip/netif.h" -#include +#ifdef ESP8266 + #include +#endif #include "c_types.h" #include @@ -57,11 +59,15 @@ extern "C" { #include "coredecls.h" #define LOG_HEAP_SIZE(a) _Log_heap_size(a) void _Log_heap_size(const char *msg) { +#ifdef ESP8266 register uint32_t *sp asm("a1"); int freestack = 4 * (sp - g_pcont->stack); Serial.printf("%s %d, Fragmentation=%d, Thunkstack=%d, Free stack=%d, FreeContStack=%d\n", msg, ESP.getFreeHeap(), ESP.getHeapFragmentation(), stack_thunk_light_get_max_usage(), freestack, ESP.getFreeContStack()); +#elif defined(ESP32) + Serial.printf("> Heap %s = %d\n", msg, uxTaskGetStackHighWaterMark(nullptr)); +#endif } #else #define LOG_HEAP_SIZE(a) @@ -71,6 +77,7 @@ void _Log_heap_size(const char *msg) { extern uint32_t UtcTime(void); extern uint32_t CfgTime(void); +#ifdef ESP8266 // Stack thunk is not needed with ESP32 // Stack thunked versions of calls // Initially in BearSSLHelpers.h extern "C" { @@ -164,6 +171,8 @@ unsigned char *min_br_ssl_engine_sendrec_buf(const br_ssl_engine_context *cc, si #define br_ssl_engine_sendrec_ack min_br_ssl_engine_sendrec_ack #define br_ssl_engine_sendrec_buf min_br_ssl_engine_sendrec_buf +#endif // ESP8266 + //#define DEBUG_ESP_SSL #ifdef DEBUG_ESP_SSL //#define DEBUG_BSSL(fmt, ...) DEBUG_ESP_PORT.printf_P((PGM_P)PSTR( "BSSL:" fmt), ## __VA_ARGS__) @@ -201,19 +210,23 @@ void WiFiClientSecure_light::_clear() { // Constructor WiFiClientSecure_light::WiFiClientSecure_light(int recv, int xmit) : WiFiClient() { _clear(); -LOG_HEAP_SIZE("StackThunk before"); + // LOG_HEAP_SIZE("StackThunk before"); //stack_thunk_light_add_ref(); -LOG_HEAP_SIZE("StackThunk after"); + // LOG_HEAP_SIZE("StackThunk after"); // now finish the setup setBufferSizes(recv, xmit); // reasonable minimum allocateBuffers(); } WiFiClientSecure_light::~WiFiClientSecure_light() { +#ifdef ESP8266 if (_client) { _client->unref(); _client = nullptr; } +#elif defined(ESP32) + stop(); +#endif //_cipher_list = nullptr; // std::shared will free if last reference _freeSSL(); } @@ -258,6 +271,7 @@ void WiFiClientSecure_light::setBufferSizes(int recv, int xmit) { _iobuf_out_size = xmit; } +#ifdef ESP8266 bool WiFiClientSecure_light::stop(unsigned int maxWaitMs) { bool ret = WiFiClient::stop(maxWaitMs); // calls our virtual flush() _freeSSL(); @@ -268,6 +282,17 @@ bool WiFiClientSecure_light::flush(unsigned int maxWaitMs) { (void) _run_until(BR_SSL_SENDAPP); return WiFiClient::flush(maxWaitMs); } +#elif defined(ESP32) +void WiFiClientSecure_light::stop(void) { + WiFiClient::stop(); // calls our virtual flush() + _freeSSL(); +} + +void WiFiClientSecure_light::flush(void) { + (void) _run_until(BR_SSL_SENDAPP); + WiFiClient::flush(); +} +#endif int WiFiClientSecure_light::connect(IPAddress ip, uint16_t port) { DEBUG_BSSL("connect(%s,%d)", ip.toString().c_str(), port); @@ -307,7 +332,11 @@ void WiFiClientSecure_light::_freeSSL() { } bool WiFiClientSecure_light::_clientConnected() { +#ifdef ESP8266 return (_client && _client->state() == ESTABLISHED); +#elif defined(ESP32) + return WiFiClient::connected(); +#endif } uint8_t WiFiClientSecure_light::connected() { @@ -489,7 +518,7 @@ size_t WiFiClientSecure_light::peekBytes(uint8_t *buffer, size_t length) { achieved, this function returns 0. On error, it returns -1. */ int WiFiClientSecure_light::_run_until(unsigned target, bool blocking) { -//LOG_HEAP_SIZE("_run_until 1"); + //LOG_HEAP_SIZE("_run_until 1"); if (!ctx_present()) { DEBUG_BSSL("_run_until: Not connected\n"); return -1; @@ -506,9 +535,15 @@ int WiFiClientSecure_light::_run_until(unsigned target, bool blocking) { return -1; } +#ifdef ESP8266 if (!(_client->state() == ESTABLISHED) && !WiFiClient::available()) { return (state & target) ? 0 : -1; } +#elif defined(ESP32) + if (!_clientConnected() && !WiFiClient::available()) { + return (state & target) ? 0 : -1; + } +#endif /* If there is some record data to send, do it. This takes @@ -898,12 +933,16 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { do { // used to exit on Out of Memory error and keep all cleanup code at the same place // ============================================================ // allocate Thunk stack, move to alternate stack and initialize +#ifdef ESP8266 stack_thunk_light_add_ref(); +#endif // ESP8266 LOG_HEAP_SIZE("Thunk allocated"); DEBUG_BSSL("_connectSSL: start connection\n"); _freeSSL(); clearLastError(); - if (!stack_thunk_light_get_stack_bot()) break; +#ifdef ESP8266 + if (!stack_thunk_light_get_stack_bot()) break; +#endif // ESP8266 _ctx_present = true; _eng = &_sc->eng; // Allocation/deallocation taken care of by the _sc shared_ptr @@ -964,10 +1003,12 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { } #endif LOG_HEAP_SIZE("_connectSSL.end"); +#ifdef ESP8266 _max_thunkstack_use = stack_thunk_light_get_max_usage(); stack_thunk_light_del_ref(); //stack_thunk_light_repaint(); LOG_HEAP_SIZE("_connectSSL.end, freeing StackThunk"); +#endif // ESP8266 #ifdef USE_MQTT_TLS_CA_CERT free(x509_minimal); @@ -982,7 +1023,9 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { // if we arrived here, this means we had an OOM error, cleaning up setLastError(ERR_OOM); DEBUG_BSSL("_connectSSL: Out of memory\n"); +#ifdef ESP8266 stack_thunk_light_del_ref(); +#endif #ifdef USE_MQTT_TLS_CA_CERT free(x509_minimal); #else diff --git a/tasmota/WiFiClientSecureLightBearSSL.h b/tasmota/WiFiClientSecureLightBearSSL.h index f480a9d42..f88a9f17f 100755 --- a/tasmota/WiFiClientSecureLightBearSSL.h +++ b/tasmota/WiFiClientSecureLightBearSSL.h @@ -43,7 +43,11 @@ class WiFiClientSecure_light : public WiFiClient { uint8_t connected() override; size_t write(const uint8_t *buf, size_t size) override; + #ifdef ESP8266 size_t write_P(PGM_P buf, size_t size) override; + #else + size_t write_P(PGM_P buf, size_t size); + #endif size_t write(const char *buf) { return write((const uint8_t*)buf, strlen(buf)); } @@ -55,11 +59,17 @@ class WiFiClientSecure_light : public WiFiClient { int available() override; int read() override; int peek() override; + #ifdef ESP8266 size_t peekBytes(uint8_t *buffer, size_t length) override; bool flush(unsigned int maxWaitMs); bool stop(unsigned int maxWaitMs); void flush() override { (void)flush(0); } void stop() override { (void)stop(0); } + #else + size_t peekBytes(uint8_t *buffer, size_t length); + void flush() override; + void stop() override; + #endif // Only check SHA1 fingerprint of public key void setPubKeyFingerprint(const uint8_t *f1, const uint8_t *f2, diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 15e99f352..9a0acba75 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -679,8 +679,13 @@ void MqttReconnect(void) { if (MqttClient.connect(TasmotaGlobal.mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, lwt_retain, TasmotaGlobal.mqtt_data, MQTT_CLEAN_SESSION)) { #ifdef USE_MQTT_TLS if (Mqtt.mqtt_tls) { +#ifdef ESP8266 AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connected in %d ms, max ThunkStack used %d"), millis() - mqtt_connect_time, tlsClient->getMaxThunkStackUse()); +#elif defined(ESP32) + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connected in %d ms, stack low mark %d"), + millis() - mqtt_connect_time, uxTaskGetStackHighWaterMark(nullptr)); +#endif if (!tlsClient->getMFLNStatus()) { AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "MFLN not supported by TLS server")); } From 6d0005cc290975a0da56d2ccf11dd726bafc02d6 Mon Sep 17 00:00:00 2001 From: Vic Date: Fri, 15 Jan 2021 19:02:09 +0100 Subject: [PATCH 67/71] some more improvements on german strings --- tasmota/language/de_DE.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index 161f31482..071bfaaa0 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -143,8 +143,8 @@ #define D_POWERUSAGE_REACTIVE "Blindleistung" #define D_PRESSURE "Luftdruck" #define D_PRESSUREATSEALEVEL "Luftdruck auf Meereshöhe" -#define D_PROGRAM_FLASH_SIZE "Ges. Flash Speicher" -#define D_PROGRAM_SIZE "Ben. Flash Speicher" +#define D_PROGRAM_FLASH_SIZE "Flash nutzbar" +#define D_PROGRAM_SIZE "Größe Programm" #define D_PROJECT "Projekt" #define D_RAIN "Regen" #define D_RANGE "Bereich" @@ -333,7 +333,7 @@ #define D_PROGRAM_VERSION "Tasmota Version" #define D_BUILD_DATE_AND_TIME "Build-Datum & -Uhrzeit" #define D_CORE_AND_SDK_VERSION "Core-/SDK-Version" -#define D_FLASH_WRITE_COUNT "Anz. Flash Schreibzugriffe" +#define D_FLASH_WRITE_COUNT "Anz. Flash-Schreibzyklen" #define D_MAC_ADDRESS "MAC-Adresse" #define D_MQTT_HOST "MQTT Host" #define D_MQTT_PORT "MQTT Port" @@ -343,12 +343,12 @@ #define D_MQTT_GROUP_TOPIC "MQTT Group Topic" #define D_MQTT_FULL_TOPIC "MQTT Full Topic" #define D_MQTT_NO_RETAIN "MQTT No Retain" -#define D_MDNS_DISCOVERY "mDNS-Ermittlung" -#define D_MDNS_ADVERTISE "mDNS-Bekanntmachung" +#define D_MDNS_DISCOVERY "mDNS-Erkennung" +#define D_MDNS_ADVERTISE "mDNS-Freigaben" #define D_ESP_CHIP_ID "ESP Chip ID" #define D_FLASH_CHIP_ID "Flash Chip ID" -#define D_FLASH_CHIP_SIZE "Realer Flash Speicher" -#define D_FREE_PROGRAM_SPACE "Verf. Flash Speicher" +#define D_FLASH_CHIP_SIZE "Größe Flash-Chip" +#define D_FREE_PROGRAM_SPACE "Flash frei" #define D_UPGRADE_BY_WEBSERVER "Update über Web-Server" #define D_OTA_URL "OTA-URL" From af798b40e20cee018dfa857670d3d46adbc180b6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 15 Jan 2021 20:59:56 +0100 Subject: [PATCH 68/71] fix compile ESP8266 --- pio-tools/download_fs.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pio-tools/download_fs.py b/pio-tools/download_fs.py index f43bec128..4343adee3 100644 --- a/pio-tools/download_fs.py +++ b/pio-tools/download_fs.py @@ -24,8 +24,9 @@ platform = env.PioPlatform() board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") # Hack for using mklittlefs instead of mkspiffs -> needed since littlefs is not supported with this for ESP32 -#print("Replace MKSPIFFSTOOL with mklittlefs") -env.Replace( MKSPIFFSTOOL=platform.get_package_dir("tool-mklittlefs") + '/mklittlefs' ) +if env["PIOPLATFORM"] == "espressif32": + #print("Replace MKSPIFFSTOOL with mklittlefs") + env.Replace( MKSPIFFSTOOL=platform.get_package_dir("tool-mklittlefs") + '/mklittlefs' ) # needed for later AutodetectUploadPort(env) From 9270e956d4c4297199e1cc93602155275da886b5 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sat, 16 Jan 2021 10:55:40 +0100 Subject: [PATCH 69/71] Zigbee increase timeout to 5s for first command --- tasmota/xdrv_23_zigbee_7_0_statemachine.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_23_zigbee_7_0_statemachine.ino b/tasmota/xdrv_23_zigbee_7_0_statemachine.ino index 7c00cfb42..cc23c7a92 100644 --- a/tasmota/xdrv_23_zigbee_7_0_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_0_statemachine.ino @@ -785,7 +785,7 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = { ZI_WAIT_UNTIL(5000, ZBR_RSTACK) // wait for RSTACK message // Init device and probe version - ZI_SEND(ZBS_VERSION) ZI_WAIT_RECV_FUNC(1000, ZBR_VERSION, &EZ_ReceiveCheckVersion) // check EXT PAN ID + ZI_SEND(ZBS_VERSION) ZI_WAIT_RECV_FUNC(5000, ZBR_VERSION, &EZ_ReceiveCheckVersion) // check EXT PAN ID // configure EFR32 ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, kConfiguredCoord) From 3bb15cda2a95731fabfd778ff2d13fcb60395d25 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 16 Jan 2021 11:18:40 +0100 Subject: [PATCH 70/71] Fix ESP32 MLX90640 compilation --- tasmota/xdrv_43_mlx90640.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_43_mlx90640.ino b/tasmota/xdrv_43_mlx90640.ino index 18255c079..53cbcfe07 100644 --- a/tasmota/xdrv_43_mlx90640.ino +++ b/tasmota/xdrv_43_mlx90640.ino @@ -418,12 +418,12 @@ void MLX90640HandleWebGuiResponse(void){ if(_line==0){_buf[0]=1000+MLX90640.Ta;} //ambient temperature modulation hack else{_buf[0]=(float)_line;} memcpy((char*)&_buf[1],(char*)&MLX90640.To[_line*64],64*4); - Webserver->send(200,PSTR("application/octet-stream"),(const char*)&_buf,65*4); + Webserver->send_P(200,PSTR("application/octet-stream"),(const char*)&_buf,65*4); return; } WebGetArg("up", tmp, sizeof(tmp)); // update POI to browser if (strlen(tmp)==1) { - Webserver->send(200,PSTR("application/octet-stream"),(const char*)&MLX90640.pois,MLX90640_POI_NUM*2); + Webserver->send_P(200,PSTR("application/octet-stream"),(const char*)&MLX90640.pois,MLX90640_POI_NUM*2); return; } else if (strlen(tmp)>2) { // receive updated POI from browser From 7957e0c8998a3d5aa155a54765df9ef6fcf4b6c3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 16 Jan 2021 11:53:36 +0100 Subject: [PATCH 71/71] add tool-mklittlefs to tasmota32solo1 --- platformio_override_sample.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index e46754e7a..4db6a41b3 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -166,6 +166,7 @@ lib_extra_dirs = [env:tasmota32solo1] extends = env:tasmota32 platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/raw/framework-arduinoespressif32/framework-arduinoespressif32-release_v3.3-solo1-4b325f52e.tar.gz + platformio/tool-mklittlefs @ ~1.203.200522 platformio/tool-esptoolpy @ ~1.30000.0 build_unflags = ${esp32_defaults.build_unflags} build_flags = ${common32.build_flags}