From 006e60650909db03ce6564e3a03b8414233e37f4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 14 Apr 2020 18:45:42 +0200 Subject: [PATCH 01/70] ESP32 board partition --- platformio_tasmota_env32.ini | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index fb280f1bc..4f6661c17 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -4,6 +4,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -22,6 +23,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -40,6 +42,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -58,6 +61,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -76,6 +80,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -94,6 +99,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -112,6 +118,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -130,6 +137,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -148,6 +156,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -166,6 +175,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -184,6 +194,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -202,6 +213,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -220,6 +232,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -238,6 +251,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -256,6 +270,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -274,6 +289,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -292,6 +308,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -310,6 +327,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -328,6 +346,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -346,6 +365,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -364,6 +384,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -382,6 +403,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -400,6 +422,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -418,6 +441,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -436,6 +460,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -454,6 +479,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -472,6 +498,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -490,6 +517,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -508,6 +536,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} @@ -526,6 +555,7 @@ platform = ${common32.platform} platform_packages = ${common32.platform_packages} board = ${common32.board} board_build.ldscript = ${common32.board_build.ldscript} +board_build.partitions = ${common32.board_build.partitions} board_build.flash_mode = ${common32.board_build.flash_mode} board_build.f_cpu = ${common32.board_build.f_cpu} monitor_speed = ${common32.monitor_speed} From 757d2bb93d9dd74cf036fa1032c996f859819fa0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 14 Apr 2020 18:46:26 +0200 Subject: [PATCH 02/70] Add files via upload --- esp32_partition_app2000k_spiffs32k.csv | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 esp32_partition_app2000k_spiffs32k.csv diff --git a/esp32_partition_app2000k_spiffs32k.csv b/esp32_partition_app2000k_spiffs32k.csv new file mode 100644 index 000000000..01505a86b --- /dev/null +++ b/esp32_partition_app2000k_spiffs32k.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x1F4000, +app1, app, ota_1, 0x20400, 0x1F4000, +spiffs, data, spiffs, 0x3F8000,0x8000, From 2e2675db73e3d669bbb29eea8f0c95fbf1791e53 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 14 Apr 2020 18:53:05 +0200 Subject: [PATCH 03/70] Delete esp32_partition_app2000k_spiffs32k.csv --- esp32_partition_app2000k_spiffs32k.csv | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 esp32_partition_app2000k_spiffs32k.csv diff --git a/esp32_partition_app2000k_spiffs32k.csv b/esp32_partition_app2000k_spiffs32k.csv deleted file mode 100644 index 01505a86b..000000000 --- a/esp32_partition_app2000k_spiffs32k.csv +++ /dev/null @@ -1,6 +0,0 @@ -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x5000, -otadata, data, ota, 0xe000, 0x2000, -app0, app, ota_0, 0x10000, 0x1F4000, -app1, app, ota_1, 0x20400, 0x1F4000, -spiffs, data, spiffs, 0x3F8000,0x8000, From 8fab7ddf2830475f681099528b8b0851838567c3 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 14 Apr 2020 18:53:28 +0200 Subject: [PATCH 04/70] Add files via upload --- esp32_partition_app2000k_spiffs32k.csv | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 esp32_partition_app2000k_spiffs32k.csv diff --git a/esp32_partition_app2000k_spiffs32k.csv b/esp32_partition_app2000k_spiffs32k.csv new file mode 100644 index 000000000..2d024922a --- /dev/null +++ b/esp32_partition_app2000k_spiffs32k.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x1F4000, +app1, app, ota_1, 0x204000, 0x1F4000, +spiffs, data, spiffs, 0x3F8000,0x8000, From 5c49a89d21f8d3bdb9e0cddc2191342e495673d0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 14 Apr 2020 19:05:07 +0200 Subject: [PATCH 05/70] Update platformio_override_sample.ini --- platformio_override_sample.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index aa979497a..8a2ec07d6 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -230,6 +230,7 @@ platform = espressif32@1.12.0 platform_packages = board = wemos_d1_mini32 board_build.ldscript = esp32_out.ld +board_build.partitions = esp32_partition_app1810k_spiffs320k.csv board_build.flash_mode = ${common.board_build.flash_mode} board_build.f_cpu = ${common.board_build.f_cpu} build_unflags = ${common.build_unflags} From 6a0c2414216d72a6175af2e2f8f6060b6afc7dbd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 14 Apr 2020 19:05:30 +0200 Subject: [PATCH 06/70] Delete esp32_partition_app2000k_spiffs32k.csv --- esp32_partition_app2000k_spiffs32k.csv | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 esp32_partition_app2000k_spiffs32k.csv diff --git a/esp32_partition_app2000k_spiffs32k.csv b/esp32_partition_app2000k_spiffs32k.csv deleted file mode 100644 index 2d024922a..000000000 --- a/esp32_partition_app2000k_spiffs32k.csv +++ /dev/null @@ -1,6 +0,0 @@ -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x5000, -otadata, data, ota, 0xe000, 0x2000, -app0, app, ota_0, 0x10000, 0x1F4000, -app1, app, ota_1, 0x204000, 0x1F4000, -spiffs, data, spiffs, 0x3F8000,0x8000, From 037d3791fadaebc7b226a72202396274842b1eb8 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 14 Apr 2020 19:05:50 +0200 Subject: [PATCH 07/70] Add files via upload --- esp32_partition_app1810k_spiffs320k.csv | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 esp32_partition_app1810k_spiffs320k.csv diff --git a/esp32_partition_app1810k_spiffs320k.csv b/esp32_partition_app1810k_spiffs320k.csv new file mode 100644 index 000000000..49f6c1150 --- /dev/null +++ b/esp32_partition_app1810k_spiffs320k.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x1D0000, +app1, app, ota_1, 0x1E0000, 0x1D0000, +spiffs, data, spiffs, 0x3B0000,0x50000, From 8160866adaf598cee8d167eed0eaf662dbf43618 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 14 Apr 2020 20:15:33 +0200 Subject: [PATCH 08/70] Delete esp32_partition_app1810k_spiffs320k.csv --- esp32_partition_app1810k_spiffs320k.csv | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 esp32_partition_app1810k_spiffs320k.csv diff --git a/esp32_partition_app1810k_spiffs320k.csv b/esp32_partition_app1810k_spiffs320k.csv deleted file mode 100644 index 49f6c1150..000000000 --- a/esp32_partition_app1810k_spiffs320k.csv +++ /dev/null @@ -1,6 +0,0 @@ -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x5000, -otadata, data, ota, 0xe000, 0x2000, -app0, app, ota_0, 0x10000, 0x1D0000, -app1, app, ota_1, 0x1E0000, 0x1D0000, -spiffs, data, spiffs, 0x3B0000,0x50000, From 639c477550f92d2fb6dfbb034d2272f848af2f7d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 14 Apr 2020 20:16:57 +0200 Subject: [PATCH 09/70] Add files via upload --- esp32_partition_app1984k_spiffs64k.csv | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 esp32_partition_app1984k_spiffs64k.csv diff --git a/esp32_partition_app1984k_spiffs64k.csv b/esp32_partition_app1984k_spiffs64k.csv new file mode 100644 index 000000000..3b428f9a9 --- /dev/null +++ b/esp32_partition_app1984k_spiffs64k.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x1F0000, +app1, app, ota_1, 0x200000, 0x1F0000, +spiffs, data, spiffs, 0x3F0000,0x10000, From 817bc47f04f95c543ac838282f00be6f2d6b1498 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 14 Apr 2020 20:18:00 +0200 Subject: [PATCH 10/70] Spiffs 64k --- 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 8a2ec07d6..11c0d7ee0 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -230,7 +230,7 @@ platform = espressif32@1.12.0 platform_packages = board = wemos_d1_mini32 board_build.ldscript = esp32_out.ld -board_build.partitions = esp32_partition_app1810k_spiffs320k.csv +board_build.partitions = esp32_partition_app1984k_spiffs64k.csv board_build.flash_mode = ${common.board_build.flash_mode} board_build.f_cpu = ${common.board_build.f_cpu} build_unflags = ${common.build_unflags} From 639968c0abd39ef7efd521caeb53bc00732eb8d2 Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Tue, 14 Apr 2020 18:14:16 -0300 Subject: [PATCH 11/70] Fix Set)ption13 on Buttons V2 --- tasmota/support_button_v2.ino | 51 ++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/tasmota/support_button_v2.ino b/tasmota/support_button_v2.ino index 0e706b44f..abf656bce 100644 --- a/tasmota/support_button_v2.ino +++ b/tasmota/support_button_v2.ino @@ -118,8 +118,6 @@ void ButtonHandler(void) uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; // Extent hold time factor in case of iminnent Reset command uint16_t loops_per_second = 1000 / Settings.button_debounce; // ButtonDebounce (50) char scmnd[20]; - char scommand[CMDSZ]; - char stopic[TOPSZ]; // uint8_t maxdev = (devices_present > MAX_KEYS) ? MAX_KEYS : devices_present; // for (uint32_t button_index = 0; button_index < maxdev; button_index++) { @@ -190,12 +188,15 @@ void ButtonHandler(void) if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { - if (Settings.flag.button_single && !Settings.flag3.mqtt_buttons) { // SetOption13 (0) - Allow only single button press for immediate action, SetOption73 (0) - Decouple button from relay and send just mqtt topic - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1); - if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set - ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally + if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action, SetOption73 (0) - Decouple button from relay and send just mqtt topic + if (!Settings.flag3.mqtt_buttons) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1); + if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set + ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally + } + } else { + MqttButtonTopic(button_index +1, 1, 0); // SetOption73 (0) - Decouple button from relay and send just mqtt topic } - } else { Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, Button.press_counter[button_index]); @@ -217,12 +218,10 @@ void ButtonHandler(void) if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button hold Button.press_counter[button_index] = 0; if (Settings.flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic - snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_index +1); - GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P(S_JSON_COMMAND_SVALUE, "ACTION", GetStateText(3)); - MqttPublish(stopic); - } - SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); // Execute Hold command via MQTT if ButtonTopic is set + MqttButtonTopic(button_index +1, 3, 1); + } else { + SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); // Execute Hold command via MQTT if ButtonTopic is set + } } else { if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer Button.press_counter[button_index] = 0; @@ -287,15 +286,7 @@ void ButtonHandler(void) } if (Settings.flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic if (Button.press_counter[button_index] >= 1 && Button.press_counter[button_index] <= 5) { - char mqttstate[7]; - - GetTextIndexed(mqttstate, sizeof(mqttstate), Button.press_counter[button_index], kMultiPress); - SendKey(KEY_BUTTON, button_index +1, Button.press_counter[button_index] +9); - snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_index +1); - GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P(S_JSON_COMMAND_SVALUE, "ACTION", mqttstate); - MqttPublish(stopic); - + MqttButtonTopic(button_index +1, Button.press_counter[button_index], 0); } } } @@ -306,12 +297,28 @@ void ButtonHandler(void) } } } + } } Button.last_state[button_index] = button; } } +void MqttButtonTopic(uint8_t index, uint8_t action, uint8_t hold) +{ + char scommand[CMDSZ]; + char stopic[TOPSZ]; + char mqttstate[7]; + + GetTextIndexed(mqttstate, sizeof(mqttstate), action, kMultiPress); + + SendKey(KEY_BUTTON, index, (hold) ? 3 : action +9); + snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), index); + GetTopic_P(stopic, STAT, mqtt_topic, scommand); + Response_P(S_JSON_COMMAND_SVALUE, "ACTION", (hold) ? SettingsText(SET_STATE_TXT4) : mqttstate); + MqttPublish(stopic); +} + void ButtonLoop(void) { if (Button.present) { From ad18dc76e137170125e68d8b3f78bc89d8d0a5ec Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Tue, 14 Apr 2020 20:24:34 -0300 Subject: [PATCH 12/70] Update support_button_v2.ino --- tasmota/support_button_v2.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/support_button_v2.ino b/tasmota/support_button_v2.ino index abf656bce..d345b58d2 100644 --- a/tasmota/support_button_v2.ino +++ b/tasmota/support_button_v2.ino @@ -304,7 +304,7 @@ void ButtonHandler(void) } } -void MqttButtonTopic(uint8_t index, uint8_t action, uint8_t hold) +void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold) { char scommand[CMDSZ]; char stopic[TOPSZ]; @@ -312,8 +312,8 @@ void MqttButtonTopic(uint8_t index, uint8_t action, uint8_t hold) GetTextIndexed(mqttstate, sizeof(mqttstate), action, kMultiPress); - SendKey(KEY_BUTTON, index, (hold) ? 3 : action +9); - snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), index); + SendKey(KEY_BUTTON, button_id, (hold) ? 3 : action +9); + snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_id); GetTopic_P(stopic, STAT, mqtt_topic, scommand); Response_P(S_JSON_COMMAND_SVALUE, "ACTION", (hold) ? SettingsText(SET_STATE_TXT4) : mqttstate); MqttPublish(stopic); From 5f6c10650795d1b20996227eb0c75321ce7b3fef Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Wed, 15 Apr 2020 08:11:54 +0200 Subject: [PATCH 13/70] scripter esp32 script size expansion --- tasmota/xdrv_10_scripter.ino | 54 ++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index e086adedb..88400ff0d 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -65,6 +65,35 @@ keywords if then else endif, or, and are better readable for beginners (others m uint32_t EncodeLightId(uint8_t relay_id); uint32_t DecodeLightId(uint32_t hue_id); +#if defined(ESP32) && defined(ESP32_SCRIPT_SIZE) && !defined(USE_24C256) && !defined(USE_SCRIPT_FATFS) + +#include "FS.h" +#include "SPIFFS.h" +void SaveFile(const char *name,const uint8_t *buf,uint32_t len) { + File file = SPIFFS.open(name, FILE_WRITE); + if (!file) return; + file.write(buf, len); + file.close(); +} + +#define FORMAT_SPIFFS_IF_FAILED true +uint8_t spiffs_mounted=0; + +void LoadFile(const char *name,uint8_t *buf,uint32_t len) { + if (!spiffs_mounted) { + if(!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED)){ + //Serial.println("SPIFFS Mount Failed"); + return; + } + spiffs_mounted=1; + } + File file = SPIFFS.open(name); + if (!file) return; + file.read(buf, len); + file.close(); +} +#endif + // offsets epoch readings by 1.1.2019 00:00:00 to fit into float with second resolution #define EPOCH_OFFSET 1546300800 @@ -3597,6 +3626,11 @@ void ScriptSaveSettings(void) { } #endif +#if defined(ESP32) && defined(ESP32_SCRIPT_SIZE) && !defined(USE_24C256) && !defined(USE_SCRIPT_FATFS) + if (glob_script_mem.flags&1) { + SaveFile("/script.txt",(uint8_t*)glob_script_mem.script_ram,ESP32_SCRIPT_SIZE); + } +#endif } if (glob_script_mem.script_mem) { @@ -4820,6 +4854,11 @@ bool Xdrv10(uint8_t function) switch (function) { case FUNC_PRE_INIT: +#ifdef USE_WEBCAM + if (Settings.module==ESP32_CAM_AITHINKER) { + webcam_setup(); + } +#endif // set defaults to rules memory glob_script_mem.script_ram=Settings.rules[0]; glob_script_mem.script_size=MAX_SCRIPT_SIZE; @@ -4889,6 +4928,21 @@ bool Xdrv10(uint8_t function) } #endif + +#if defined(ESP32) && defined(ESP32_SCRIPT_SIZE) && !defined(USE_24C256) && !defined(USE_SCRIPT_FATFS) + char *script; + script=(char*)calloc(ESP32_SCRIPT_SIZE+4,1); + if (!script) break; + LoadFile("/script.txt",(uint8_t*)script,ESP32_SCRIPT_SIZE); + glob_script_mem.script_ram=script; + glob_script_mem.script_size=ESP32_SCRIPT_SIZE; + script[ESP32_SCRIPT_SIZE-1]=0; + // use rules storage for permanent vars + glob_script_mem.script_pram=(uint8_t*)Settings.rules[0]; + glob_script_mem.script_pram_size=MAX_SCRIPT_SIZE; + glob_script_mem.flags=1; +#endif + // assure permanent memory is 4 byte aligned { uint32_t ptr=(uint32_t)glob_script_mem.script_pram; ptr&=0xfffffffc; From 7d85ccb793d4255304097fccece9498a68670a61 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Wed, 15 Apr 2020 08:21:43 +0200 Subject: [PATCH 14/70] Update xdrv_10_scripter.ino --- tasmota/xdrv_10_scripter.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 88400ff0d..9199d3b90 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -4854,11 +4854,13 @@ bool Xdrv10(uint8_t function) switch (function) { case FUNC_PRE_INIT: + /* #ifdef USE_WEBCAM if (Settings.module==ESP32_CAM_AITHINKER) { webcam_setup(); } #endif +*/ // set defaults to rules memory glob_script_mem.script_ram=Settings.rules[0]; glob_script_mem.script_size=MAX_SCRIPT_SIZE; From 487f4a9191194cd69934f8a757aba169c05273ac Mon Sep 17 00:00:00 2001 From: VanillaFord <48869131+VanillaFord@users.noreply.github.com> Date: Wed, 15 Apr 2020 09:36:23 +0200 Subject: [PATCH 15/70] if GPIO_SR04_TRIG is not configured use single PIN mode with GPIO_SR04_ECHO only enable single PIN mode for SR04 sensor. If pin GPIO_SR04_TRIG is not configured, use sensor interface in single PIN mode with GPIO_SR04_ECHO only See as depicted in newping library, see: https://bitbucket.org/teckel12/arduino-new-ping/wiki/Home#!single-pin-sketch --- tasmota/xsns_22_sr04.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xsns_22_sr04.ino b/tasmota/xsns_22_sr04.ino index 636992a57..54e1c00f8 100644 --- a/tasmota/xsns_22_sr04.ino +++ b/tasmota/xsns_22_sr04.ino @@ -47,7 +47,7 @@ uint8_t Sr04TModeDetect(void) if (pin[GPIO_SR04_ECHO]>=99) return sr04_type; sr04_echo_pin = pin[GPIO_SR04_ECHO]; - sr04_trig_pin = (pin[GPIO_SR04_TRIG] < 99) ? pin[GPIO_SR04_TRIG] : -1; + sr04_trig_pin = (pin[GPIO_SR04_TRIG] < 99) ? pin[GPIO_SR04_TRIG] : pin[GPIO_SR04_ECHO]; // if GPIO_SR04_TRIG is not configured use single PIN mode with GPIO_SR04_ECHO only sonar_serial = new TasmotaSerial(sr04_echo_pin, sr04_trig_pin, 1); if (sonar_serial->begin(9600,1)) { From 57f836cc9eae8a68b4b7a0212faf8a6613219bdd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 15 Apr 2020 09:58:38 +0200 Subject: [PATCH 16/70] Remove possible Webserver naming ambuigity --- tasmota/Parsing.cpp | 6 +- tasmota/support_flash_log.ino | 8 +- tasmota/xdrv_01_webserver.ino | 176 +++++++++++++++---------------- tasmota/xdrv_02_mqtt.ino | 4 +- tasmota/xdrv_07_domoticz.ino | 4 +- tasmota/xdrv_09_timers.ino | 6 +- tasmota/xdrv_10_scripter.ino | 44 ++++---- tasmota/xdrv_11_knx.ino | 42 ++++---- tasmota/xdrv_20_hue.ino | 12 +-- tasmota/xdrv_21_wemo.ino | 10 +- tasmota/xdrv_23_zigbee_3_hue.ino | 4 +- tasmota/xdrv_28_pcf8574.ino | 8 +- tasmota/xsns_34_hx711.ino | 8 +- tasmota/xsns_60_GPS.ino | 18 ++-- tasmota/xsns_91_prometheus.ino | 2 +- 15 files changed, 178 insertions(+), 174 deletions(-) diff --git a/tasmota/Parsing.cpp b/tasmota/Parsing.cpp index 145b72572..a7665d7b1 100644 --- a/tasmota/Parsing.cpp +++ b/tasmota/Parsing.cpp @@ -19,6 +19,8 @@ Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) */ +#ifdef ESP8266 + // Use patched Parsing.cpp to fix ALEXA parsing issue in v2.4.2 #include #if defined(ARDUINO_ESP8266_RELEASE_2_4_2) @@ -620,4 +622,6 @@ bool ESP8266WebServer::_parseFormUploadAborted(){ return false; } -#endif // ARDUINO_ESP8266_RELEASE \ No newline at end of file +#endif // ARDUINO_ESP8266_RELEASE + +#endif // ESP8266 diff --git a/tasmota/support_flash_log.ino b/tasmota/support_flash_log.ino index cf64de6d5..5f73c4078 100644 --- a/tasmota/support_flash_log.ino +++ b/tasmota/support_flash_log.ino @@ -371,13 +371,13 @@ void FLOG::stopRecording(void){ * * @param size: size of the data entry/record in bytes, i.e. sizeof(myStruct) * @param sendHeader: should implement at least something like: - * @example WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // This is very likely unknown!! - * WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=myfile.txt")); + * @example Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); // This is very likely unknown!! + * Webserver->sendHeader(F("Content-Disposition"), F("attachment; filename=myfile.txt")); * @param sendRecord: will receive the memory address as "uint8_t* addr" and should consume the current entry/record * @example myStruct_t *entry = (myStruct_t*)addr; - * Then make useful Strings and send it, i.e.: WebServer->sendContent_P(myString); + * Then make useful Strings and send it, i.e.: Webserver->sendContent_P(myString); * @param sendFooter: finish the download, should implement at least: - * @example WebServer->sendContent(""); + * @example Webserver->sendContent(""); */ void FLOG::startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter){ diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 178502150..18df7fa4a 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -109,7 +109,7 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "}" "};" "if (rfsh) {" - "x.open('GET','.?m=1'+a,true);" // ?m related to WebServer->hasArg("m") + "x.open('GET','.?m=1'+a,true);" // ?m related to Webserver->hasArg("m") "x.send();" "lt=setTimeout(la,%d);" // Settings.web_refresh "}" @@ -146,7 +146,7 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "eb('l1').innerHTML=s;" "}" "};" - "x.open('GET','.?m=1'+a,true);" // ?m related to WebServer->hasArg("m") + "x.open('GET','.?m=1'+a,true);" // ?m related to Webserver->hasArg("m") "x.send();" "lt=setTimeout(la,%d);" // Settings.web_refresh "}"; @@ -205,7 +205,7 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "sn=t.scrollTop;" "}" "};" - "x.open('GET','cs?c2='+id+o,true);" // Related to WebServer->hasArg("c2") and WebGetArg("c2", stmp, sizeof(stmp)) + "x.open('GET','cs?c2='+id+o,true);" // Related to Webserver->hasArg("c2") and WebGetArg("c2", stmp, sizeof(stmp)) "x.send();" "}" "lt=setTimeout(l,%d);" @@ -301,10 +301,10 @@ const char HTTP_SCRIPT_TEMPLATE[] PROGMEM = "}" #ifdef USE_JAVASCRIPT_ES6 - "sl=()=>ld('tp?m=1',x2);" // ?m related to WebServer->hasArg("m") + "sl=()=>ld('tp?m=1',x2);" // ?m related to Webserver->hasArg("m") #else "function sl(){" - "ld('tp?m=1',x2);" // ?m related to WebServer->hasArg("m") + "ld('tp?m=1',x2);" // ?m related to Webserver->hasArg("m") "}" #endif @@ -325,11 +325,11 @@ const char HTTP_SCRIPT_MODULE2[] PROGMEM = "sk(%d," STR(ADC0_PIN) ");" "}" "function sl(){" - "ld('md?m=1',x1);" // ?m related to WebServer->hasArg("m") - "ld('md?g=1',x2);" // ?g related to WebServer->hasArg("g") + "ld('md?m=1',x1);" // ?m related to Webserver->hasArg("m") + "ld('md?g=1',x2);" // ?g related to Webserver->hasArg("g") // "if(eb('g17')){" "if(eb('g" STR(ADC0_PIN) "')){" - "ld('md?a=1',x3);" // ?a related to WebServer->hasArg("a") + "ld('md?a=1',x3);" // ?a related to Webserver->hasArg("a") "}" "}" "wl(sl);"; @@ -544,7 +544,7 @@ const uint16_t DNS_PORT = 53; enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER, HTTP_MANAGER_RESET_ONLY}; DNSServer *DnsServer; -ESP8266WebServer *WebServer; +ESP8266WebServer *Webserver; struct WEB { String chunk_buffer = ""; // Could be max 2 * CHUNKED_BUFFER_SIZE @@ -561,7 +561,7 @@ struct WEB { // Helper function to avoid code duplication (saves 4k Flash) static void WebGetArg(const char* arg, char* out, size_t max) { - String s = WebServer->arg(arg); + String s = Webserver->arg(arg); strlcpy(out, s.c_str(), max); // out[max-1] = '\0'; // Ensure terminating NUL } @@ -574,7 +574,7 @@ void ShowWebSource(uint32_t source) { if ((source > 0) && (source < SRC_MAX)) { char stemp1[20]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SRC: %s from %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource), WebServer->client().remoteIP().toString().c_str()); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SRC: %s from %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource), Webserver->client().remoteIP().toString().c_str()); } } @@ -589,28 +589,28 @@ void StartWebserver(int type, IPAddress ipweb) { if (!Settings.web_refresh) { Settings.web_refresh = HTTP_REFRESH_TIME; } if (!Web.state) { - if (!WebServer) { - WebServer = new ESP8266WebServer((HTTP_MANAGER == type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT); - WebServer->on("/", HandleRoot); - WebServer->onNotFound(HandleNotFound); - WebServer->on("/up", HandleUpgradeFirmware); - WebServer->on("/u1", HandleUpgradeFirmwareStart); // OTA - WebServer->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); - WebServer->on("/u2", HTTP_OPTIONS, HandlePreflightRequest); - WebServer->on("/cs", HTTP_GET, HandleConsole); - WebServer->on("/cs", HTTP_OPTIONS, HandlePreflightRequest); - WebServer->on("/cm", HandleHttpCommand); + if (!Webserver) { + Webserver = new ESP8266WebServer((HTTP_MANAGER == type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT); + Webserver->on("/", HandleRoot); + Webserver->onNotFound(HandleNotFound); + Webserver->on("/up", HandleUpgradeFirmware); + Webserver->on("/u1", HandleUpgradeFirmwareStart); // OTA + Webserver->on("/u2", HTTP_POST, HandleUploadDone, HandleUploadLoop); + Webserver->on("/u2", HTTP_OPTIONS, HandlePreflightRequest); + Webserver->on("/cs", HTTP_GET, HandleConsole); + Webserver->on("/cs", HTTP_OPTIONS, HandlePreflightRequest); + Webserver->on("/cm", HandleHttpCommand); #ifndef FIRMWARE_MINIMAL - WebServer->on("/cn", HandleConfiguration); - WebServer->on("/md", HandleModuleConfiguration); - WebServer->on("/wi", HandleWifiConfiguration); - WebServer->on("/lg", HandleLoggingConfiguration); - WebServer->on("/tp", HandleTemplateConfiguration); - WebServer->on("/co", HandleOtherConfiguration); - WebServer->on("/dl", HandleBackupConfiguration); - WebServer->on("/rs", HandleRestoreConfiguration); - WebServer->on("/rt", HandleResetConfiguration); - WebServer->on("/in", HandleInformation); + Webserver->on("/cn", HandleConfiguration); + Webserver->on("/md", HandleModuleConfiguration); + Webserver->on("/wi", HandleWifiConfiguration); + Webserver->on("/lg", HandleLoggingConfiguration); + Webserver->on("/tp", HandleTemplateConfiguration); + Webserver->on("/co", HandleOtherConfiguration); + Webserver->on("/dl", HandleBackupConfiguration); + Webserver->on("/rs", HandleRestoreConfiguration); + Webserver->on("/rt", HandleResetConfiguration); + Webserver->on("/in", HandleInformation); XdrvCall(FUNC_WEB_ADD_HANDLER); XsnsCall(FUNC_WEB_ADD_HANDLER); #endif // Not FIRMWARE_MINIMAL @@ -619,9 +619,9 @@ void StartWebserver(int type, IPAddress ipweb) // Collect User-Agent for Alexa Hue Emulation // This is used in xdrv_20_hue.ino in function findEchoGeneration() - WebServer->collectHeaders(HEADER_KEYS, sizeof(HEADER_KEYS)/sizeof(char*)); + Webserver->collectHeaders(HEADER_KEYS, sizeof(HEADER_KEYS)/sizeof(char*)); - WebServer->begin(); // Web server start + Webserver->begin(); // Web server start } if (Web.state != type) { #if LWIP_IPV6 @@ -639,7 +639,7 @@ void StartWebserver(int type, IPAddress ipweb) void StopWebserver(void) { if (Web.state) { - WebServer->close(); + Webserver->close(); Web.state = HTTP_OFF; AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_STOPPED)); } @@ -684,7 +684,7 @@ void WifiManagerBegin(bool reset_only) void PollDnsWebserver(void) { if (DnsServer) { DnsServer->processNextRequest(); } - if (WebServer) { WebServer->handleClient(); } + if (Webserver) { Webserver->handleClient(); } } /*********************************************************************************************/ @@ -692,7 +692,7 @@ void PollDnsWebserver(void) bool WebAuthenticate(void) { if (strlen(SettingsText(SET_WEBPWD)) && (HTTP_MANAGER_RESET_ONLY != Web.state)) { - return WebServer->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD)); + return Webserver->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD)); } else { return true; } @@ -705,7 +705,7 @@ bool HttpCheckPriviledgedAccess(bool autorequestauth = true) return false; } if (autorequestauth && !WebAuthenticate()) { - WebServer->requestAuthentication(); + Webserver->requestAuthentication(); return false; } return true; @@ -714,15 +714,15 @@ bool HttpCheckPriviledgedAccess(bool autorequestauth = true) void HttpHeaderCors(void) { if (strlen(SettingsText(SET_CORS))) { - WebServer->sendHeader(F("Access-Control-Allow-Origin"), SettingsText(SET_CORS)); + Webserver->sendHeader(F("Access-Control-Allow-Origin"), SettingsText(SET_CORS)); } } void WSHeaderSend(void) { - WebServer->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate")); - WebServer->sendHeader(F("Pragma"), F("no-cache")); - WebServer->sendHeader(F("Expires"), F("-1")); + Webserver->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate")); + Webserver->sendHeader(F("Pragma"), F("no-cache")); + Webserver->sendHeader(F("Expires"), F("-1")); HttpHeaderCors(); } @@ -733,7 +733,7 @@ void WSHeaderSend(void) void WSSend(int code, int ctype, const String& content) { char ct[25]; // strlen("application/octet-stream") +1 = Longest Content type string - WebServer->send(code, GetTextIndexed(ct, sizeof(ct), ctype, kContentTypes), content); + Webserver->send(code, GetTextIndexed(ct, sizeof(ct), ctype, kContentTypes), content); } /********************************************************************************************** @@ -742,13 +742,13 @@ void WSSend(int code, int ctype, const String& content) void WSContentBegin(int code, int ctype) { - WebServer->client().flush(); + Webserver->client().flush(); WSHeaderSend(); #ifdef ARDUINO_ESP8266_RELEASE_2_3_0 - WebServer->sendHeader(F("Accept-Ranges"),F("none")); - WebServer->sendHeader(F("Transfer-Encoding"),F("chunked")); + Webserver->sendHeader(F("Accept-Ranges"),F("none")); + Webserver->sendHeader(F("Transfer-Encoding"),F("chunked")); #endif - WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); + Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); WSSend(code, ctype, ""); // Signal start of chunked content Web.chunk_buffer = ""; } @@ -761,9 +761,9 @@ void _WSContentSend(const String& content) // Low level sendContent for a const char * footer = "\r\n"; char chunk_size[11]; sprintf(chunk_size, "%x\r\n", len); - WebServer->sendContent(String() + chunk_size + content + footer); + Webserver->sendContent(String() + chunk_size + content + footer); #else - WebServer->sendContent(content); + Webserver->sendContent(content); #endif #ifdef USE_DEBUG_DRIVER @@ -849,8 +849,8 @@ void WSContentSend_PD(const char* formatP, ...) // Content send snprintf_P ch void WSContentStart_P(const char* title, bool auth) { - if (auth && strlen(SettingsText(SET_WEBPWD)) && !WebServer->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD))) { - return WebServer->requestAuthentication(); + if (auth && strlen(SettingsText(SET_WEBPWD)) && !Webserver->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD))) { + return Webserver->requestAuthentication(); } WSContentBegin(200, CT_HTML); @@ -961,7 +961,7 @@ void WSContentEnd(void) { WSContentFlush(); // Flush chunk buffer _WSContentSend(""); // Signal end of chunked content - WebServer->client().stop(); + Webserver->client().stop(); } void WSContentStop(void) @@ -1043,17 +1043,17 @@ void HandleRoot(void) { if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the page. - if (WebServer->hasArg("rst")) { + if (Webserver->hasArg("rst")) { WebRestart(0); return; } if (WifiIsInManagerMode()) { #ifndef FIRMWARE_MINIMAL - if (strlen(SettingsText(SET_WEBPWD)) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) { + if (strlen(SettingsText(SET_WEBPWD)) && !(Webserver->hasArg("USER1")) && !(Webserver->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) { HandleWifiLogin(); } else { - if (!strlen(SettingsText(SET_WEBPWD)) || (((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == SettingsText(SET_WEBPWD) )) || HTTP_MANAGER_RESET_ONLY == Web.state)) { + if (!strlen(SettingsText(SET_WEBPWD)) || (((Webserver->arg("USER1") == WEB_USERNAME ) && (Webserver->arg("PASS1") == SettingsText(SET_WEBPWD) )) || HTTP_MANAGER_RESET_ONLY == Web.state)) { HandleWifiConfiguration(); } else { // wrong user and pass @@ -1243,11 +1243,11 @@ void HandleRoot(void) bool HandleRootStatusRefresh(void) { if (!WebAuthenticate()) { - WebServer->requestAuthentication(); + Webserver->requestAuthentication(); return true; } - if (!WebServer->hasArg("m")) { // Status refresh requested + if (!Webserver->hasArg("m")) { // Status refresh requested return false; } @@ -1429,7 +1429,7 @@ void HandleTemplateConfiguration(void) { if (!HttpCheckPriviledgedAccess()) { return; } - if (WebServer->hasArg("save")) { + if (Webserver->hasArg("save")) { TemplateSaveSettings(); WebRestart(1); return; @@ -1437,7 +1437,7 @@ void HandleTemplateConfiguration(void) char stemp[30]; // Template number and Sensor name - if (WebServer->hasArg("m")) { + if (Webserver->hasArg("m")) { WSContentBegin(200, CT_PLAIN); for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { // "}2'%d'>%s (%d)}3" - "}2'0'>Sonoff Basic (1)}3" uint32_t midx = pgm_read_byte(kModuleNiceList + i); @@ -1548,7 +1548,7 @@ void TemplateSaveSettings(void) uint32_t flag = atoi(tmp); for (uint32_t i = 0; i < GPIO_FLAG_USED; i++) { snprintf_P(webindex, sizeof(webindex), PSTR("c%d"), i); - uint32_t state = WebServer->hasArg(webindex) << i +4; // FLAG + uint32_t state = Webserver->hasArg(webindex) << i +4; // FLAG flag += state; } WebGetArg("g99", tmp, sizeof(tmp)); // BASE @@ -1564,7 +1564,7 @@ void HandleModuleConfiguration(void) { if (!HttpCheckPriviledgedAccess()) { return; } - if (WebServer->hasArg("save")) { + if (Webserver->hasArg("save")) { ModuleSaveSettings(); WebRestart(1); return; @@ -1575,7 +1575,7 @@ void HandleModuleConfiguration(void) myio cmodule; ModuleGpios(&cmodule); - if (WebServer->hasArg("m")) { + if (Webserver->hasArg("m")) { WSContentBegin(200, CT_PLAIN); uint32_t vidx = 0; for (uint32_t i = 0; i <= sizeof(kModuleNiceList); i++) { // "}2'%d'>%s (%d)}3" - "}2'255'>UserTemplate (0)}3" - "}2'0'>Sonoff Basic (1)}3" @@ -1592,7 +1592,7 @@ void HandleModuleConfiguration(void) return; } - if (WebServer->hasArg("g")) { + if (Webserver->hasArg("g")) { WSContentBegin(200, CT_PLAIN); for (uint32_t j = 0; j < sizeof(kGpioNiceList); j++) { midx = pgm_read_byte(kGpioNiceList + j); @@ -1605,7 +1605,7 @@ void HandleModuleConfiguration(void) } #ifndef USE_ADC_VCC - if (WebServer->hasArg("a")) { + if (Webserver->hasArg("a")) { WSContentBegin(200, CT_PLAIN); for (uint32_t j = 0; j < ADC0_END; j++) { WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, j, GetTextIndexed(stemp, sizeof(stemp), j, kAdc0Names), j); @@ -1720,7 +1720,7 @@ void HandleWifiConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI); - if (WebServer->hasArg("save") && HTTP_MANAGER_RESET_ONLY != Web.state) { + if (Webserver->hasArg("save") && HTTP_MANAGER_RESET_ONLY != Web.state) { WifiSaveSettings(); WebRestart(2); return; @@ -1731,7 +1731,7 @@ void HandleWifiConfiguration(void) WSContentSendStyle(); if (HTTP_MANAGER_RESET_ONLY != Web.state) { - if (WebServer->hasArg("scan")) { + if (Webserver->hasArg("scan")) { #ifdef USE_EMULATION UdpDisconnect(); #endif // USE_EMULATION @@ -1844,7 +1844,7 @@ void HandleLoggingConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_LOGGING); - if (WebServer->hasArg("save")) { + if (Webserver->hasArg("save")) { LoggingSaveSettings(); HandleConfiguration(); return; @@ -1909,7 +1909,7 @@ void HandleOtherConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_OTHER); - if (WebServer->hasArg("save")) { + if (Webserver->hasArg("save")) { OtherSaveSettings(); WebRestart(1); return; @@ -1973,7 +1973,7 @@ void OtherSaveSettings(void) WebGetArg("wp", tmp, sizeof(tmp)); SettingsUpdateText(SET_WEBPWD, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? SettingsText(SET_WEBPWD) : tmp); - Settings.flag.mqtt_enabled = WebServer->hasArg("b1"); // SetOption3 - Enable MQTT + Settings.flag.mqtt_enabled = Webserver->hasArg("b1"); // SetOption3 - Enable MQTT #ifdef USE_EMULATION UdpDisconnect(); #if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) @@ -1994,7 +1994,7 @@ void OtherSaveSettings(void) /* // This sometimes provides intermittent watchdog - bool template_activate = WebServer->hasArg("t2"); // Try this to tackle intermittent watchdog after execution of Template command + bool template_activate = Webserver->hasArg("t2"); // Try this to tackle intermittent watchdog after execution of Template command WebGetArg("t1", tmp, sizeof(tmp)); if (strlen(tmp)) { // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255} char svalue[128]; @@ -2010,7 +2010,7 @@ void OtherSaveSettings(void) */ WebGetArg("t1", tmp, sizeof(tmp)); if (strlen(tmp)) { // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255} - snprintf_P(message, sizeof(message), PSTR(D_CMND_BACKLOG " " D_CMND_TEMPLATE " %s%s"), tmp, (WebServer->hasArg("t2")) ? "; " D_CMND_MODULE " 0" : ""); + snprintf_P(message, sizeof(message), PSTR(D_CMND_BACKLOG " " D_CMND_TEMPLATE " %s%s"), tmp, (Webserver->hasArg("t2")) ? "; " D_CMND_MODULE " 0" : ""); ExecuteWebCommand(message, SRC_WEBGUI); } } @@ -2025,8 +2025,8 @@ void HandleBackupConfiguration(void) if (!SettingsBufferAlloc()) { return; } - WiFiClient myClient = WebServer->client(); - WebServer->setContentLength(sizeof(Settings)); + WiFiClient myClient = Webserver->client(); + Webserver->setContentLength(sizeof(Settings)); char attachment[TOPSZ]; @@ -2036,7 +2036,7 @@ void HandleBackupConfiguration(void) char hostname[sizeof(my_hostname)]; snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(hostname, my_hostname), my_version); - WebServer->sendHeader(F("Content-Disposition"), attachment); + Webserver->sendHeader(F("Content-Disposition"), attachment); WSSend(200, CT_STREAM, ""); @@ -2336,7 +2336,7 @@ void HandleUploadLoop(void) return; } - HTTPUpload& upload = WebServer->upload(); + HTTPUpload& upload = Webserver->upload(); if (UPLOAD_FILE_START == upload.status) { restart_flag = 60; @@ -2549,8 +2549,8 @@ void HandleUploadLoop(void) void HandlePreflightRequest(void) { HttpHeaderCors(); - WebServer->sendHeader(F("Access-Control-Allow-Methods"), F("GET, POST")); - WebServer->sendHeader(F("Access-Control-Allow-Headers"), F("authorization")); + Webserver->sendHeader(F("Access-Control-Allow-Methods"), F("GET, POST")); + Webserver->sendHeader(F("Access-Control-Allow-Headers"), F("authorization")); WSSend(200, CT_HTML, ""); } @@ -2574,7 +2574,7 @@ void HandleHttpCommand(void) WSContentBegin(200, CT_JSON); if (valid) { uint32_t curridx = web_log_index; - String svalue = WebServer->arg("cmnd"); + String svalue = Webserver->arg("cmnd"); if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCOMMAND); if (web_log_index != curridx) { @@ -2620,7 +2620,7 @@ void HandleConsole(void) { if (!HttpCheckPriviledgedAccess()) { return; } - if (WebServer->hasArg("c2")) { // Console refresh requested + if (Webserver->hasArg("c2")) { // Console refresh requested HandleConsoleRefresh(); return; } @@ -2640,7 +2640,7 @@ void HandleConsoleRefresh(void) bool cflg = true; uint32_t counter = 0; // Initial start, should never be 0 again - String svalue = WebServer->arg("c1"); + String svalue = Webserver->arg("c1"); if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), svalue.c_str()); ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCONSOLE); @@ -2685,13 +2685,13 @@ void HandleConsoleRefresh(void) void HandleNotFound(void) { -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Not found (%s)"), WebServer->uri().c_str()); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Not found (%s)"), Webserver->uri().c_str()); if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the error page. #ifdef USE_EMULATION #ifdef USE_EMULATION_HUE - String path = WebServer->uri(); + String path = Webserver->uri(); if ((EMUL_HUE == Settings.flag2.emulation) && (path.startsWith("/api"))) { HandleHueApi(&path); } else @@ -2699,9 +2699,9 @@ void HandleNotFound(void) #endif // USE_EMULATION { WSContentBegin(404, CT_PLAIN); - WSContentSend_P(PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), WebServer->uri().c_str(), (WebServer->method() == HTTP_GET) ? "GET" : "POST", WebServer->args()); - for (uint32_t i = 0; i < WebServer->args(); i++) { - WSContentSend_P(PSTR(" %s: %s\n"), WebServer->argName(i).c_str(), WebServer->arg(i).c_str()); + WSContentSend_P(PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), Webserver->uri().c_str(), (Webserver->method() == HTTP_GET) ? "GET" : "POST", Webserver->args()); + for (uint32_t i = 0; i < Webserver->args(); i++) { + WSContentSend_P(PSTR(" %s: %s\n"), Webserver->argName(i).c_str(), Webserver->arg(i).c_str()); } WSContentEnd(); } @@ -2711,12 +2711,12 @@ void HandleNotFound(void) bool CaptivePortal(void) { // Possible hostHeader: connectivitycheck.gstatic.com or 192.168.4.1 - if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader().c_str())) { + 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("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 + Webserver->client().stop(); // Stop is needed because we sent no content length return true; } return false; diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 780d94c98..6ad843980 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -1252,7 +1252,7 @@ void HandleMqttConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT); - if (WebServer->hasArg("save")) { + if (Webserver->hasArg("save")) { MqttSaveSettings(); WebRestart(1); return; @@ -1334,7 +1334,7 @@ bool Xdrv02(uint8_t function) WSContentSend_P(HTTP_BTN_MENU_MQTT); break; case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); + Webserver->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); break; #endif // USE_WEBSERVER case FUNC_COMMAND: diff --git a/tasmota/xdrv_07_domoticz.ino b/tasmota/xdrv_07_domoticz.ino index 1fddf5890..ef7202fa7 100644 --- a/tasmota/xdrv_07_domoticz.ino +++ b/tasmota/xdrv_07_domoticz.ino @@ -559,7 +559,7 @@ void HandleDomoticzConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_DOMOTICZ); - if (WebServer->hasArg("save")) { + if (Webserver->hasArg("save")) { DomoticzSaveSettings(); WebRestart(1); return; @@ -651,7 +651,7 @@ bool Xdrv07(uint8_t function) WSContentSend_P(HTTP_BTN_MENU_DOMOTICZ); break; case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration); + Webserver->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration); break; #endif // USE_WEBSERVER case FUNC_MQTT_SUBSCRIBE: diff --git a/tasmota/xdrv_09_timers.ino b/tasmota/xdrv_09_timers.ino index f751d853f..a5cb67f41 100644 --- a/tasmota/xdrv_09_timers.ino +++ b/tasmota/xdrv_09_timers.ino @@ -702,7 +702,7 @@ void HandleTimerConfiguration(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TIMER); - if (WebServer->hasArg("save")) { + if (Webserver->hasArg("save")) { TimerSaveSettings(); HandleConfiguration(); return; @@ -740,7 +740,7 @@ void TimerSaveSettings(void) char message[LOGSZ]; Timer timer; - Settings.flag3.timers_enable = WebServer->hasArg("e0"); // CMND_TIMERS + Settings.flag3.timers_enable = Webserver->hasArg("e0"); // CMND_TIMERS WebGetArg("t0", tmp, sizeof(tmp)); char *p = tmp; snprintf_P(message, sizeof(message), PSTR(D_LOG_MQTT D_CMND_TIMERS " %d"), Settings.flag3.timers_enable); // CMND_TIMERS @@ -781,7 +781,7 @@ bool Xdrv09(uint8_t function) #endif // USE_RULES break; case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_TIMER, HandleTimerConfiguration); + Webserver->on("/" WEB_HANDLE_TIMER, HandleTimerConfiguration); break; #endif // USE_TIMERS_WEB #endif // USE_WEBSERVER diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index e086adedb..e57f1ea80 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -3341,8 +3341,8 @@ void Script_FileUploadConfiguration(void) if (!HttpCheckPriviledgedAccess()) { return; } - if (WebServer->hasArg("download")) { - String stmp = WebServer->arg("download"); + if (Webserver->hasArg("download")) { + String stmp = Webserver->arg("download"); char *cp=(char*)stmp.c_str(); if (DownloadFile(cp)) { // is directory @@ -3386,7 +3386,7 @@ void script_upload(void) { //AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: file upload")); - HTTPUpload& upload = WebServer->upload(); + HTTPUpload& upload = Webserver->upload(); if (upload.status == UPLOAD_FILE_START) { char npath[48]; sprintf(npath,"%s/%s",path,upload.filename.c_str()); @@ -3402,7 +3402,7 @@ void script_upload(void) { } } else { Web.upload_error=1; - WebServer->send(500, "text/plain", "500: couldn't create file"); + Webserver->send(500, "text/plain", "500: couldn't create file"); } } @@ -3428,8 +3428,8 @@ uint8_t DownloadFile(char *file) { uint32_t flen=download_file.size(); - download_Client = WebServer->client(); - WebServer->setContentLength(flen); + download_Client = Webserver->client(); + Webserver->setContentLength(flen); char attachment[100]; char *cp; @@ -3440,7 +3440,7 @@ uint8_t DownloadFile(char *file) { } } snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"),cp); - WebServer->sendHeader(F("Content-Disposition"), attachment); + Webserver->sendHeader(F("Content-Disposition"), attachment); WSSend(200, CT_STREAM, ""); uint8_t buff[512]; @@ -3472,7 +3472,7 @@ uint8_t DownloadFile(char *file) { void HandleScriptTextareaConfiguration(void) { if (!HttpCheckPriviledgedAccess()) { return; } - if (WebServer->hasArg("save")) { + if (Webserver->hasArg("save")) { ScriptSaveSettings(); HandleConfiguration(); return; @@ -3486,13 +3486,13 @@ void HandleScriptConfiguration(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_SCRIPT); #ifdef USE_SCRIPT_FATFS - if (WebServer->hasArg("d1")) { + if (Webserver->hasArg("d1")) { DownloadFile(glob_script_mem.flink[0]); } - if (WebServer->hasArg("d2")) { + if (Webserver->hasArg("d2")) { DownloadFile(glob_script_mem.flink[1]); } - if (WebServer->hasArg("upl")) { + if (Webserver->hasArg("upl")) { Script_FileUploadConfiguration(); } #endif @@ -3532,14 +3532,14 @@ void HandleScriptConfiguration(void) { void ScriptSaveSettings(void) { - if (WebServer->hasArg("c1")) { + if (Webserver->hasArg("c1")) { bitWrite(Settings.rule_enabled,0,1); } else { bitWrite(Settings.rule_enabled,0,0); } - String str = WebServer->arg("t1"); + String str = Webserver->arg("t1"); if (*str.c_str()) { @@ -3990,11 +3990,11 @@ void Script_Handle_Hue(String *path) { uint8_t device = DecodeLightId(atoi(path->c_str())); uint8_t index = device-devices_present-1; - if (WebServer->args()) { + if (Webserver->args()) { response = "["; StaticJsonBuffer<400> jsonBuffer; - JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); + JsonObject &hue_json = jsonBuffer.parseObject(Webserver->arg((Webserver->args())-1)); if (hue_json.containsKey("on")) { response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); @@ -4436,8 +4436,8 @@ void Script_Check_HTML_Setvars(void) { if (!HttpCheckPriviledgedAccess()) { return; } - if (WebServer->hasArg("sv")) { - String stmp = WebServer->arg("sv"); + if (Webserver->hasArg("sv")) { + String stmp = Webserver->arg("sv"); char cmdbuf[64]; memset(cmdbuf,0,sizeof(cmdbuf)); char *cp=cmdbuf; @@ -4932,13 +4932,13 @@ bool Xdrv10(uint8_t function) WSContentSend_P(HTTP_BTN_MENU_RULES); break; case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration); - WebServer->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration); + Webserver->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration); + Webserver->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration); #ifdef USE_SCRIPT_FATFS - WebServer->on("/u3", HTTP_POST,[]() { WebServer->sendHeader("Location","/u3");WebServer->send(303);},script_upload); - WebServer->on("/u3", HTTP_GET,ScriptFileUploadSuccess); - WebServer->on("/upl", HTTP_GET,Script_FileUploadConfiguration); + Webserver->on("/u3", HTTP_POST,[]() { Webserver->sendHeader("Location","/u3");Webserver->send(303);},script_upload); + Webserver->on("/u3", HTTP_GET,ScriptFileUploadSuccess); + Webserver->on("/upl", HTTP_GET,Script_FileUploadConfiguration); #endif break; #endif // USE_WEBSERVER diff --git a/tasmota/xdrv_11_knx.ino b/tasmota/xdrv_11_knx.ino index b8177c1ad..d6f2864dc 100644 --- a/tasmota/xdrv_11_knx.ino +++ b/tasmota/xdrv_11_knx.ino @@ -809,22 +809,22 @@ void HandleKNXConfiguration(void) char tmp[100]; String stmp; - if ( WebServer->hasArg("save") ) { + if ( Webserver->hasArg("save") ) { KNX_Save_Settings(); HandleConfiguration(); } else { - if ( WebServer->hasArg("btn_add") ) { - if ( WebServer->arg("btn_add") == "1" ) { + if ( Webserver->hasArg("btn_add") ) { + if ( Webserver->arg("btn_add") == "1" ) { - stmp = WebServer->arg("GAop"); //option selected + stmp = Webserver->arg("GAop"); //option selected uint8_t GAop = stmp.toInt(); - stmp = WebServer->arg("GA_FNUM"); + stmp = Webserver->arg("GA_FNUM"); uint8_t GA_FNUM = stmp.toInt(); - stmp = WebServer->arg("GA_AREA"); + stmp = Webserver->arg("GA_AREA"); uint8_t GA_AREA = stmp.toInt(); - stmp = WebServer->arg("GA_FDEF"); + stmp = Webserver->arg("GA_FDEF"); uint8_t GA_FDEF = stmp.toInt(); if (GAop) { @@ -834,13 +834,13 @@ void HandleKNXConfiguration(void) else { - stmp = WebServer->arg("CBop"); //option selected + stmp = Webserver->arg("CBop"); //option selected uint8_t CBop = stmp.toInt(); - stmp = WebServer->arg("CB_FNUM"); + stmp = Webserver->arg("CB_FNUM"); uint8_t CB_FNUM = stmp.toInt(); - stmp = WebServer->arg("CB_AREA"); + stmp = Webserver->arg("CB_AREA"); uint8_t CB_AREA = stmp.toInt(); - stmp = WebServer->arg("CB_FDEF"); + stmp = Webserver->arg("CB_FDEF"); uint8_t CB_FDEF = stmp.toInt(); if (CBop) { @@ -848,19 +848,19 @@ void HandleKNXConfiguration(void) } } } - else if ( WebServer->hasArg("btn_del_ga") ) + else if ( Webserver->hasArg("btn_del_ga") ) { - stmp = WebServer->arg("btn_del_ga"); + stmp = Webserver->arg("btn_del_ga"); uint8_t GA_NUM = stmp.toInt(); KNX_DEL_GA(GA_NUM); } - else if ( WebServer->hasArg("btn_del_cb") ) + else if ( Webserver->hasArg("btn_del_cb") ) { - stmp = WebServer->arg("btn_del_cb"); + stmp = Webserver->arg("btn_del_cb"); uint8_t CB_NUM = stmp.toInt(); KNX_DEL_CB(CB_NUM); @@ -954,16 +954,16 @@ void KNX_Save_Settings(void) String stmp; address_t KNX_addr; - Settings.flag.knx_enabled = WebServer->hasArg("b1"); - Settings.flag.knx_enable_enhancement = WebServer->hasArg("b2"); + Settings.flag.knx_enabled = Webserver->hasArg("b1"); + Settings.flag.knx_enable_enhancement = Webserver->hasArg("b2"); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ENABLED ": %d, " D_KNX_ENHANCEMENT ": %d"), Settings.flag.knx_enabled, Settings.flag.knx_enable_enhancement ); - stmp = WebServer->arg("area"); + stmp = Webserver->arg("area"); KNX_addr.pa.area = stmp.toInt(); - stmp = WebServer->arg("line"); + stmp = Webserver->arg("line"); KNX_addr.pa.line = stmp.toInt(); - stmp = WebServer->arg("member"); + stmp = Webserver->arg("member"); KNX_addr.pa.member = stmp.toInt(); Settings.knx_physsical_addr = KNX_addr.value; knx.physical_address_set( KNX_addr ); // Set Physical KNX Address of the device @@ -1224,7 +1224,7 @@ bool Xdrv11(uint8_t function) WSContentSend_P(HTTP_BTN_MENU_KNX); break; case FUNC_WEB_ADD_HANDLER: - WebServer->on("/kn", HandleKNXConfiguration); + Webserver->on("/kn", HandleKNXConfiguration); break; #endif // USE_KNX_WEB_MENU #endif // USE_WEBSERVER diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 32a852b50..f9e21c3a3 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -448,7 +448,7 @@ static const char * FIRST_GEN_UA[] = { // list of User-Agents signature // Check if the Echo device is of 1st generation, which triggers different results uint32_t findEchoGeneration(void) { // result is 1 for 1st gen, 2 for 2nd gen and further - String user_agent = WebServer->header("User-Agent"); + String user_agent = Webserver->header("User-Agent"); uint32_t gen = 2; for (uint32_t i = 0; i < sizeof(FIRST_GEN_UA)/sizeof(char*); i++) { @@ -521,11 +521,11 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { const size_t buf_size = 100; char * buf = (char*) malloc(buf_size); - if (WebServer->args()) { + if (Webserver->args()) { response = "["; StaticJsonBuffer<300> jsonBuffer; - JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); + JsonObject &hue_json = jsonBuffer.parseObject(Webserver->arg((Webserver->args())-1)); if (hue_json.containsKey("on")) { on = hue_json["on"]; snprintf_P(buf, buf_size, @@ -827,8 +827,8 @@ void HandleHueApi(String *path) path->remove(0, 4); // remove /api uint16_t apilen = path->length(); AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API " (%s)"), path->c_str()); // HTP: Hue API (//lights/1/state - for (args = 0; args < WebServer->args(); args++) { - String json = WebServer->arg(args); + for (args = 0; args < Webserver->args(); args++) { + String json = Webserver->arg(args); AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_POST_ARGS " (%s)"), json.c_str()); // HTP: Hue POST args ({"on":false}) } @@ -861,7 +861,7 @@ bool Xdrv20(uint8_t function) #endif switch (function) { case FUNC_WEB_ADD_HANDLER: - WebServer->on(F("/description.xml"), HandleUpnpSetupHue); + Webserver->on(F("/description.xml"), HandleUpnpSetupHue); break; } } diff --git a/tasmota/xdrv_21_wemo.ino b/tasmota/xdrv_21_wemo.ino index cb3566f89..eef509e2a 100644 --- a/tasmota/xdrv_21_wemo.ino +++ b/tasmota/xdrv_21_wemo.ino @@ -198,7 +198,7 @@ void HandleUpnpEvent(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); char event[500]; - strlcpy(event, WebServer->arg(0).c_str(), sizeof(event)); + strlcpy(event, Webserver->arg(0).c_str(), sizeof(event)); // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), event); @@ -259,10 +259,10 @@ bool Xdrv21(uint8_t function) if (devices_present && (EMUL_WEMO == Settings.flag2.emulation)) { switch (function) { case FUNC_WEB_ADD_HANDLER: - WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); - WebServer->on("/eventservice.xml", HandleUpnpService); - WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); - WebServer->on("/setup.xml", HandleUpnpSetupWemo); + Webserver->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); + Webserver->on("/eventservice.xml", HandleUpnpService); + Webserver->on("/metainfoservice.xml", HandleUpnpMetaService); + Webserver->on("/setup.xml", HandleUpnpSetupWemo); break; } } diff --git a/tasmota/xdrv_23_zigbee_3_hue.ino b/tasmota/xdrv_23_zigbee_3_hue.ino index 0d00ad9e0..e534134dc 100644 --- a/tasmota/xdrv_23_zigbee_3_hue.ino +++ b/tasmota/xdrv_23_zigbee_3_hue.ino @@ -190,11 +190,11 @@ void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { const size_t buf_size = 100; char * buf = (char*) malloc(buf_size); - if (WebServer->args()) { + if (Webserver->args()) { response = "["; StaticJsonBuffer<300> jsonBuffer; - JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); + JsonObject &hue_json = jsonBuffer.parseObject(Webserver->arg((Webserver->args())-1)); if (hue_json.containsKey("on")) { on = hue_json["on"]; snprintf_P(buf, buf_size, diff --git a/tasmota/xdrv_28_pcf8574.ino b/tasmota/xdrv_28_pcf8574.ino index 95074fab8..888f34fee 100644 --- a/tasmota/xdrv_28_pcf8574.ino +++ b/tasmota/xdrv_28_pcf8574.ino @@ -160,7 +160,7 @@ void HandlePcf8574(void) AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_PCF8574)); - if (WebServer->hasArg("save")) { + if (Webserver->hasArg("save")) { Pcf8574SaveSettings(); WebRestart(1); return; @@ -193,9 +193,9 @@ void Pcf8574SaveSettings(void) char stemp[7]; char tmp[100]; - //AddLog_P(LOG_LEVEL_DEBUG, PSTR("PCF: Start working on Save arguements: inverted:%d")), WebServer->hasArg("b1"); + //AddLog_P(LOG_LEVEL_DEBUG, PSTR("PCF: Start working on Save arguements: inverted:%d")), Webserver->hasArg("b1"); - Settings.flag3.pcf8574_ports_inverted = WebServer->hasArg("b1"); // SetOption81 - Invert all ports on PCF8574 devices + Settings.flag3.pcf8574_ports_inverted = Webserver->hasArg("b1"); // SetOption81 - Invert all ports on PCF8574 devices for (byte idx = 0; idx < Pcf8574.max_devices; idx++) { byte count=0; byte n = Settings.pcf8574_config[idx]; @@ -248,7 +248,7 @@ bool Xdrv28(uint8_t function) WSContentSend_P(HTTP_BTN_MENU_PCF8574); break; case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_PCF8574, HandlePcf8574); + Webserver->on("/" WEB_HANDLE_PCF8574, HandlePcf8574); break; #endif // USE_WEBSERVER } diff --git a/tasmota/xsns_34_hx711.ino b/tasmota/xsns_34_hx711.ino index 44bb9036c..86e920945 100644 --- a/tasmota/xsns_34_hx711.ino +++ b/tasmota/xsns_34_hx711.ino @@ -494,7 +494,7 @@ void HandleHxAction(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_HX711); - if (WebServer->hasArg("save")) { + if (Webserver->hasArg("save")) { HxSaveSettings(); HandleConfiguration(); return; @@ -502,7 +502,7 @@ void HandleHxAction(void) char stemp1[20]; - if (WebServer->hasArg("reset")) { + if (Webserver->hasArg("reset")) { snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 1")); // Reset ExecuteWebCommand(stemp1, SRC_WEBGUI); @@ -510,7 +510,7 @@ void HandleHxAction(void) return; } - if (WebServer->hasArg("calibrate")) { + if (Webserver->hasArg("calibrate")) { WebGetArg("p1", stemp1, sizeof(stemp1)); Settings.weight_reference = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToFloat(stemp1) * 1000); @@ -593,7 +593,7 @@ bool Xsns34(uint8_t function) WSContentSend_P(HTTP_BTN_MENU_HX711); break; case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction); + Webserver->on("/" WEB_HANDLE_HX711, HandleHxAction); break; #endif // USE_HX711_GUI #endif // USE_WEBSERVER diff --git a/tasmota/xsns_60_GPS.ino b/tasmota/xsns_60_GPS.ino index 966b3a609..87e15d6a2 100644 --- a/tasmota/xsns_60_GPS.ino +++ b/tasmota/xsns_60_GPS.ino @@ -98,7 +98,7 @@ The serial pins are GPS_RX and GPS_TX, no further installation steps needed. To set latitude and longitude in settings + sensor60 14 - open virtual serial port over TCP, usable for u-center + open virtual serial port over TCP, usable for u-center + sensor60 15 pause virtual serial port over TCP @@ -137,7 +137,7 @@ const char kUBXTypes[] PROGMEM = "UBX"; #define UBX_SERIAL_BUFFER_SIZE 256 #define UBX_TCP_PORT 1234 -#define NTP_MILLIS_OFFSET 50 // estimated latency in milliseconds +#define NTP_MILLIS_OFFSET 50 // estimated latency in milliseconds /********************************************************************************************\ | *globals @@ -504,8 +504,8 @@ uint32_t UBXprocessGPS() #ifdef USE_FLOG void UBXsendHeader(void) { - WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); - WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); + Webserver->setContentLength(CONTENT_LENGTH_UNKNOWN); + Webserver->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); WSSend(200, CT_STREAM, F( "\r\n" "lon/10000000.0f,7,lon); snprintf_P(record, sizeof(record),PSTR("\n\t\n\n"),lat ,lon, stime); // DEBUG_SENSOR_LOG(PSTR("FLOG: DL %u %u"), Flog->sector.dword_buffer[k+j],Flog->sector.dword_buffer[k+j+1]); - WebServer->sendContent_P(record); + Webserver->sendContent_P(record); } void UBXsendFooter(void) { - WebServer->sendContent(F("\n\n")); - WebServer->sendContent(""); + Webserver->sendContent(F("\n\n")); + Webserver->sendContent(""); Rtc.user_time_entry = false; // we have blocked the main loop and want a new valid time } @@ -707,7 +707,7 @@ void UBXHandleTIME() if (UBX.mode.forceUTCupdate || Rtc.user_time_entry == false){ AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: UTC-Time is valid, set system time")); Rtc.utc_time = UBX.rec_buffer.values.time; - } + } Rtc.user_time_entry = true; } } @@ -928,7 +928,7 @@ bool Xsns60(uint8_t function) break; #ifdef USE_FLOG case FUNC_WEB_ADD_HANDLER: - WebServer->on("/UBX", UBXsendFile); + Webserver->on("/UBX", UBXsendFile); break; #endif //USE_FLOG case FUNC_JSON_APPEND: diff --git a/tasmota/xsns_91_prometheus.ino b/tasmota/xsns_91_prometheus.ino index ea4c0047a..f5b0eba9d 100644 --- a/tasmota/xsns_91_prometheus.ino +++ b/tasmota/xsns_91_prometheus.ino @@ -90,7 +90,7 @@ bool Xsns91(uint8_t function) switch (function) { case FUNC_WEB_ADD_HANDLER: - WebServer->on("/metrics", HandleMetrics); + Webserver->on("/metrics", HandleMetrics); break; } return result; From 97abf686129ab6169e5df86eecabc01482eedd6b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 15 Apr 2020 10:14:16 +0200 Subject: [PATCH 17/70] Fix HTTP authorization response code Fix HTTP authorization response code (#8170) --- tasmota/xdrv_01_webserver.ino | 72 +++++++++++++++++------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 18df7fa4a..5d286bf2e 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2562,54 +2562,54 @@ void HandleHttpCommand(void) AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_COMMAND)); - bool valid = true; if (strlen(SettingsText(SET_WEBPWD))) { char tmp1[33]; WebGetArg("user", tmp1, sizeof(tmp1)); char tmp2[strlen(SettingsText(SET_WEBPWD)) +1]; WebGetArg("password", tmp2, sizeof(tmp2)); - if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, SettingsText(SET_WEBPWD)))) { valid = false; } + if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, SettingsText(SET_WEBPWD)))) { + WSContentBegin(401, CT_JSON); + WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_NEED_USER_AND_PASSWORD "\"}")); + WSContentEnd(); + return; + } } WSContentBegin(200, CT_JSON); - if (valid) { - uint32_t curridx = web_log_index; - String svalue = Webserver->arg("cmnd"); - if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { - ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCOMMAND); - if (web_log_index != curridx) { - uint32_t counter = curridx; - WSContentSend_P(PSTR("{")); - bool cflg = false; - do { - char* tmp; - size_t len; - GetLog(counter, &tmp, &len); - if (len) { - // [14:49:36 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [{"POWER":"OFF"}] - char* JSON = (char*)memchr(tmp, '{', len); - if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O]) - size_t JSONlen = len - (JSON - tmp); - if (JSONlen > sizeof(mqtt_data)) { JSONlen = sizeof(mqtt_data); } - char stemp[JSONlen]; - strlcpy(stemp, JSON +1, JSONlen -2); - WSContentSend_P(PSTR("%s%s"), (cflg) ? "," : "", stemp); - cflg = true; - } + uint32_t curridx = web_log_index; + String svalue = Webserver->arg("cmnd"); + if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { + ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCOMMAND); + if (web_log_index != curridx) { + uint32_t counter = curridx; + WSContentSend_P(PSTR("{")); + bool cflg = false; + do { + char* tmp; + size_t len; + GetLog(counter, &tmp, &len); + if (len) { + // [14:49:36 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [{"POWER":"OFF"}] + char* JSON = (char*)memchr(tmp, '{', len); + if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O]) + size_t JSONlen = len - (JSON - tmp); + if (JSONlen > sizeof(mqtt_data)) { JSONlen = sizeof(mqtt_data); } + char stemp[JSONlen]; + strlcpy(stemp, JSON +1, JSONlen -2); + WSContentSend_P(PSTR("%s%s"), (cflg) ? "," : "", stemp); + cflg = true; } - counter++; - counter &= 0xFF; - if (!counter) counter++; // Skip 0 as it is not allowed - } while (counter != web_log_index); - WSContentSend_P(PSTR("}")); - } else { - WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}")); - } + } + counter++; + counter &= 0xFF; + if (!counter) counter++; // Skip 0 as it is not allowed + } while (counter != web_log_index); + WSContentSend_P(PSTR("}")); } else { - WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENTER_COMMAND " cmnd=\"}")); + WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}")); } } else { - WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_NEED_USER_AND_PASSWORD "\"}")); + WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENTER_COMMAND " cmnd=\"}")); } WSContentEnd(); } From b7454d7bd8a4891d4e8ad435e2b202c8e8552667 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Wed, 15 Apr 2020 08:40:18 -0500 Subject: [PATCH 18/70] Add DevGroupStatus command, Include member add/remove logging --- tasmota/i18n.h | 1 + tasmota/support_command.ino | 9 +++-- tasmota/support_device_groups.ino | 60 ++++++++++++++++++------------- 3 files changed, 44 insertions(+), 26 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 35a840acf..9f99d7c1d 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -297,6 +297,7 @@ #define D_CMND_DEVGROUP_NAME "DevGroupName" #define D_CMND_DEVGROUP_SEND "DevGroupSend" #define D_CMND_DEVGROUP_SHARE "DevGroupShare" +#define D_CMND_DEVGROUPSTATUS "DevGroupStatus" #define D_CMND_SERIALSEND "SerialSend" #define D_CMND_SERIALDELIMITER "SerialDelimiter" #define D_CMND_BAUDRATE "Baudrate" diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index bfbd38078..6897384d0 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -36,7 +36,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix #ifdef USE_DEVICE_GROUPS_SEND D_CMND_DEVGROUP_SEND "|" #endif // USE_DEVICE_GROUPS_SEND - D_CMND_DEVGROUP_SHARE "|" + D_CMND_DEVGROUP_SHARE "|" D_CMND_DEVGROUPSTATUS "|" #endif // USE_DEVICE_GROUPS D_CMND_SENSOR "|" D_CMND_DRIVER; @@ -59,7 +59,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = { #ifdef USE_DEVICE_GROUPS_SEND &CmndDevGroupSend, #endif // USE_DEVICE_GROUPS_SEND - &CmndDevGroupShare, + &CmndDevGroupShare, &CmndDevGroupStatus, #endif // USE_DEVICE_GROUPS &CmndSensor, &CmndDriver }; @@ -1793,6 +1793,11 @@ void CmndDevGroupShare(void) Settings.device_group_share_out = parm[1]; Response_P(PSTR("{\"" D_CMND_DEVGROUP_SHARE "\":{\"In\":\"%X\",\"Out\":\"%X\"}}"), Settings.device_group_share_in, Settings.device_group_share_out); } + +void CmndDevGroupStatus(void) +{ + DeviceGroupStatus((XdrvMailbox.usridx ? XdrvMailbox.index - 1 : 0)); +} #endif // USE_DEVICE_GROUPS void CmndSensor(void) diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index e1719f59e..3a9258a60 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -34,6 +34,7 @@ struct device_group_member { IPAddress ip_address; uint16_t received_sequence; uint16_t acked_sequence; + uint32_t unicast_count; }; struct device_group { @@ -48,7 +49,6 @@ struct device_group { bool local; char group_name[TOPSZ]; char message[128]; - uint8_t group_member_count; struct device_group_member * device_group_members; #ifdef USE_DEVICE_GROUPS_SEND uint8_t values_8bit[DGR_ITEM_LAST_8BIT]; @@ -77,7 +77,7 @@ void DeviceGroupsInit(void) // Initialize the device information for each device group. device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group)); if (device_groups == nullptr) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating %u-element device group array"), device_group_count); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error allocating %u-element device group array"), device_group_count); device_groups_initialization_failed = true; return; } @@ -169,7 +169,7 @@ void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * la } delay(10); } - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error sending %s packet"), label); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error sending %s packet"), label); } void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType message_type, ...) @@ -184,7 +184,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes if (processing_remote_device_message && message_type != DGR_MSGTYPE_UPDATE_COMMAND) return; // Get a pointer to the device information for this device. - device_group * device_group = &device_groups[device_group_index]; + struct device_group * device_group = &device_groups[device_group_index]; // If we're still sending initial status requests, ignore this request. if (device_group->initial_status_requests_remaining) return; @@ -551,7 +551,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes // Multicast the packet. #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending %u-byte device group %s packet via multicast, sequence=%u"), device_group->message_length, device_group->group_name, device_group->message[device_group->message_header_length] | device_group->message[device_group->message_header_length + 1] << 8); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending %u-byte device group %s packet via multicast, sequence=%u"), device_group->message_length, device_group->group_name, device_group->message[device_group->message_header_length] | device_group->message[device_group->message_header_length + 1] << 8); #endif // DEVICE_GROUPS_DEBUG SendDeviceGroupPacket(IPAddress(0,0,0,0), device_group->message, device_group->message_length, PSTR("Multicast")); @@ -598,12 +598,10 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) if (!device_group_member) { device_group_member = (struct device_group_member *)calloc(1, sizeof(struct device_group_member)); if (device_group_member == nullptr) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating device group member block")); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Error allocating device group member block")); return; } -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: adding member %s (%p)"), IPAddressToString(remote_ip), device_group_member); -#endif // DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Adding member %s"), IPAddressToString(remote_ip)); device_group_member->ip_address = remote_ip; *flink = device_group_member; break; @@ -720,7 +718,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) case DGR_ITEM_LIGHT_CHANNELS: break; default: - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: ********** invalid item=%u received from device group %s member %s"), item, device_group->group_name, IPAddressToString(remote_ip)); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: ********** Invalid item=%u received from device group %s member %s"), item, device_group->group_name, IPAddressToString(remote_ip)); } #endif // DEVICE_GROUPS_DEBUG @@ -802,13 +800,28 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) return; badmsg: - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: malformed message received from %s"), IPAddressToString(remote_ip)); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: Malformed message received from %s"), IPAddressToString(remote_ip)); #ifdef DEVICE_GROUPS_DEBUG AddLog_P2(LOG_LEVEL_DEBUG, PSTR("packet_length=%u, offset=%u"), packet_length, message_ptr - packet); #endif // DEVICE_GROUPS_DEBUG processing_remote_device_message = false; } +void DeviceGroupStatus(uint8_t device_group_index) +{ + if (Settings.flag4.device_groups_enabled && device_group_index < device_group_count) { + char buffer[1024]; + int member_count = 0; + struct device_group * device_group = &device_groups[device_group_index]; + buffer[0] = buffer[1] = 0; + for (struct device_group_member * device_group_member = device_group->device_group_members; device_group_member; device_group_member = device_group_member->flink) { + snprintf(buffer, sizeof(buffer), PSTR("%s,{\"IPAddress\":\"%s\",\"ResendCount\":%u,\"LastRcvdSeq\":%u,\"LastAckedSeq\":%u}"), buffer, IPAddressToString(device_group_member->ip_address), device_group_member->unicast_count, device_group_member->received_sequence, device_group_member->acked_sequence); + member_count++; + } + Response_P(PSTR("{\"" D_CMND_DEVGROUPSTATUS "\":{\"Index\":%u,\"GroupName\":\"%s\",\"MessageSeq\":%u,\"MemberCount\":%d,\"Members\":[%s]}"), device_group_index, device_group->group_name, outgoing_sequence, member_count, &buffer[1]); + } +} + void DeviceGroupsLoop(void) { if (!Settings.flag4.device_groups_enabled) return; @@ -822,16 +835,16 @@ void DeviceGroupsLoop(void) if (!device_groups_initialized) DeviceGroupsInit(); if (device_groups_initialization_failed) return; - // Load the status request message for all device groups. This message will be multicast 5 - // times. + // Load the status request message for all device groups. This message will be multicast 10 + // times at 200ms intervals. next_check_time = now + 3000; for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) { device_group * device_group = &device_groups[device_group_index]; device_group->message_length = BeginDeviceGroupMessage(device_group, DGR_FLAG_RESET | DGR_FLAG_STATUS_REQUEST) - device_group->message; - device_group->initial_status_requests_remaining = 5; + device_group->initial_status_requests_remaining = 10; device_group->next_ack_check_time = next_check_time; } - + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: (Re)discovering device groups")); } if (device_groups_initialization_failed) return; @@ -856,15 +869,15 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex if (device_group->initial_status_requests_remaining) { if (--device_group->initial_status_requests_remaining) { #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending initial status request for group %s"), device_group->group_name); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending initial status request for group %s"), device_group->group_name); #endif // DEVICE_GROUPS_DEBUG SendDeviceGroupPacket(IPAddress(0,0,0,0), device_group->message, device_group->message_length, PSTR("Initial")); device_group->message[device_group->message_header_length + 2] = DGR_FLAG_STATUS_REQUEST; // The reset flag is on only for the first packet - turn it off now device_group->next_ack_check_time = now + 200; } - // If we've sent the initial status request message 5 times, send our status to all - // the members. + // If we've sent the initial status request message the set number of times, send our + // status to all the members. else { device_group->next_ack_check_time = 0; _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS); @@ -874,7 +887,7 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex // If we're done initializing, iterate through the group memebers, ... else { #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: checking for ack's")); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Checking for ack's")); #endif // DEVICE_GROUPS_DEBUG bool acked = true; struct device_group_member ** flink = &device_group->device_group_members; @@ -887,9 +900,7 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex // If we haven't receive an ack from this member in DGR_MEMBER_TIMEOUT ms, assume // they're offline and remove them from the group. if (device_group->member_timeout_time < now) { -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: removing member %s (%p)"), IPAddressToString(device_group_member->ip_address), device_group_member); -#endif // DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Removing member %s"), IPAddressToString(device_group_member->ip_address)); *flink = device_group_member->flink; free(device_group_member); } @@ -897,9 +908,10 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex // Otherwise, unicast the last message directly to this member. else { #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending %u-byte device group %s packet via unicast to %s, sequence %u, last message acked=%u"), device_group->message_length, device_group->group_name, IPAddressToString(device_group_member->ip_address), outgoing_sequence, device_group_member->acked_sequence); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending %u-byte device group %s packet via unicast to %s, sequence %u, last message acked=%u"), device_group->message_length, device_group->group_name, IPAddressToString(device_group_member->ip_address), outgoing_sequence, device_group_member->acked_sequence); #endif // DEVICE_GROUPS_DEBUG SendDeviceGroupPacket(device_group_member->ip_address, device_group->message, device_group->message_length, PSTR("Unicast")); + device_group_member->unicast_count++; acked = false; flink = &device_group_member->flink; } @@ -940,7 +952,7 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex #endif // DEVICE_GROUPS_DEBUG if (device_group->next_announcement_time <= now) { #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending device group %s announcement"), device_group->group_name); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Sending device group %s announcement"), device_group->group_name); #endif // DEVICE_GROUPS_DEBUG SendDeviceGroupPacket(IPAddress(0,0,0,0), device_group->message, BeginDeviceGroupMessage(device_group, DGR_FLAG_ANNOUNCEMENT, true) - device_group->message, PSTR("Announcement")); device_group->next_announcement_time = now + DGR_ANNOUNCEMENT_INTERVAL + random(10000); From 3a4cf26abad51bd981c8262826970a5ab462816d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 15 Apr 2020 16:22:20 +0200 Subject: [PATCH 19/70] Enable single PIN mode for SR04 sensor Enable single PIN mode for SR04 sensor (#8189) --- tasmota/xsns_22_sr04.ino | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/tasmota/xsns_22_sr04.ino b/tasmota/xsns_22_sr04.ino index 636992a57..a23a38117 100644 --- a/tasmota/xsns_22_sr04.ino +++ b/tasmota/xsns_22_sr04.ino @@ -32,40 +32,39 @@ #define XSNS_22 22 uint8_t sr04_type = 1; -int sr04_echo_pin = 0; -int sr04_trig_pin = 0; real64_t distance; NewPing* sonar = nullptr; TasmotaSerial* sonar_serial = nullptr; - - uint8_t Sr04TModeDetect(void) { sr04_type = 0; - if (pin[GPIO_SR04_ECHO]>=99) return sr04_type; + if (99 == pin[GPIO_SR04_ECHO]) { return sr04_type; } - sr04_echo_pin = pin[GPIO_SR04_ECHO]; - sr04_trig_pin = (pin[GPIO_SR04_TRIG] < 99) ? pin[GPIO_SR04_TRIG] : -1; + int sr04_echo_pin = pin[GPIO_SR04_ECHO]; + int sr04_trig_pin = (pin[GPIO_SR04_TRIG] < 99) ? pin[GPIO_SR04_TRIG] : -1; sonar_serial = new TasmotaSerial(sr04_echo_pin, sr04_trig_pin, 1); if (sonar_serial->begin(9600,1)) { DEBUG_SENSOR_LOG(PSTR("SR04: Detect mode")); - if (sr04_trig_pin!=-1) { - sr04_type = (Sr04TMiddleValue(Sr04TMode3Distance(),Sr04TMode3Distance(),Sr04TMode3Distance())!=NO_ECHO)?3:1; + if (sr04_trig_pin != -1) { + sr04_type = (Sr04TMiddleValue(Sr04TMode3Distance(), Sr04TMode3Distance(), Sr04TMode3Distance()) != NO_ECHO) ? 3 : 1; } else { - sr04_type = 2; + sr04_type = 2; } } else { sr04_type = 1; } if (sr04_type < 2) { - delete sonar_serial; - sonar_serial = nullptr; - sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, 300); + delete sonar_serial; + sonar_serial = nullptr; + if (-1 == sr04_trig_pin) { + sr04_trig_pin = pin[GPIO_SR04_ECHO]; // if GPIO_SR04_TRIG is not configured use single PIN mode with GPIO_SR04_ECHO only + } + sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, 300); } else { if (sonar_serial->hardwareSerial()) { ClaimSerial(); From 71717c3f4ec6061ad40fd8fff05b30226e82f00a Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 15 Apr 2020 18:54:20 +0200 Subject: [PATCH 20/70] Improved and simplified Ping --- tasmota/xdrv_38_ping.ino | 351 +++++++++++++++++++++++++++++---------- 1 file changed, 263 insertions(+), 88 deletions(-) diff --git a/tasmota/xdrv_38_ping.ino b/tasmota/xdrv_38_ping.ino index 0156314a7..d30c0093d 100644 --- a/tasmota/xdrv_38_ping.ino +++ b/tasmota/xdrv_38_ping.ino @@ -21,7 +21,10 @@ #define XDRV_38 38 -#include +#include "lwip/icmp.h" +#include "lwip/inet_chksum.h" +#include "lwip/raw.h" +#include "lwip/timeouts.h" const char kPingCommands[] PROGMEM = "|" // no prefix D_CMND_PING @@ -31,119 +34,291 @@ void (* const PingCommand[])(void) PROGMEM = { &CmndPing, }; -// inspired by https://github.com/dancol90/ESP8266Ping - -typedef struct Ping_t { - uint16_t total_count; // total count if packets sent - uint16_t timeout_count; // time-outs (no responses) - uint32_t min_time; // minimum time in ms for a successful response - uint32_t max_time; // maximum time in ms for a successful response - uint32_t sum_time; // cumulated time in ms for all successful responses (used to compute the average) - bool busy; // is ping on-going - bool done; // indicates the ping campaign is finished -} Ping_t; - -ping_option ping_opt; -Ping_t ping; - extern "C" { - // callbacks for ping + + extern uint32 system_relative_time(uint32 time); + extern void ets_bzero(void *s, size_t n); - // called after a ping response is received or time-out - void ICACHE_RAM_ATTR ping_recv_cb(ping_option *popt, struct ping_resp *p_resp) { - // If successful - if (p_resp->ping_err >= 0) { - uint32_t resp_time = p_resp->resp_time; - ping.sum_time += resp_time; - if (resp_time < ping.min_time) { ping.min_time = resp_time; } - if (resp_time > ping.max_time) { ping.max_time = resp_time; } + const uint16_t Ping_ID = 0xAFAF; // PING packet ID + const size_t Ping_data_size = 32; // default packet size + const uint32_t Ping_timeout_ms = 1000; // default time-out of 1 second, which is enough for LAN/WIFI + const uint32_t Ping_coarse = 1000; // interval between sending packets, 1 packet every second + + typedef struct Ping_t { + uint32 ip; // target IPv4 address + Ping_t *next; // next object in linked list + uint16_t seq_num; // next sequence number + uint16_t seqno; // reject a packet already received + uint8_t success_count; // sucessful responses received + uint8_t timeout_count; // time-outs (no responses) + uint8_t to_send_count; // number of packets remaining to send + uint32_t ping_time_sent; // timestamp when the packet was sent + uint32_t min_time; // minimum time in ms for a successful response + uint32_t max_time; // maximum time in ms for a successful response + uint32_t sum_time; // cumulated time in ms for all successful responses (used to compute the average) + bool done; // indicates the ping campaign is finished + bool fast; // fast mode, i.e. stop pings when first successful response + } Ping_t; + + // globals + Ping_t *ping_head = nullptr; // head of the Linked List for ping objects + struct raw_pcb *t_ping_pcb = nullptr; // registered with first ping, deregistered after last ping, the same pcb is used for all packets + + // ================================================================================ + // Find the Ping object indexed by IP address + // ================================================================================ + // + // find the ping structure corresponding to the specified IP, or nullptr if not found + // + Ping_t ICACHE_FLASH_ATTR * t_ping_find(uint32_t ip) { + Ping_t *ping = ping_head; + while (ping != nullptr) { + if (ping->ip == ip) { + return ping; + } + ping = ping->next; + } + return nullptr; + } + + // ================================================================================ + // Timer called a packet response is in time-out + // ================================================================================ + // + // called after the ICMP timeout occured + // we never received the packet, increase the timeout count + // + void ICACHE_FLASH_ATTR t_ping_timeout(void* arg) { + Ping_t *ping = (Ping_t*) arg; + ping->timeout_count++; + } + + // ================================================================================ + // Send ICMP packet + // ================================================================================ + // Prepare a echo ICMP request + // + void ICACHE_FLASH_ATTR t_ping_prepare_echo(struct icmp_echo_hdr *iecho, uint16_t len, Ping_t *ping) { + size_t data_len = len - sizeof(struct icmp_echo_hdr); + + ICMPH_TYPE_SET(iecho, ICMP_ECHO); + ICMPH_CODE_SET(iecho, 0); + iecho->chksum = 0; + iecho->id = Ping_ID; + ping->seq_num++; + if (ping->seq_num == 0x7fff) { ping->seq_num = 0; } + + iecho->seqno = htons(ping->seq_num); // TODO + + /* fill the additional data buffer with some data */ + for (uint32_t i = 0; i < data_len; i++) { + ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i; + } + + iecho->chksum = inet_chksum(iecho, len); + } + // + // send the ICMP packet + // + void ICACHE_FLASH_ATTR t_ping_send(struct raw_pcb *raw, Ping_t *ping) { + struct pbuf *p; + uint16_t ping_size = sizeof(struct icmp_echo_hdr) + Ping_data_size; + + ping->ping_time_sent = system_get_time(); + p = pbuf_alloc(PBUF_IP, ping_size, PBUF_RAM); + if (!p) { return; } + if ((p->len == p->tot_len) && (p->next == nullptr)) { + ip_addr_t ping_target; + struct icmp_echo_hdr *iecho; + + ping_target.addr = ping->ip; + iecho = (struct icmp_echo_hdr *) p->payload; + + t_ping_prepare_echo(iecho, ping_size, ping); + raw_sendto(raw, p, &ping_target); + } + pbuf_free(p); + } + + // ================================================================================ + // Timer called when it's time to send next packet, of when finished + // ================================================================================ + // this timer is called every x seconds to send a new packet, whatever happened to the previous packet + static void ICACHE_FLASH_ATTR t_ping_coarse_tmr(void *arg) { + Ping_t *ping = (Ping_t*) arg; + if (ping->to_send_count > 0) { + ping->to_send_count--; + // have we sent all packets? + t_ping_send(t_ping_pcb, ping); + + sys_timeout(Ping_timeout_ms, t_ping_timeout, ping); + sys_timeout(Ping_coarse, t_ping_coarse_tmr, ping); + } else { + sys_untimeout(t_ping_coarse_tmr, ping); + ping->done = true; } } - // called after the ping campaign is finished - void ICACHE_RAM_ATTR ping_sent_cb(ping_option *popt, struct ping_resp *p_resp) { - // copy counters to build the MQTT response - ping.total_count = p_resp->total_count; - ping.timeout_count = p_resp->timeout_count; - ping.done = true; + // ================================================================================ + // Callback: a packet response was received + // ================================================================================ + // + // Reveived packet + // + static uint8_t ICACHE_FLASH_ATTR t_ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) { + Ping_t *ping = t_ping_find(addr->addr); + + if (nullptr == ping) { // unknown source address + return 0; // don't eat the packet and ignore it + } + + if (pbuf_header( p, -PBUF_IP_HLEN)==0) { + struct icmp_echo_hdr *iecho; + iecho = (struct icmp_echo_hdr *)p->payload; + + if ((iecho->id == Ping_ID) && (iecho->seqno == htons(ping->seq_num)) && iecho->type == ICMP_ER) { + + if (iecho->seqno != ping->seqno){ // debounce already received packet + /* do some ping result processing */ + sys_untimeout(t_ping_timeout, ping); // remove time-out handler + uint32_t delay = system_relative_time(ping->ping_time_sent); + delay /= 1000; + + ping->sum_time += delay; + if (delay < ping->min_time) { ping->min_time = delay; } + if (delay > ping->max_time) { ping->max_time = delay; } + + ping->success_count++; + ping->seqno = iecho->seqno; + if (ping->fast) { // if fast mode, abort further pings when first successful response is received + sys_untimeout(t_ping_coarse_tmr, ping); + ping->done = true; + ping->to_send_count = 0; + } + } + + pbuf_free(p); + return 1; /* eat the packet */ + } + } + + return 0; /* don't eat the packet */ } + + // ================================================================================ + // Internal structure PCB management + // ================================================================================ + // we are going to send a packet, make sure pcb is initialized + void t_ping_register_pcb(void) { + if (nullptr == t_ping_pcb) { + t_ping_pcb = raw_new(IP_PROTO_ICMP); + + raw_recv(t_ping_pcb, t_ping_recv, nullptr); // we cannot register data structure here as we can only register one + raw_bind(t_ping_pcb, IP_ADDR_ANY); + } + } + + // we have finsihed a ping series, deallocated if no more ongoing + void t_ping_deregister_pcb(void) { + if (nullptr == ping_head) { // deregister only if no ping is flying + raw_remove(t_ping_pcb); + t_ping_pcb = nullptr; + } + } + + // ================================================================================ + // Start pings + // ================================================================================ + bool t_ping_start(uint32_t ip, uint32_t count) { + // check if pings are already ongoing for this IP + if (t_ping_find(ip)) { + return false; + } + + Ping_t *ping = new Ping_t(); + if (0 == count) { + count = 4; + ping->fast = true; + } + ping->min_time = UINT32_MAX; + ping->ip = ip; + ping->to_send_count = count - 1; + + // add to Linked List from head + ping->next = ping_head; + ping_head = ping; // insert at head + + t_ping_register_pcb(); + t_ping_send(t_ping_pcb, ping); + + // set timers for time-out and cadence + sys_timeout(Ping_timeout_ms, t_ping_timeout, ping); + sys_timeout(Ping_coarse, t_ping_coarse_tmr, ping); + } + } // Check if any ping requests is completed, and publish the results void PingResponsePoll(void) { - if (ping.done) { - uint32_t success = ping.total_count - ping.timeout_count; - uint32_t ip = ping_opt.ip; + Ping_t *ping = ping_head; + Ping_t **prev_link = &ping_head; // previous link pointer (used to remove en entry) - // Serial.printf( - // "DEBUG ping_sent_cb: ping reply\n" - // "\tsuccess_count = %d \n" - // "\ttimeout_count = %d \n" - // "\tmin_time = %d \n" - // "\tmax_time = %d \n" - // "\tavg_time = %d \n", - // success, ping.timeout_count, - // ping.min_time, ping.max_time, - // success ? ping.sum_time / success : 0 - // ); + while (ping != nullptr) { + if (ping->done) { + uint32_t success = ping->success_count; + uint32_t ip = ping->ip; - Response_P(PSTR("{\"" D_JSON_PING "\":{\"%d.%d.%d.%d\":{" - "\"Reachable\":%s" - ",\"Success\":%d" - ",\"Timeout\":%d" - ",\"MinTime\":%d" - ",\"MaxTime\":%d" - ",\"AvgTime\":%d" - "}}}"), - ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24, - success ? "true" : "false", - success, ping.timeout_count, - ping.min_time, ping.max_time, - success ? ping.sum_time / success : 0 - ); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_PING)); - XdrvRulesProcess(); - ping.done = false; - ping.busy = false; + Response_P(PSTR("{\"" D_JSON_PING "\":{\"%d.%d.%d.%d\":{" + "\"Reachable\":%s" + ",\"Success\":%d" + ",\"Timeout\":%d" + ",\"MinTime\":%d" + ",\"MaxTime\":%d" + ",\"AvgTime\":%d" + "}}}"), + ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24, + success ? "true" : "false", + success, ping->timeout_count, + success ? ping->min_time : 0, ping->max_time, + success ? ping->sum_time / success : 0 + ); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_PING)); + XdrvRulesProcess(); + + // remove from linked list + *prev_link = ping->next; + // don't increment prev_link + Ping_t *ping_to_delete = ping; + ping = ping->next; // move to next before deleting the object + delete ping_to_delete; // free memory allocated + } else { + prev_link = &ping->next; + ping = ping->next; + } } } +/*********************************************************************************************\ + * Ping Command +\*********************************************************************************************/ + void CmndPing(void) { uint32_t count = XdrvMailbox.index; IPAddress ip; RemoveSpace(XdrvMailbox.data); - if (count > 8) { count = 8; } - - if (ping.busy) { - ResponseCmndChar_P(PSTR("Ping busy")); - return; - } + if (count > 10) { count = 8; } // max 8 seconds if (WiFi.hostByName(XdrvMailbox.data, ip)) { - memset(&ping_opt, 0, sizeof(ping_opt)); - memset(&ping, 0, sizeof(ping)); - ping.min_time = UINT32_MAX; - - ping_opt.count = count; - ping_opt.coarse_time = 1; // wait 1 second between messages - ping_opt.ip = ip; - - // callbacks - ping_opt.recv_function = (ping_recv_function) ping_recv_cb; // at each response or time-out - ping_opt.sent_function = (ping_sent_function) ping_sent_cb; // when all packets have been sent and reveived - - ping.busy = true; - if (ping_start(&ping_opt)) { + bool ok = t_ping_start(ip, count); + if (ok) { ResponseCmndDone(); } else { - ResponseCmndChar_P(PSTR("Unable to send Ping")); - ping.busy = false; + ResponseCmndChar_P(PSTR("Ping already ongoing for this IP")); } } else { ResponseCmndChar_P(PSTR("Unable to resolve IP address")); } - } @@ -157,7 +332,7 @@ bool Xdrv38(uint8_t function) switch (function) { case FUNC_EVERY_250_MSECOND: - PingResponsePoll(); + PingResponsePoll(); // TODO break; case FUNC_COMMAND: result = DecodeCommand(kPingCommands, PingCommand); @@ -166,4 +341,4 @@ bool Xdrv38(uint8_t function) return result; } -#endif // USE_PING +#endif // USE_PING \ No newline at end of file From 49ef6598fca07aabbc5e20bd56baed33143cfd0f Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 15 Apr 2020 18:55:04 +0200 Subject: [PATCH 21/70] Update size of Ping --- tasmota/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 97476820f..6ac041770 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -391,7 +391,7 @@ #define SUNRISE_DAWN_ANGLE DAWN_NORMAL // Select desired Dawn Angle from (DAWN_NORMAL, DAWN_CIVIL, DAWN_NAUTIC, DAWN_ASTRONOMIC) // -- Ping ---------------------------------------- -// #define USE_PING // Enable Ping command (+3k code) +// #define USE_PING // Enable Ping command (+2k code) // -- Rules or Script ---------------------------- // Select none or only one of the below defines From ba20008cd91a2984549244eee55cd15a89ec3b7b Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Wed, 15 Apr 2020 19:42:50 +0200 Subject: [PATCH 22/70] Don't apply DimmerRange to CT PWM --- tasmota/xdrv_04_light.ino | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index eda02eafb..a636fdeb0 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1985,6 +1985,15 @@ bool isChannelGammaCorrected(uint32_t channel) { return true; } +// is the channel a regular PWM or ColorTemp control +bool isChannelCT(uint32_t channel) { + if (PHILIPS == my_module_type) { + if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return true; } // PMW reserved for CT + if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return true; } // PMW reserved for CT + } + return false; +} + // Calculate the Gamma correction, if any, for fading, using the fast Gamma curve (10 bits in+out) uint16_t fadeGamma(uint32_t channel, uint16_t v) { if (isChannelGammaCorrected(channel)) { @@ -2106,7 +2115,9 @@ void LightSetOutputs(const uint16_t *cur_col_10) { if (pin[GPIO_PWM1 +i] < 99) { //AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d"), i, cur_col_10[i]); uint16_t cur_col = cur_col_10[i + Light.pwm_offset]; - cur_col = cur_col > 0 ? changeUIntScale(cur_col, 0, Settings.pwm_range, Light.pwm_min, Light.pwm_max) : 0; // shrink to the range of pwm_min..pwm_max + if (!isChannelCT(i)) { // if CT don't use pwm_min and pwm_max + cur_col = cur_col > 0 ? changeUIntScale(cur_col, 0, Settings.pwm_range, Light.pwm_min, Light.pwm_max) : 0; // shrink to the range of pwm_min..pwm_max + } analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col : cur_col); } } From 5c43f4c4c216d7465af440122684753ecea34992 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 16 Apr 2020 11:00:56 +0200 Subject: [PATCH 23/70] Fix ESP32 compile error Fix ESP32 compile error (#8195) --- tasmota/xdrv_04_light.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index a636fdeb0..1c5751829 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1987,10 +1987,12 @@ bool isChannelGammaCorrected(uint32_t channel) { // is the channel a regular PWM or ColorTemp control bool isChannelCT(uint32_t channel) { +#ifdef ESP8266 if (PHILIPS == my_module_type) { if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return true; } // PMW reserved for CT if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return true; } // PMW reserved for CT } +#endif // ESP8266 return false; } From d2b7b4012f6692cd30e01bc23937adc03d8bc5b2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 16 Apr 2020 14:59:01 +0200 Subject: [PATCH 24/70] More ESP32 compatibility More ESP32 compatibility (breaks current ESP32 configuration again!) --- tasmota/settings.h | 31 +++++++++++++++++++++++++------ tasmota/xdrv_99_debug.ino | 22 ++++++++++++++++++++-- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 3f8827636..01f0cf174 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -86,7 +86,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t energy_weekend : 1; // bit 20 (v6.6.0.8) - CMND_TARIFF uint32_t dds2382_model : 1; // bit 21 (v6.6.0.14) - SetOption71 - Select different Modbus registers for Active Energy (#6531) uint32_t hardware_energy_total : 1; // bit 22 (v6.6.0.15) - SetOption72 - Enable hardware energy total counter as reference (#6561) - uint32_t mqtt_buttons : 1; // bit 23 (v8.2.0.3) - SetOption73 - Detach buttons from relays and enable MQTT action state for multipress + uint32_t mqtt_buttons : 1; // bit 23 (v8.2.0.3) - SetOption73 - Detach buttons from relays and enable MQTT action state for multipress uint32_t ds18x20_internal_pullup : 1; // bit 24 (v7.0.0.1) - SetOption74 - Enable internal pullup for single DS18x20 sensor uint32_t grouptopic_mode : 1; // bit 25 (v7.0.0.1) - SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1) uint32_t bootcount_update : 1; // bit 26 (v7.0.0.4) - SetOption76 - Enable incrementing bootcount when deepsleep is enabled @@ -245,7 +245,7 @@ typedef struct { } EnergyUsage; -typedef struct PACKED { +typedef struct { uint8_t fnid = 0; uint8_t dpid = 0; } TuyaFnidDpidMap; @@ -253,7 +253,7 @@ typedef struct PACKED { const uint32_t settings_text_size = 699; // Settings.text_pool[size] = Settings.display_model (2D2) - Settings.text_pool (017) const uint8_t MAX_TUYA_FUNCTIONS = 16; -struct PACKED SYSCFG { +struct SYSCFG { uint16_t cfg_holder; // 000 v6 header uint16_t cfg_size; // 002 unsigned long save_flag; // 004 @@ -369,7 +369,13 @@ struct PACKED SYSCFG { uint8_t module; // 474 uint8_t ws_color[4][3]; // 475 uint8_t ws_width[3]; // 481 - myio my_gp; // 484 + +#ifdef ESP8266 + myio my_gp; // 484 - 17 bytes (ESP8266) +#else // ESP32 + uint8_t free_esp32_484[17]; // 484 +#endif // ESP8266 - ESP32 + uint8_t my_adc0; // 495 uint16_t light_pixels; // 496 uint8_t light_color[5]; // 498 @@ -397,7 +403,14 @@ struct PACKED SYSCFG { uint32_t ip_address[4]; // 544 unsigned long energy_kWhtotal; // 554 +#ifdef ESP8266 char ex_mqtt_fulltopic[100]; // 558 +#else // ESP32 + myio my_gp; // 558 - 40 bytes (ESP32) + mytmplt user_template; // 580 - 35 bytes (ESP32) + + uint8_t free_esp32_5a3[25]; // 5A3 +#endif // ESP8266 - ESP32 SysBitfield2 flag2; // 5BC unsigned long pulse_counter[MAX_COUNTERS]; // 5C0 @@ -423,7 +436,12 @@ struct PACKED SYSCFG { char user_template_name[15]; // 720 15 bytes - Backward compatibility since v8.2.0.3 - mytmplt user_template; // 72F 14 bytes +#ifdef ESP8266 + mytmplt user_template; // 72F 14 bytes (ESP8266) +#else // ESP32 + uint8_t free_esp32_72f[14]; // 72F +#endif // ESP8266 - ESP32 + uint8_t novasds_startingoffset; // 73D uint8_t web_color[18][3]; // 73E uint16_t display_width; // 774 @@ -507,8 +525,9 @@ struct PACKED SYSCFG { uint8_t zb_free_byte; // F33 uint16_t pms_wake_interval; // F34 - uint8_t free_f36[130]; // F36 + uint8_t free_f36[130]; // F36 - Decrement if adding new Setting variables just above and below + // Only 32 bit boundary variables below uint16_t pulse_counter_debounce_low; // FB8 uint16_t pulse_counter_debounce_high; // FBA uint32_t keeloq_master_msb; // FBC diff --git a/tasmota/xdrv_99_debug.ino b/tasmota/xdrv_99_debug.ino index 538ac7f71..d18ab5833 100644 --- a/tasmota/xdrv_99_debug.ino +++ b/tasmota/xdrv_99_debug.ino @@ -172,11 +172,11 @@ void CpuLoadLoop(void) CPU_loops ++; if ((CPU_last_millis + (CPU_load_check *1000)) <= CPU_last_loop_time) { #if defined(F_CPU) && (F_CPU == 160000000L) - int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *800) ); + int CPU_load = 100 - ( (CPU_loops*(1 + 30*ssleep)) / (CPU_load_check *800) ); CPU_loops = CPU_loops / CPU_load_check; AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(160MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); #else - int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *400) ); + int CPU_load = 100 - ( (CPU_loops*(1 + 30*ssleep)) / (CPU_load_check *400) ); CPU_loops = CPU_loops / CPU_load_check; AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(80MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); #endif @@ -188,6 +188,7 @@ void CpuLoadLoop(void) /*******************************************************************************************/ +#ifdef ESP8266 #if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) // All version before core 2.4.2 // https://github.com/esp8266/Arduino/issues/2557 @@ -224,10 +225,20 @@ void DebugFreeMem(void) #endif // ARDUINO_ESP8266_RELEASE_2_x_x +#else // ESP32 + +void DebugFreeMem(void) +{ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d"), ESP.getFreeHeap()); +} + +#endif // ESP8266 - ESP32 + /*******************************************************************************************/ void DebugRtcDump(char* parms) { +#ifdef ESP8266 #define CFG_COLS 16 uint16_t idx; @@ -283,6 +294,7 @@ void DebugRtcDump(char* parms) snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data); AddLog(LOG_LEVEL_INFO); } +#endif // ESP8266 } /*******************************************************************************************/ @@ -385,6 +397,7 @@ void DebugCfgPoke(char* parms) void SetFlashMode(uint8_t mode) { +#ifdef ESP8266 uint8_t *_buffer; uint32_t address; @@ -400,6 +413,7 @@ void SetFlashMode(uint8_t mode) } } delete[] _buffer; +#endif // ESP8266 } /*********************************************************************************************\ @@ -503,6 +517,7 @@ uint32_t DebugSwap32(uint32_t x) { void CmndFlashDump(void) { +#ifdef ESP8266 // FlashDump // FlashDump 0xFF000 // FlashDump 0xFC000 10 @@ -533,6 +548,7 @@ void CmndFlashDump(void) DebugSwap32(values[4]), DebugSwap32(values[5]), DebugSwap32(values[6]), DebugSwap32(values[7])); } ResponseCmndDone(); +#endif // ESP8266 } #ifdef USE_I2C @@ -600,10 +616,12 @@ void CmndI2cRead(void) void CmndI2cStretch(void) { +#ifdef ESP8266 if (i2c_flg && (XdrvMailbox.payload > 0)) { Wire.setClockStretchLimit(XdrvMailbox.payload); } ResponseCmndDone(); +#endif // ESP8266 } void CmndI2cClock(void) From 538dfbef2e2f31a6754b816da8d28c9a881ef993 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 16 Apr 2020 16:29:33 +0200 Subject: [PATCH 25/70] More ESP32 compatibility --- tasmota/xdrv_01_webserver.ino | 15 +++++++++++++-- tasmota/xdrv_99_debug.ino | 4 +++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 5d286bf2e..008310cf6 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1675,17 +1675,28 @@ void ModuleSaveSettings(void) if (ValidGPIO(i, cmodule.io[i])) { snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i); WebGetArg(webindex, tmp, sizeof(tmp)); - Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); + uint8_t value = (!strlen(tmp)) ? 0 : atoi(tmp); +#ifdef ESP8266 + Settings.my_gp.io[i] = value; +#else // ESP32 + if (i == ADC0_PIN) { + Settings.my_adc0 = value; + } else { + Settings.my_gp.io[i] = value; + } +#endif // ESP8266 - ESP32 + gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(value); } } } +#ifdef ESP8266 #ifndef USE_ADC_VCC // WebGetArg("g17", tmp, sizeof(tmp)); WebGetArg("g" STR(ADC0_PIN), tmp, sizeof(tmp)); Settings.my_adc0 = (!strlen(tmp)) ? 0 : atoi(tmp); gpios += F(", " D_ADC "0 "); gpios += String(Settings.my_adc0); #endif // USE_ADC_VCC +#endif // ESP8266 AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), ModuleName().c_str(), gpios.c_str()); } diff --git a/tasmota/xdrv_99_debug.ino b/tasmota/xdrv_99_debug.ino index d18ab5833..feb04cabd 100644 --- a/tasmota/xdrv_99_debug.ino +++ b/tasmota/xdrv_99_debug.ino @@ -229,7 +229,9 @@ void DebugFreeMem(void) void DebugFreeMem(void) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d"), ESP.getFreeHeap()); + register uint8_t *sp asm("a1"); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), sp - pxTaskGetStackStart(NULL), XdrvMailbox.data); } #endif // ESP8266 - ESP32 From 367658b75be252e21b952b75aaee6ed5b19f5b04 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 16 Apr 2020 18:33:26 +0200 Subject: [PATCH 26/70] More ESP32 compatibility --- .../src/esp8266toEsp32.cpp | 41 ++++++++++++++----- .../src/esp8266toEsp32.h | 19 ++++----- tasmota/support.ino | 6 ++- tasmota/support_command.ino | 2 +- tasmota/tasmota_compat.h | 1 - tasmota/xdrv_01_webserver.ino | 2 +- 6 files changed, 46 insertions(+), 25 deletions(-) diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp index f4a17f368..029d41470 100644 --- a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp +++ b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp @@ -20,18 +20,44 @@ #include #include #include "esp8266toEsp32.h" + // ESP Stuff -struct rst_info resetInfo; + +String ESP32GetResetReason(uint32_t cpu_no) +{ + // tools\sdk\include\esp32\rom\rtc.h + switch (rtc_get_reset_reason( (RESET_REASON) cpu_no)) { + case POWERON_RESET : return F("Vbat power on reset"); // 1 + case SW_RESET : return F("Software reset digital core"); // 3 + case OWDT_RESET : return F("Legacy watch dog reset digital core"); // 4 + case DEEPSLEEP_RESET : return F("Deep Sleep reset digital core"); // 5 + case SDIO_RESET : return F("Reset by SLC module, reset digital core"); // 6 + case TG0WDT_SYS_RESET : return F("Timer Group0 Watch dog reset digital core"); // 7 + case TG1WDT_SYS_RESET : return F("Timer Group1 Watch dog reset digital core"); // 8 + case RTCWDT_SYS_RESET : return F("RTC Watch dog Reset digital core"); // 9 + case INTRUSION_RESET : return F("Instrusion tested to reset CPU"); // 10 + case TGWDT_CPU_RESET : return F("Time Group reset CPU"); // 11 + case SW_CPU_RESET : return F("Software reset CPU"); // 12 + case RTCWDT_CPU_RESET : return F("RTC Watch dog Reset CPU"); // 13 + case EXT_CPU_RESET : return F("or APP CPU, reseted by PRO CPU"); // 14 + case RTCWDT_BROWN_OUT_RESET : return F("Reset when the vdd voltage is not stable"); // 15 + case RTCWDT_RTC_RESET : return F("RTC Watch dog reset digital core and rtc module"); // 16 + default : return F("NO_MEAN"); // 0 + } +} String ESP_getResetReason(void) { - // CPU 0 - return String(rtc_get_reset_reason(0)); + return ESP32GetResetReason(0); // CPU 0 } -String ESP_getResetInfo(void) +uint32_t ESP_ResetInfoReason(void) { - return String(PSTR("0")); + RESET_REASON reason = rtc_get_reset_reason(0); + if (POWERON_RESET == reason) { return REASON_DEFAULT_RST; } + if (SW_CPU_RESET == reason) { return REASON_SOFT_RESTART; } + if (DEEPSLEEP_RESET == reason) { return REASON_DEEP_SLEEP_AWAKE; } + if (SW_RESET == reason) { return REASON_EXT_SYS_RST; } } uint32_t ESP_getBootVersion(void) @@ -74,11 +100,6 @@ String String_ESP_getChipId() return String(uint32_t(mac >> 32)) + String(uint32_t(mac)); } -uint32_t ESP_getFlashChipRealSize() -{ - return ESP.getFlashChipSize(); -} - uint32_t ESP_getSketchSize(void) { static uint32_t sketchsize = 0; diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h index 8a30da55d..28e187d52 100644 --- a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h +++ b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h @@ -34,15 +34,14 @@ #define ESP_flashReadHeader(offset, data, size) ESP32_flashRead(offset, data, size) #define ESP_flashRead(offset, data, size) ESP32_flashRead(offset, data, size) String ESP_getResetReason(void); +uint32_t ESP_ResetInfoReason(void); uint32_t ESP_getBootVersion(void); bool ESP_rtcUserMemoryWrite(uint32_t offset, uint32_t *data, size_t size); bool ESP_rtcUserMemoryRead(uint32_t offset, uint32_t *data, size_t size); void ESP_reset(); -String ESP_getResetInfo(void); uint32_t ESP_getFlashChipId(); uint32_t ESP_getChipId(); String String_ESP_getChipId(); -uint32_t ESP_getFlashChipRealSize(); uint32_t ESP_getSketchSize(); // Analog @@ -67,7 +66,6 @@ typedef double real64_t; #define ETS_UART_INTR_DISABLE() #define ETS_UART_INTR_ENABLE() -#define getChipId() getEfuseMac() #define ESPhttpUpdate httpUpdate #define getFlashChipRealSize() getFlashChipSize() @@ -92,14 +90,13 @@ typedef int SerialConfig; #undef LWIP_IPV6 -struct rst_info -{ - int reason; -}; - -#define REASON_DEFAULT_RST 1 -#define REASON_EXT_SYS_RST 2 -#define REASON_DEEP_SLEEP_AWAKE 3 +#define REASON_DEFAULT_RST 0 // "Power on" normal startup by power on +#define REASON_WDT_RST 1 // "Hardware Watchdog" hardware watch dog reset +#define REASON_EXCEPTION_RST 2 // "Exception" exception reset, GPIO status won’t change +#define REASON_SOFT_WDT_RST 3 // "Software Watchdog" software watch dog reset, GPIO status won’t change +#define REASON_SOFT_RESTART 4 // "Software/System restart" software restart ,system_restart , GPIO status won’t change +#define REASON_DEEP_SLEEP_AWAKE 5 // "Deep-Sleep Wake" wake up from deep-sleep +#define REASON_EXT_SYS_RST 6 // "External System" external system reset // memmove ... #define memcpy_P memcpy diff --git a/tasmota/support.ino b/tasmota/support.ino index 9c720c996..0435293e6 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -99,7 +99,11 @@ uint32_t ResetReason(void) REASON_DEEP_SLEEP_AWAKE = 5, // "Deep-Sleep Wake" wake up from deep-sleep REASON_EXT_SYS_RST = 6 // "External System" external system reset */ - return resetInfo.reason; +#ifdef ESP8266 + return resetInfo.reason; // Returns Tasmota reason codes +#else + return ESP_ResetInfoReason(); +#endif } String GetResetReason(void) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 6897384d0..0d4e12236 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -448,7 +448,7 @@ void CmndStatus(void) D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\"" D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"), ESP_getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, - ESP.getFlashChipSize()/1024, ESP_getFlashChipRealSize()/1024, ESP_getFlashChipId(), ESP.getFlashChipMode(), + ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP_getFlashChipId(), ESP.getFlashChipMode(), LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2, feature5, feature6); XsnsDriverState(); ResponseAppend_P(PSTR(",\"Sensors\":")); diff --git a/tasmota/tasmota_compat.h b/tasmota/tasmota_compat.h index 6571d0f34..839f5cef8 100644 --- a/tasmota/tasmota_compat.h +++ b/tasmota/tasmota_compat.h @@ -17,7 +17,6 @@ #define ESP_reset() ESP.reset() #define ESP_getBootVersion() ESP.getBootVersion() #define ESP_getFlashChipId() ESP.getFlashChipId() -#define ESP_getFlashChipRealSize() ESP.getFlashChipRealSize() #define ESP_getSketchSize() ESP.getSketchSize() #define ESP_getChipId() ESP.getChipId() // diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 008310cf6..8b5806938 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2213,7 +2213,7 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1}2 ")); // Empty line WSContentSend_P(PSTR("}1" D_ESP_CHIP_ID "}2%d"), ESP_getChipId()); WSContentSend_P(PSTR("}1" D_FLASH_CHIP_ID "}20x%06X"), ESP_getFlashChipId()); - WSContentSend_P(PSTR("}1" D_FLASH_CHIP_SIZE "}2%dkB"), ESP_getFlashChipRealSize() / 1024); + 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); From 618ac9ab14a907ec141fbb02e2f7246f8f438907 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 16 Apr 2020 19:36:14 +0200 Subject: [PATCH 27/70] Added Zigbee attribute types --- tasmota/xdrv_23_zigbee_5_converters.ino | 854 +++++++++++++----------- 1 file changed, 467 insertions(+), 387 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 7a8ea4806..5e39771c5 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -23,6 +23,72 @@ * ZCL \*********************************************************************************************/ + +enum Z_DataTypes { + Znodata = 0x00, + Zdata8 = 0x08, Zdata16, Zdata24, Zdata32, Zdata40, Zdata48, Zdata56, Zdata64, + Zbool = 0x10, + Zmap8 = 0x18, Zmap16, Zmap24, Zmap32, Zmap40, Zmap48, Zmap56, Zmap64, + Zuint8 = 0x20, Zuint16, Zuint24, Zuint32, Zuint40, Zuint48, Zuint56, Zuint64, + Zint8 = 0x28, Zint16, Zint24, Zint32, Zint40, Zint48, Zint56, Zint64, + Zenum8 = 0x30, Zenum16 = 0x31, + Zsemi = 0x38, Zsingle = 0x39, Zdouble = 0x3A, + Zoctstr = 0x41, Zstring = 0x42, Zoctstr16 = 0x43, Zstring16 = 0x44, + Arrray = 0x48, + Zstruct = 0x4C, + Zset = 0x50, Zbag = 0x51, + ZToD = 0xE0, Zdate = 0xE1, ZUTC = 0xE2, + ZclusterId = 0xE8, ZattribId = 0xE9, ZbacOID = 0xEA, + ZEUI64 = 0xF0, Zkey128 = 0xF1, + Zunk = 0xFF +}; + +// +// get the lenth in bytes for a data-type +// return 0 if unknown of type specific +// +// Note: this code is smaller than a static array +uint8_t Z_getDatatypeLen(uint8_t t) { + if ( ((t >= 0x08) && (t <= 0x0F)) || // data8 - data64 + ((t >= 0x18) && (t <= 0x2F)) ) { // map/uint/int + return (t & 0x07) + 1; + } + switch (t) { + case Zbool: + case Zenum8: + return 1; + case Zenum16: + case Zsemi: + case ZclusterId: + case ZattribId: + return 2; + case Zsingle: + case ZToD: + case Zdate: + case ZUTC: + case ZbacOID: + return 4; + case Zdouble: + case ZEUI64: + return 8; + case Zkey128: + return 16; + case Znodata: + default: + return 0; + } +} + +// typedef struct Z_DataTypeMapping { +// uint8_t datatype; +// uint8_t len; // len in bytes and add 0x80 if DISCRETE +// } + +// const Z_DataTypeMapping Z_types[] PROGMEM = { +// { Znodata, 0 }, +// { Zdata8, 0 }, +// }; + typedef union ZCLHeaderFrameControl_t { struct { uint8_t frame_type : 2; // 00 = across entire profile, 01 = cluster specific @@ -188,7 +254,7 @@ uint8_t toPercentageCR2032(uint32_t voltage) { uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer &buf, - uint32_t offset, uint32_t len) { + uint32_t offset, uint32_t buflen) { uint32_t i = offset; uint32_t attrtype = buf.get8(i++); @@ -196,105 +262,98 @@ uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer // fallback - enter a null value json[attrid_str] = (char*) nullptr; + uint32_t len = Z_getDatatypeLen(attrtype); // pre-compute lenght, overloaded for variable length attributes + // now parse accordingly to attr type switch (attrtype) { - case 0x00: // nodata - case 0xFF: // unk - break; - case 0x10: // bool - case 0x20: // uint8 - case 0x30: // enum8 + // case Znodata: // nodata + // case Zunk: // unk + // break; + case Zbool: // bool + case Zuint8: // uint8 + case Zenum8: // enum8 { uint8_t uint8_val = buf.get8(i); - i += 1; + // i += 1; if (0xFF != uint8_val) { json[attrid_str] = uint8_val; } } break; - case 0x21: // uint16 - case 0x31: // enum16 + case Zuint16: // uint16 + case Zenum16: // enum16 { uint16_t uint16_val = buf.get16(i); - i += 2; + // i += 2; if (0xFFFF != uint16_val) { json[attrid_str] = uint16_val; } } break; - case 0x23: // uint32 + case Zuint32: // uint32 { uint32_t uint32_val = buf.get32(i); - i += 4; + // i += 4; if (0xFFFFFFFF != uint32_val) { json[attrid_str] = uint32_val; } } break; - // Note: uint40, uint48, uint56, uint64 are stored as Hex - case 0x24: // uint40 - case 0x25: // uint48 - case 0x26: // uint56 - case 0x27: // uint64 + // Note: uint40, uint48, uint56, uint64 are displayed as Hex + // Note: int40, int48, int56, int64 are displayed as Hex + case Zuint40: // uint40 + case Zuint48: // uint48 + case Zuint56: // uint56 + case Zuint64: // uint64 + case Zint40: // int40 + case Zint48: // int48 + case Zint56: // int56 + case Zint64: // int64 { - uint8_t len = attrtype - 0x1F; // 5 - 8 + // uint8_t len = attrtype - 0x27; // 5 - 8 // print as HEX char hex[2*len+1]; ToHex_P(buf.buf(i), len, hex, sizeof(hex)); json[attrid_str] = hex; - i += len; + // i += len; } break; - case 0x28: // uint8 + case Zint8: // int8 { int8_t int8_val = buf.get8(i); - i += 1; + // i += 1; if (0x80 != int8_val) { json[attrid_str] = int8_val; } } break; - case 0x29: // uint16 + case Zint16: // int16 { int16_t int16_val = buf.get16(i); - i += 2; + // i += 2; if (0x8000 != int16_val) { json[attrid_str] = int16_val; } } break; - case 0x2B: // uint16 + case Zint32: // int32 { int32_t int32_val = buf.get32(i); - i += 4; + // i += 4; if (0x80000000 != int32_val) { json[attrid_str] = int32_val; } } break; - // Note: int40, int48, int56, int64 are not stored as Hex - case 0x2C: // int40 - case 0x2D: // int48 - case 0x2E: // int56 - case 0x2F: // int64 - { - uint8_t len = attrtype - 0x27; // 5 - 8 - // print as HEX - char hex[2*len+1]; - ToHex_P(buf.buf(i), len, hex, sizeof(hex)); - json[attrid_str] = hex; - i += len; - } - break; - case 0x41: // octet string, 1 byte len - case 0x42: // char string, 1 byte len - case 0x43: // octet string, 2 bytes len - case 0x44: // char string, 2 bytes len + case Zoctstr: // octet string, 1 byte len + case Zstring: // char string, 1 byte len + case Zoctstr16: // octet string, 2 bytes len + case Zstring16: // char string, 2 bytes len // For strings, default is to try to do a real string, but reverts to octet stream if null char is present or on some exceptions { bool parse_as_string = true; - uint32_t len = (attrtype <= 0x42) ? buf.get8(i) : buf.get16(i); // len is 8 or 16 bits + len = (attrtype <= 0x42) ? buf.get8(i) : buf.get16(i); // len is 8 or 16 bits i += (attrtype <= 0x42) ? 1 : 2; // increment pointer if (i + len > buf.len()) { // make sure we don't get past the buffer len = buf.len() - i; @@ -302,14 +361,6 @@ uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer // check if we can safely use a string if ((0x41 == attrtype) || (0x43 == attrtype)) { parse_as_string = false; } - // else { - // for (uint32_t j = 0; j < len; j++) { - // if (0x00 == buf.get8(i+j)) { - // parse_as_string = false; - // break; - // } - // } - // } if (parse_as_string) { char str[len+1]; @@ -323,97 +374,82 @@ uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer json[attrid_str] = hex; } - i += len; - break; + // i += len; + // break; } - i += buf.get8(i) + 1; + // i += buf.get8(i) + 1; break; - case 0x08: // data8 - case 0x18: // map8 + case Zdata8: // data8 + case Zmap8: // map8 { uint8_t uint8_val = buf.get8(i); - i += 1; + // i += 1; json[attrid_str] = uint8_val; } break; - case 0x09: // data16 - case 0x19: // map16 + case Zdata16: // data16 + case Zmap16: // map16 { uint16_t uint16_val = buf.get16(i); - i += 2; + // i += 2; json[attrid_str] = uint16_val; } break; - case 0x0B: // data32 - case 0x1B: // map32 + case Zdata32: // data32 + case Zmap32: // map32 { uint32_t uint32_val = buf.get32(i); - i += 4; + // i += 4; json[attrid_str] = uint32_val; } break; - // TODO - case 0x39: // float + case Zsingle: // float { uint32_t uint32_val = buf.get32(i); float * float_val = (float*) &uint32_val; - i += 4; + // i += 4; json[attrid_str] = *float_val; } break; - case 0xE0: // ToD - case 0xE1: // date - case 0xE2: // UTC - i += 4; - break; - - case 0xE8: // clusterId - case 0xE9: // attribId - i += 2; - break; - case 0xEA: // bacOID - i += 4; - break; - - case 0xF0: // EUI64 - i += 8; - break; - case 0xF1: // key128 - i += 16; + // TODO + case ZToD: // ToD + case Zdate: // date + case ZUTC: // UTC + case ZclusterId: // clusterId + case ZattribId: // attribId + case ZbacOID: // bacOID + case ZEUI64: // EUI64 + case Zkey128: // key128 + case Zsemi: // semi (float on 2 bytes) break; // Other un-implemented data types - case 0x0A: // data24 - case 0x0C: // data40 - case 0x0D: // data48 - case 0x0E: // data56 - case 0x0F: // data64 - i += attrtype - 0x07; // 2-8 + case Zdata24: // data24 + case Zdata40: // data40 + case Zdata48: // data48 + case Zdata56: // data56 + case Zdata64: // data64 break; // map - case 0x1A: // map24 - case 0x1C: // map40 - case 0x1D: // map48 - case 0x1E: // map56 - case 0x1F: // map64 - i += attrtype - 0x17; + case Zmap24: // map24 + case Zmap40: // map40 + case Zmap48: // map48 + case Zmap56: // map56 + case Zmap64: // map64 break; - // semi - case 0x38: // semi (float on 2 bytes) - i += 2; - break; - case 0x3A: // double precision + case Zdouble: // double precision { uint64_t uint64_val = buf.get64(i); double * double_val = (double*) &uint64_val; - i += 8; + // i += 8; json[attrid_str] = *double_val; } break; } + i += len; // String pp; // pretty print // json[attrid_str].prettyPrintTo(pp); @@ -529,12 +565,36 @@ void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { // 1 = remove initial value typedef int32_t (*Z_AttrConverter)(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); typedef struct Z_AttributeConverter { - uint16_t cluster; + uint8_t type; + uint8_t cluster_short; uint16_t attribute; const char * name; Z_AttrConverter func; } Z_AttributeConverter; +enum Cx_cluster_short { + Cx0000, Cx0001, Cx0002, Cx0003, Cx0004, Cx0005, Cx0006, Cx0007, + Cx0008, Cx0009, Cx000A, Cx000B, Cx000C, Cx000D, Cx000E, Cx000F, + Cx0010, Cx0011, Cx0012, Cx0013, Cx0014, Cx001A, Cx0020, Cx0100, + Cx0101, Cx0102, Cx0300, Cx0400, Cx0401, Cx0402, Cx0403, Cx0404, + Cx0405, Cx0406, Cx0B01, Cx0B05, +}; + +const uint16_t Cx_cluster[] PROGMEM = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x001A, 0x0020, 0x0100, + 0x0101, 0x0102, 0x0300, 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, + 0x0405, 0x0406, 0x0B01, 0x0B05, +}; + +uint16_t CxToCluster(uint8_t cx) { + if (cx < sizeof(Cx_cluster)/sizeof(Cx_cluster[0])) { + return pgm_read_word(&Cx_cluster[cx]); + } + return 0xFFFF; +} + ZF(ZCLVersion) ZF(AppVersion) ZF(StackVersion) ZF(HWVersion) ZF(Manufacturer) ZF(ModelId) ZF(DateCode) ZF(PowerSource) ZF(SWBuildID) ZF(Power) ZF(SwitchType) ZF(Dimmer) ZF(MainsVoltage) ZF(MainsFrequency) ZF(BatteryVoltage) ZF(BatteryPercentage) @@ -606,7 +666,7 @@ ZF(WhitePointY) ZF(ColorPointRX) ZF(ColorPointRY) ZF(ColorPointRIntensity) ZF(Co ZF(ColorPointGIntensity) ZF(ColorPointBX) ZF(ColorPointBY) ZF(ColorPointBIntensity) ZF(Illuminance) ZF(IlluminanceMinMeasuredValue) ZF(IlluminanceMaxMeasuredValue) ZF(IlluminanceTolerance) -ZF(IlluminanceLightSensorType) ZF(IlluminanceLevelStatus) +ZF(IlluminanceLightSensorType) ZF(IlluminanceLevelStatus) ZF(IlluminanceTargetLevel) ZF(Temperature) ZF(TemperatureMinMeasuredValue) ZF(TemperatureMaxMeasuredValue) ZF(TemperatureTolerance) @@ -621,341 +681,361 @@ ZF(Humidity) ZF(HumidityMinMeasuredValue) ZF(HumidityMaxMeasuredValue) ZF(Humidi ZF(Occupancy) ZF(OccupancySensorType) ZF(CompanyName) ZF(MeterTypeID) ZF(DataQualityID) ZF(CustomerName) ZF(Model) ZF(PartNumber) -ZF(SoftwareRevision) ZF(POD) ZF(AvailablePower) ZF(PowerThreshold) +ZF(SoftwareRevision) ZF(POD) ZF(AvailablePower) ZF(PowerThreshold) ZF(ProductRevision) ZF(UtilityName) ZF(NumberOfResets) ZF(PersistentMemoryWrites) ZF(LastMessageLQI) ZF(LastMessageRSSI) // list of post-processing directives const Z_AttributeConverter Z_PostProcess[] PROGMEM = { - { 0x0000, 0x0000, Z(ZCLVersion), &Z_Copy }, - { 0x0000, 0x0001, Z(AppVersion), &Z_Copy }, - { 0x0000, 0x0002, Z(StackVersion), &Z_Copy }, - { 0x0000, 0x0003, Z(HWVersion), &Z_Copy }, - { 0x0000, 0x0004, Z(Manufacturer), &Z_ManufKeep }, // record Manufacturer - { 0x0000, 0x0005, Z(ModelId), &Z_ModelKeep }, // record Model - { 0x0000, 0x0006, Z(DateCode), &Z_Copy }, - { 0x0000, 0x0007, Z(PowerSource), &Z_Copy }, - { 0x0000, 0x4000, Z(SWBuildID), &Z_Copy }, - { 0x0000, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values + { Zuint8, Cx0000, 0x0000, Z(ZCLVersion), &Z_Copy }, + { Zuint8, Cx0000, 0x0001, Z(AppVersion), &Z_Copy }, + { Zuint8, Cx0000, 0x0002, Z(StackVersion), &Z_Copy }, + { Zuint8, Cx0000, 0x0003, Z(HWVersion), &Z_Copy }, + { Zstring, Cx0000, 0x0004, Z(Manufacturer), &Z_ManufKeep }, // record Manufacturer + { Zstring, Cx0000, 0x0005, Z(ModelId), &Z_ModelKeep }, // record Model + { Zstring, Cx0000, 0x0006, Z(DateCode), &Z_Copy }, + { Zenum8, Cx0000, 0x0007, Z(PowerSource), &Z_Copy }, + { Zstring, Cx0000, 0x4000, Z(SWBuildID), &Z_Copy }, + { Zunk, Cx0000, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Cmd 0x0A - Cluster 0x0000, attribute 0xFF01 - proprietary - { 0x0000, 0xFF01, nullptr, &Z_AqaraSensor }, // Occupancy (map8) + { Zmap8, Cx0000, 0xFF01, nullptr, &Z_AqaraSensor }, // Occupancy (map8) // Power Configuration cluster - { 0x0001, 0x0000, Z(MainsVoltage), &Z_Copy }, - { 0x0001, 0x0001, Z(MainsFrequency), &Z_Copy }, - { 0x0001, 0x0020, Z(BatteryVoltage), &Z_FloatDiv10 }, - { 0x0001, 0x0021, Z(BatteryPercentage), &Z_Copy }, + { Zuint16, Cx0001, 0x0000, Z(MainsVoltage), &Z_Copy }, + { Zuint8, Cx0001, 0x0001, Z(MainsFrequency), &Z_Copy }, + { Zuint8, Cx0001, 0x0020, Z(BatteryVoltage), &Z_FloatDiv10 }, + { Zuint8, Cx0001, 0x0021, Z(BatteryPercentage), &Z_Copy }, // Device Temperature Configuration cluster - { 0x0002, 0x0000, Z(CurrentTemperature), &Z_Copy }, - { 0x0002, 0x0001, Z(MinTempExperienced), &Z_Copy }, - { 0x0002, 0x0002, Z(MaxTempExperienced), &Z_Copy }, - { 0x0002, 0x0003, Z(OverTempTotalDwell), &Z_Copy }, + { Zint16, Cx0002, 0x0000, Z(CurrentTemperature), &Z_Copy }, + { Zint16, Cx0002, 0x0001, Z(MinTempExperienced), &Z_Copy }, + { Zint16, Cx0002, 0x0002, Z(MaxTempExperienced), &Z_Copy }, + { Zuint16, Cx0002, 0x0003, Z(OverTempTotalDwell), &Z_Copy }, // Scenes cluster - { 0x0005, 0x0000, Z(SceneCount), &Z_Copy }, - { 0x0005, 0x0001, Z(CurrentScene), &Z_Copy }, - { 0x0005, 0x0002, Z(CurrentGroup), &Z_Copy }, - { 0x0005, 0x0003, Z(SceneValid), &Z_Copy }, - //{ 0x0005, 0x0004, Z(NameSupport), &Z_Copy }, + { Zuint8, Cx0005, 0x0000, Z(SceneCount), &Z_Copy }, + { Zuint8, Cx0005, 0x0001, Z(CurrentScene), &Z_Copy }, + { Zuint16, Cx0005, 0x0002, Z(CurrentGroup), &Z_Copy }, + { Zbool, Cx0005, 0x0003, Z(SceneValid), &Z_Copy }, + //{ Zmap8, Cx0005, 0x0004, Z(NameSupport), &Z_Copy }, // On/off cluster - { 0x0006, 0x0000, Z(Power), &Z_Copy }, - { 0x0006, 0x8000, Z(Power), &Z_Copy }, // See 7280 + { Zbool, Cx0006, 0x0000, Z(Power), &Z_Copy }, + { Zbool, Cx0006, 0x8000, Z(Power), &Z_Copy }, // See 7280 // On/Off Switch Configuration cluster - { 0x0007, 0x0000, Z(SwitchType), &Z_Copy }, + { Zenum8, Cx0007, 0x0000, Z(SwitchType), &Z_Copy }, // Level Control cluster - { 0x0008, 0x0000, Z(Dimmer), &Z_Copy }, - // { 0x0008, 0x0001, Z(RemainingTime", &Z_Copy }, - // { 0x0008, 0x0010, Z(OnOffTransitionTime", &Z_Copy }, - // { 0x0008, 0x0011, Z(OnLevel", &Z_Copy }, - // { 0x0008, 0x0012, Z(OnTransitionTime", &Z_Copy }, - // { 0x0008, 0x0013, Z(OffTransitionTime", &Z_Copy }, - // { 0x0008, 0x0014, Z(DefaultMoveRate", &Z_Copy }, + { Zuint8, Cx0008, 0x0000, Z(Dimmer), &Z_Copy }, + // { Zuint16, Cx0008, 0x0001, Z(RemainingTime", &Z_Copy }, + // { Zuint16, Cx0008, 0x0010, Z(OnOffTransitionTime", &Z_Copy }, + // { Zuint8, Cx0008, 0x0011, Z(OnLevel", &Z_Copy }, + // { Zuint16, Cx0008, 0x0012, Z(OnTransitionTime", &Z_Copy }, + // { Zuint16, Cx0008, 0x0013, Z(OffTransitionTime", &Z_Copy }, + // { Zuint16, Cx0008, 0x0014, Z(DefaultMoveRate", &Z_Copy }, // Alarms cluster - { 0x0009, 0x0000, Z(AlarmCount), &Z_Copy }, + { Zuint16, Cx0009, 0x0000, Z(AlarmCount), &Z_Copy }, + // Time cluster - { 0x000A, 0x0000, Z(Time), &Z_Copy }, - { 0x000A, 0x0001, Z(TimeStatus), &Z_Copy }, - { 0x000A, 0x0002, Z(TimeZone), &Z_Copy }, - { 0x000A, 0x0003, Z(DstStart), &Z_Copy }, - { 0x000A, 0x0004, Z(DstEnd), &Z_Copy }, - { 0x000A, 0x0005, Z(DstShift), &Z_Copy }, - { 0x000A, 0x0006, Z(StandardTime), &Z_Copy }, - { 0x000A, 0x0007, Z(LocalTime), &Z_Copy }, - { 0x000A, 0x0008, Z(LastSetTime), &Z_Copy }, - { 0x000A, 0x0009, Z(ValidUntilTime), &Z_Copy }, + { ZUTC, Cx000A, 0x0000, Z(Time), &Z_Copy }, + { Zmap8, Cx000A, 0x0001, Z(TimeStatus), &Z_Copy }, + { Zint32, Cx000A, 0x0002, Z(TimeZone), &Z_Copy }, + { Zuint32, Cx000A, 0x0003, Z(DstStart), &Z_Copy }, + { Zuint32, Cx000A, 0x0004, Z(DstEnd), &Z_Copy }, + { Zint32, Cx000A, 0x0005, Z(DstShift), &Z_Copy }, + { Zuint32, Cx000A, 0x0006, Z(StandardTime), &Z_Copy }, + { Zuint32, Cx000A, 0x0007, Z(LocalTime), &Z_Copy }, + { ZUTC, Cx000A, 0x0008, Z(LastSetTime), &Z_Copy }, + { ZUTC, Cx000A, 0x0009, Z(ValidUntilTime), &Z_Copy }, + // RSSI Location cluster - { 0x000B, 0x0000, Z(LocationType), &Z_Copy }, - { 0x000B, 0x0000, Z(LocationMethod), &Z_Copy }, - { 0x000B, 0x0000, Z(LocationAge), &Z_Copy }, - { 0x000B, 0x0000, Z(QualityMeasure), &Z_Copy }, - { 0x000B, 0x0000, Z(NumberOfDevices), &Z_Copy }, + { Zdata8, Cx000B, 0x0000, Z(LocationType), &Z_Copy }, + { Zenum8, Cx000B, 0x0001, Z(LocationMethod), &Z_Copy }, + { Zuint16, Cx000B, 0x0002, Z(LocationAge), &Z_Copy }, + { Zuint8, Cx000B, 0x0003, Z(QualityMeasure), &Z_Copy }, + { Zuint8, Cx000B, 0x0004, Z(NumberOfDevices), &Z_Copy }, + // Analog Input cluster - { 0x000C, 0x0004, Z(AnalogInActiveText), &Z_Copy }, - { 0x000C, 0x001C, Z(AnalogInDescription), &Z_Copy }, - { 0x000C, 0x002E, Z(AnalogInInactiveText), &Z_Copy }, - { 0x000C, 0x0041, Z(AnalogInMaxValue), &Z_Copy }, - { 0x000C, 0x0045, Z(AnalogInMinValue), &Z_Copy }, - { 0x000C, 0x0051, Z(AnalogInOutOfService), &Z_Copy }, - { 0x000C, 0x0055, Z(AqaraRotate), &Z_Copy }, - { 0x000C, 0x0057, Z(AnalogInPriorityArray),&Z_Copy }, - { 0x000C, 0x0067, Z(AnalogInReliability), &Z_Copy }, - { 0x000C, 0x0068, Z(AnalogInRelinquishDefault),&Z_Copy }, - { 0x000C, 0x006A, Z(AnalogInResolution), &Z_Copy }, - { 0x000C, 0x006F, Z(AnalogInStatusFlags), &Z_Copy }, - { 0x000C, 0x0075, Z(AnalogInEngineeringUnits),&Z_Copy }, - { 0x000C, 0x0100, Z(AnalogInApplicationType),&Z_Copy }, - { 0x000C, 0xFF05, Z(Aqara_FF05), &Z_Copy }, + // { 0xFF, Cx000C, 0x0004, Z(AnalogInActiveText), &Z_Copy }, + { Zstring, Cx000C, 0x001C, Z(AnalogInDescription), &Z_Copy }, + // { 0xFF, Cx000C, 0x002E, Z(AnalogInInactiveText), &Z_Copy }, + { Zsingle, Cx000C, 0x0041, Z(AnalogInMaxValue), &Z_Copy }, + { Zsingle, Cx000C, 0x0045, Z(AnalogInMinValue), &Z_Copy }, + { Zbool, Cx000C, 0x0051, Z(AnalogInOutOfService), &Z_Copy }, + { Zsingle, Cx000C, 0x0055, Z(AqaraRotate), &Z_Copy }, + // { 0xFF, Cx000C, 0x0057, Z(AnalogInPriorityArray),&Z_Copy }, + { Zenum8, Cx000C, 0x0067, Z(AnalogInReliability), &Z_Copy }, + // { 0xFF, Cx000C, 0x0068, Z(AnalogInRelinquishDefault),&Z_Copy }, + { Zsingle, Cx000C, 0x006A, Z(AnalogInResolution), &Z_Copy }, + { Zmap8, Cx000C, 0x006F, Z(AnalogInStatusFlags), &Z_Copy }, + { Zenum16, Cx000C, 0x0075, Z(AnalogInEngineeringUnits),&Z_Copy }, + { Zuint32, Cx000C, 0x0100, Z(AnalogInApplicationType),&Z_Copy }, + { Zunk, Cx000C, 0xFF05, Z(Aqara_FF05), &Z_Copy }, + // Analog Output cluster - { 0x000D, 0x001C, Z(AnalogOutDescription), &Z_Copy }, - { 0x000D, 0x0041, Z(AnalogOutMaxValue), &Z_Copy }, - { 0x000D, 0x0045, Z(AnalogOutMinValue), &Z_Copy }, - { 0x000D, 0x0051, Z(AnalogOutOutOfService),&Z_Copy }, - { 0x000D, 0x0055, Z(AnalogOutValue), &Z_Copy }, - { 0x000D, 0x0057, Z(AnalogOutPriorityArray),&Z_Copy }, - { 0x000D, 0x0067, Z(AnalogOutReliability), &Z_Copy }, - { 0x000D, 0x0068, Z(AnalogOutRelinquishDefault),&Z_Copy }, - { 0x000D, 0x006A, Z(AnalogOutResolution), &Z_Copy }, - { 0x000D, 0x006F, Z(AnalogOutStatusFlags), &Z_Copy }, - { 0x000D, 0x0075, Z(AnalogOutEngineeringUnits),&Z_Copy }, - { 0x000D, 0x0100, Z(AnalogOutApplicationType),&Z_Copy }, + { Zstring, Cx000D, 0x001C, Z(AnalogOutDescription), &Z_Copy }, + { Zsingle, Cx000D, 0x0041, Z(AnalogOutMaxValue), &Z_Copy }, + { Zsingle, Cx000D, 0x0045, Z(AnalogOutMinValue), &Z_Copy }, + { Zbool, Cx000D, 0x0051, Z(AnalogOutOutOfService),&Z_Copy }, + { Zsingle, Cx000D, 0x0055, Z(AnalogOutValue), &Z_Copy }, + { Zunk, Cx000D, 0x0057, Z(AnalogOutPriorityArray),&Z_Copy }, + { Zenum8, Cx000D, 0x0067, Z(AnalogOutReliability), &Z_Copy }, + { Zsingle, Cx000D, 0x0068, Z(AnalogOutRelinquishDefault),&Z_Copy }, + { Zsingle, Cx000D, 0x006A, Z(AnalogOutResolution), &Z_Copy }, + { Zmap8, Cx000D, 0x006F, Z(AnalogOutStatusFlags), &Z_Copy }, + { Zenum16, Cx000D, 0x0075, Z(AnalogOutEngineeringUnits),&Z_Copy }, + { Zuint32, Cx000D, 0x0100, Z(AnalogOutApplicationType),&Z_Copy }, + // Analog Value cluster - { 0x000E, 0x001C, Z(AnalogDescription), &Z_Copy }, - { 0x000E, 0x0051, Z(AnalogOutOfService), &Z_Copy }, - { 0x000E, 0x0055, Z(AnalogValue), &Z_Copy }, - { 0x000E, 0x0057, Z(AnalogPriorityArray), &Z_Copy }, - { 0x000E, 0x0067, Z(AnalogReliability), &Z_Copy }, - { 0x000E, 0x0068, Z(AnalogRelinquishDefault),&Z_Copy }, - { 0x000E, 0x006F, Z(AnalogStatusFlags), &Z_Copy }, - { 0x000E, 0x0075, Z(AnalogEngineeringUnits),&Z_Copy }, - { 0x000E, 0x0100, Z(AnalogApplicationType),&Z_Copy }, + { Zstring, Cx000E, 0x001C, Z(AnalogDescription), &Z_Copy }, + { Zbool, Cx000E, 0x0051, Z(AnalogOutOfService), &Z_Copy }, + { Zsingle, Cx000E, 0x0055, Z(AnalogValue), &Z_Copy }, + { Zunk, Cx000E, 0x0057, Z(AnalogPriorityArray), &Z_Copy }, + { Zenum8, Cx000E, 0x0067, Z(AnalogReliability), &Z_Copy }, + { Zsingle, Cx000E, 0x0068, Z(AnalogRelinquishDefault),&Z_Copy }, + { Zmap8, Cx000E, 0x006F, Z(AnalogStatusFlags), &Z_Copy }, + { Zenum16, Cx000E, 0x0075, Z(AnalogEngineeringUnits),&Z_Copy }, + { Zuint32, Cx000E, 0x0100, Z(AnalogApplicationType),&Z_Copy }, + // Binary Input cluster - { 0x000F, 0x0004, Z(BinaryInActiveText), &Z_Copy }, - { 0x000F, 0x001C, Z(BinaryInDescription), &Z_Copy }, - { 0x000F, 0x002E, Z(BinaryInInactiveText),&Z_Copy }, - { 0x000F, 0x0051, Z(BinaryInOutOfService),&Z_Copy }, - { 0x000F, 0x0054, Z(BinaryInPolarity), &Z_Copy }, - { 0x000F, 0x0055, Z(BinaryInValue), &Z_Copy }, - { 0x000F, 0x0057, Z(BinaryInPriorityArray),&Z_Copy }, - { 0x000F, 0x0067, Z(BinaryInReliability), &Z_Copy }, - { 0x000F, 0x006F, Z(BinaryInStatusFlags), &Z_Copy }, - { 0x000F, 0x0100, Z(BinaryInApplicationType),&Z_Copy }, + { Zstring, Cx000F, 0x0004, Z(BinaryInActiveText), &Z_Copy }, + { Zstring, Cx000F, 0x001C, Z(BinaryInDescription), &Z_Copy }, + { Zstring, Cx000F, 0x002E, Z(BinaryInInactiveText),&Z_Copy }, + { Zbool, Cx000F, 0x0051, Z(BinaryInOutOfService),&Z_Copy }, + { Zenum8, Cx000F, 0x0054, Z(BinaryInPolarity), &Z_Copy }, + { Zstring, Cx000F, 0x0055, Z(BinaryInValue), &Z_Copy }, + // { 0xFF, Cx000F, 0x0057, Z(BinaryInPriorityArray),&Z_Copy }, + { Zenum8, Cx000F, 0x0067, Z(BinaryInReliability), &Z_Copy }, + { Zmap8, Cx000F, 0x006F, Z(BinaryInStatusFlags), &Z_Copy }, + { Zuint32, Cx000F, 0x0100, Z(BinaryInApplicationType),&Z_Copy }, + // Binary Output cluster - { 0x0010, 0x0004, Z(BinaryOutActiveText), &Z_Copy }, - { 0x0010, 0x001C, Z(BinaryOutDescription), &Z_Copy }, - { 0x0010, 0x002E, Z(BinaryOutInactiveText),&Z_Copy }, - { 0x0010, 0x0042, Z(BinaryOutMinimumOffTime),&Z_Copy }, - { 0x0010, 0x0043, Z(BinaryOutMinimumOnTime),&Z_Copy }, - { 0x0010, 0x0051, Z(BinaryOutOutOfService),&Z_Copy }, - { 0x0010, 0x0054, Z(BinaryOutPolarity), &Z_Copy }, - { 0x0010, 0x0055, Z(BinaryOutValue), &Z_Copy }, - { 0x0010, 0x0057, Z(BinaryOutPriorityArray),&Z_Copy }, - { 0x0010, 0x0067, Z(BinaryOutReliability), &Z_Copy }, - { 0x0010, 0x0068, Z(BinaryOutRelinquishDefault),&Z_Copy }, - { 0x0010, 0x006F, Z(BinaryOutStatusFlags), &Z_Copy }, - { 0x0010, 0x0100, Z(BinaryOutApplicationType),&Z_Copy }, + { Zstring, Cx0010, 0x0004, Z(BinaryOutActiveText), &Z_Copy }, + { Zstring, Cx0010, 0x001C, Z(BinaryOutDescription), &Z_Copy }, + { Zstring, Cx0010, 0x002E, Z(BinaryOutInactiveText),&Z_Copy }, + { Zuint32, Cx0010, 0x0042, Z(BinaryOutMinimumOffTime),&Z_Copy }, + { Zuint32, Cx0010, 0x0043, Z(BinaryOutMinimumOnTime),&Z_Copy }, + { Zbool, Cx0010, 0x0051, Z(BinaryOutOutOfService),&Z_Copy }, + { Zenum8, Cx0010, 0x0054, Z(BinaryOutPolarity), &Z_Copy }, + { Zbool, Cx0010, 0x0055, Z(BinaryOutValue), &Z_Copy }, + { Zunk, Cx0010, 0x0057, Z(BinaryOutPriorityArray),&Z_Copy }, + { Zenum8, Cx0010, 0x0067, Z(BinaryOutReliability), &Z_Copy }, + { Zbool, Cx0010, 0x0068, Z(BinaryOutRelinquishDefault),&Z_Copy }, + { Zmap8, Cx0010, 0x006F, Z(BinaryOutStatusFlags), &Z_Copy }, + { Zuint32, Cx0010, 0x0100, Z(BinaryOutApplicationType),&Z_Copy }, + // Binary Value cluster - { 0x0011, 0x0004, Z(BinaryActiveText), &Z_Copy }, - { 0x0011, 0x001C, Z(BinaryDescription), &Z_Copy }, - { 0x0011, 0x002E, Z(BinaryInactiveText), &Z_Copy }, - { 0x0011, 0x0042, Z(BinaryMinimumOffTime), &Z_Copy }, - { 0x0011, 0x0043, Z(BinaryMinimumOnTime), &Z_Copy }, - { 0x0011, 0x0051, Z(BinaryOutOfService), &Z_Copy }, - { 0x0011, 0x0055, Z(BinaryValue), &Z_Copy }, - { 0x0011, 0x0057, Z(BinaryPriorityArray), &Z_Copy }, - { 0x0011, 0x0067, Z(BinaryReliability), &Z_Copy }, - { 0x0011, 0x0068, Z(BinaryRelinquishDefault),&Z_Copy }, - { 0x0011, 0x006F, Z(BinaryStatusFlags), &Z_Copy }, - { 0x0011, 0x0100, Z(BinaryApplicationType),&Z_Copy }, + { Zstring, Cx0011, 0x0004, Z(BinaryActiveText), &Z_Copy }, + { Zstring, Cx0011, 0x001C, Z(BinaryDescription), &Z_Copy }, + { Zstring, Cx0011, 0x002E, Z(BinaryInactiveText), &Z_Copy }, + { Zuint32, Cx0011, 0x0042, Z(BinaryMinimumOffTime), &Z_Copy }, + { Zuint32, Cx0011, 0x0043, Z(BinaryMinimumOnTime), &Z_Copy }, + { Zbool, Cx0011, 0x0051, Z(BinaryOutOfService), &Z_Copy }, + { Zbool, Cx0011, 0x0055, Z(BinaryValue), &Z_Copy }, + { Zunk, Cx0011, 0x0057, Z(BinaryPriorityArray), &Z_Copy }, + { Zenum8, Cx0011, 0x0067, Z(BinaryReliability), &Z_Copy }, + { Zbool, Cx0011, 0x0068, Z(BinaryRelinquishDefault),&Z_Copy }, + { Zmap8, Cx0011, 0x006F, Z(BinaryStatusFlags), &Z_Copy }, + { Zuint32, Cx0011, 0x0100, Z(BinaryApplicationType),&Z_Copy }, + // Multistate Input cluster - { 0x0012, 0x000E, Z(MultiInStateText), &Z_Copy }, - { 0x0012, 0x001C, Z(MultiInDescription), &Z_Copy }, - { 0x0012, 0x004A, Z(MultiInNumberOfStates),&Z_Copy }, - { 0x0012, 0x0051, Z(MultiInOutOfService), &Z_Copy }, - { 0x0012, 0x0055, Z(MultiInValue), &Z_AqaraCube }, - { 0x0012, 0x0067, Z(MultiInReliability), &Z_Copy }, - { 0x0012, 0x006F, Z(MultiInStatusFlags), &Z_Copy }, - { 0x0012, 0x0100, Z(MultiInApplicationType),&Z_Copy }, + { Zunk, Cx0012, 0x000E, Z(MultiInStateText), &Z_Copy }, + { Zstring, Cx0012, 0x001C, Z(MultiInDescription), &Z_Copy }, + { Zuint16, Cx0012, 0x004A, Z(MultiInNumberOfStates),&Z_Copy }, + { Zbool, Cx0012, 0x0051, Z(MultiInOutOfService), &Z_Copy }, + { Zuint16, Cx0012, 0x0055, Z(MultiInValue), &Z_AqaraCube }, + { Zenum8, Cx0012, 0x0067, Z(MultiInReliability), &Z_Copy }, + { Zmap8, Cx0012, 0x006F, Z(MultiInStatusFlags), &Z_Copy }, + { Zuint32, Cx0012, 0x0100, Z(MultiInApplicationType),&Z_Copy }, + // Multistate output - { 0x0013, 0x000E, Z(MultiOutStateText), &Z_Copy }, - { 0x0013, 0x001C, Z(MultiOutDescription), &Z_Copy }, - { 0x0013, 0x004A, Z(MultiOutNumberOfStates),&Z_Copy }, - { 0x0013, 0x0051, Z(MultiOutOutOfService), &Z_Copy }, - { 0x0013, 0x0055, Z(MultiOutValue), &Z_Copy }, - { 0x0013, 0x0057, Z(MultiOutPriorityArray),&Z_Copy }, - { 0x0013, 0x0067, Z(MultiOutReliability), &Z_Copy }, - { 0x0013, 0x0068, Z(MultiOutRelinquishDefault),&Z_Copy }, - { 0x0013, 0x006F, Z(MultiOutStatusFlags), &Z_Copy }, - { 0x0013, 0x0100, Z(MultiOutApplicationType),&Z_Copy }, + { Zunk, Cx0013, 0x000E, Z(MultiOutStateText), &Z_Copy }, + { Zstring, Cx0013, 0x001C, Z(MultiOutDescription), &Z_Copy }, + { Zuint16, Cx0013, 0x004A, Z(MultiOutNumberOfStates),&Z_Copy }, + { Zbool, Cx0013, 0x0051, Z(MultiOutOutOfService), &Z_Copy }, + { Zuint16, Cx0013, 0x0055, Z(MultiOutValue), &Z_Copy }, + // { Zunk, Cx0013, 0x0057, Z(MultiOutPriorityArray),&Z_Copy }, + { Zenum8, Cx0013, 0x0067, Z(MultiOutReliability), &Z_Copy }, + { Zuint16, Cx0013, 0x0068, Z(MultiOutRelinquishDefault),&Z_Copy }, + { Zmap8, Cx0013, 0x006F, Z(MultiOutStatusFlags), &Z_Copy }, + { Zuint32, Cx0013, 0x0100, Z(MultiOutApplicationType),&Z_Copy }, + // Multistate Value cluster - { 0x0014, 0x000E, Z(MultiStateText), &Z_Copy }, - { 0x0014, 0x001C, Z(MultiDescription), &Z_Copy }, - { 0x0014, 0x004A, Z(MultiNumberOfStates), &Z_Copy }, - { 0x0014, 0x0051, Z(MultiOutOfService), &Z_Copy }, - { 0x0014, 0x0055, Z(MultiValue), &Z_Copy }, - { 0x0014, 0x0067, Z(MultiReliability), &Z_Copy }, - { 0x0014, 0x0068, Z(MultiRelinquishDefault),&Z_Copy }, - { 0x0014, 0x006F, Z(MultiStatusFlags), &Z_Copy }, - { 0x0014, 0x0100, Z(MultiApplicationType), &Z_Copy }, + { Zunk, Cx0014, 0x000E, Z(MultiStateText), &Z_Copy }, + { Zstring, Cx0014, 0x001C, Z(MultiDescription), &Z_Copy }, + { Zuint16, Cx0014, 0x004A, Z(MultiNumberOfStates), &Z_Copy }, + { Zbool, Cx0014, 0x0051, Z(MultiOutOfService), &Z_Copy }, + { Zuint16, Cx0014, 0x0055, Z(MultiValue), &Z_Copy }, + { Zenum8, Cx0014, 0x0067, Z(MultiReliability), &Z_Copy }, + { Zuint16, Cx0014, 0x0068, Z(MultiRelinquishDefault),&Z_Copy }, + { Zmap8, Cx0014, 0x006F, Z(MultiStatusFlags), &Z_Copy }, + { Zuint32, Cx0014, 0x0100, Z(MultiApplicationType), &Z_Copy }, + // Power Profile cluster - { 0x001A, 0x0000, Z(TotalProfileNum), &Z_Copy }, - { 0x001A, 0x0001, Z(MultipleScheduling), &Z_Copy }, - { 0x001A, 0x0002, Z(EnergyFormatting), &Z_Copy }, - { 0x001A, 0x0003, Z(EnergyRemote), &Z_Copy }, - { 0x001A, 0x0004, Z(ScheduleMode), &Z_Copy }, + { Zuint8, Cx001A, 0x0000, Z(TotalProfileNum), &Z_Copy }, + { Zbool, Cx001A, 0x0001, Z(MultipleScheduling), &Z_Copy }, + { Zmap8, Cx001A, 0x0002, Z(EnergyFormatting), &Z_Copy }, + { Zbool, Cx001A, 0x0003, Z(EnergyRemote), &Z_Copy }, + { Zmap8, Cx001A, 0x0004, Z(ScheduleMode), &Z_Copy }, + // Poll Control cluster - { 0x0020, 0x0000, Z(CheckinInterval), &Z_Copy }, - { 0x0020, 0x0001, Z(LongPollInterval), &Z_Copy }, - { 0x0020, 0x0002, Z(ShortPollInterval), &Z_Copy }, - { 0x0020, 0x0003, Z(FastPollTimeout), &Z_Copy }, - { 0x0020, 0x0004, Z(CheckinIntervalMin), &Z_Copy }, - { 0x0020, 0x0005, Z(LongPollIntervalMin), &Z_Copy }, - { 0x0020, 0x0006, Z(FastPollTimeoutMax), &Z_Copy }, + { Zuint32, Cx0020, 0x0000, Z(CheckinInterval), &Z_Copy }, + { Zuint32, Cx0020, 0x0001, Z(LongPollInterval), &Z_Copy }, + { Zuint16, Cx0020, 0x0002, Z(ShortPollInterval), &Z_Copy }, + { Zuint16, Cx0020, 0x0003, Z(FastPollTimeout), &Z_Copy }, + { Zuint32, Cx0020, 0x0004, Z(CheckinIntervalMin), &Z_Copy }, + { Zuint32, Cx0020, 0x0005, Z(LongPollIntervalMin), &Z_Copy }, + { Zuint16, Cx0020, 0x0006, Z(FastPollTimeoutMax), &Z_Copy }, + // Shade Configuration cluster - { 0x0100, 0x0000, Z(PhysicalClosedLimit), &Z_Copy }, - { 0x0100, 0x0001, Z(MotorStepSize), &Z_Copy }, - { 0x0100, 0x0002, Z(Status), &Z_Copy }, - { 0x0100, 0x0010, Z(ClosedLimit), &Z_Copy }, - { 0x0100, 0x0011, Z(Mode), &Z_Copy }, + { Zuint16, Cx0100, 0x0000, Z(PhysicalClosedLimit), &Z_Copy }, + { Zuint8, Cx0100, 0x0001, Z(MotorStepSize), &Z_Copy }, + { Zmap8, Cx0100, 0x0002, Z(Status), &Z_Copy }, + { Zuint16, Cx0100, 0x0010, Z(ClosedLimit), &Z_Copy }, + { Zenum8, Cx0100, 0x0011, Z(Mode), &Z_Copy }, + // Door Lock cluster - { 0x0101, 0x0000, Z(LockState), &Z_Copy }, - { 0x0101, 0x0001, Z(LockType), &Z_Copy }, - { 0x0101, 0x0002, Z(ActuatorEnabled), &Z_Copy }, - { 0x0101, 0x0003, Z(DoorState), &Z_Copy }, - { 0x0101, 0x0004, Z(DoorOpenEvents), &Z_Copy }, - { 0x0101, 0x0005, Z(DoorClosedEvents), &Z_Copy }, - { 0x0101, 0x0006, Z(OpenPeriod), &Z_Copy }, + { Zenum8, Cx0101, 0x0000, Z(LockState), &Z_Copy }, + { Zenum8, Cx0101, 0x0001, Z(LockType), &Z_Copy }, + { Zbool, Cx0101, 0x0002, Z(ActuatorEnabled), &Z_Copy }, + { Zenum8, Cx0101, 0x0003, Z(DoorState), &Z_Copy }, + { Zuint32, Cx0101, 0x0004, Z(DoorOpenEvents), &Z_Copy }, + { Zuint32, Cx0101, 0x0005, Z(DoorClosedEvents), &Z_Copy }, + { Zuint16, Cx0101, 0x0006, Z(OpenPeriod), &Z_Copy }, + // Aqara Lumi Vibration Sensor - { 0x0101, 0x0055, Z(AqaraVibrationMode), &Z_AqaraVibration }, - { 0x0101, 0x0503, Z(AqaraVibrationsOrAngle), &Z_Copy }, - { 0x0101, 0x0505, Z(AqaraVibration505), &Z_Copy }, - { 0x0101, 0x0508, Z(AqaraAccelerometer), &Z_AqaraVibration }, + { Zunk, Cx0101, 0x0055, Z(AqaraVibrationMode), &Z_AqaraVibration }, + { Zunk, Cx0101, 0x0503, Z(AqaraVibrationsOrAngle), &Z_Copy }, + { Zunk, Cx0101, 0x0505, Z(AqaraVibration505), &Z_Copy }, + { Zunk, Cx0101, 0x0508, Z(AqaraAccelerometer), &Z_AqaraVibration }, + // Window Covering cluster - { 0x0102, 0x0000, Z(WindowCoveringType), &Z_Copy }, - { 0x0102, 0x0001, Z(PhysicalClosedLimitLift),&Z_Copy }, - { 0x0102, 0x0002, Z(PhysicalClosedLimitTilt),&Z_Copy }, - { 0x0102, 0x0003, Z(CurrentPositionLift), &Z_Copy }, - { 0x0102, 0x0004, Z(CurrentPositionTilt), &Z_Copy }, - { 0x0102, 0x0005, Z(NumberofActuationsLift),&Z_Copy }, - { 0x0102, 0x0006, Z(NumberofActuationsTilt),&Z_Copy }, - { 0x0102, 0x0007, Z(ConfigStatus), &Z_Copy }, - { 0x0102, 0x0008, Z(CurrentPositionLiftPercentage),&Z_Copy }, - { 0x0102, 0x0009, Z(CurrentPositionTiltPercentage),&Z_Copy }, - { 0x0102, 0x0010, Z(InstalledOpenLimitLift),&Z_Copy }, - { 0x0102, 0x0011, Z(InstalledClosedLimitLift),&Z_Copy }, - { 0x0102, 0x0012, Z(InstalledOpenLimitTilt),&Z_Copy }, - { 0x0102, 0x0013, Z(InstalledClosedLimitTilt),&Z_Copy }, - { 0x0102, 0x0014, Z(VelocityLift), &Z_Copy }, - { 0x0102, 0x0015, Z(AccelerationTimeLift),&Z_Copy }, - { 0x0102, 0x0016, Z(DecelerationTimeLift), &Z_Copy }, - { 0x0102, 0x0017, Z(Mode), &Z_Copy }, - { 0x0102, 0x0018, Z(IntermediateSetpointsLift),&Z_Copy }, - { 0x0102, 0x0019, Z(IntermediateSetpointsTilt),&Z_Copy }, + { Zenum8, Cx0102, 0x0000, Z(WindowCoveringType), &Z_Copy }, + { Zuint16, Cx0102, 0x0001, Z(PhysicalClosedLimitLift),&Z_Copy }, + { Zuint16, Cx0102, 0x0002, Z(PhysicalClosedLimitTilt),&Z_Copy }, + { Zuint16, Cx0102, 0x0003, Z(CurrentPositionLift), &Z_Copy }, + { Zuint16, Cx0102, 0x0004, Z(CurrentPositionTilt), &Z_Copy }, + { Zuint16, Cx0102, 0x0005, Z(NumberofActuationsLift),&Z_Copy }, + { Zuint16, Cx0102, 0x0006, Z(NumberofActuationsTilt),&Z_Copy }, + { Zmap8, Cx0102, 0x0007, Z(ConfigStatus), &Z_Copy }, + { Zuint8, Cx0102, 0x0008, Z(CurrentPositionLiftPercentage),&Z_Copy }, + { Zuint8, Cx0102, 0x0009, Z(CurrentPositionTiltPercentage),&Z_Copy }, + { Zuint16, Cx0102, 0x0010, Z(InstalledOpenLimitLift),&Z_Copy }, + { Zuint16, Cx0102, 0x0011, Z(InstalledClosedLimitLift),&Z_Copy }, + { Zuint16, Cx0102, 0x0012, Z(InstalledOpenLimitTilt),&Z_Copy }, + { Zuint16, Cx0102, 0x0013, Z(InstalledClosedLimitTilt),&Z_Copy }, + { Zuint16, Cx0102, 0x0014, Z(VelocityLift), &Z_Copy }, + { Zuint16, Cx0102, 0x0015, Z(AccelerationTimeLift),&Z_Copy }, + { Zuint16, Cx0102, 0x0016, Z(DecelerationTimeLift), &Z_Copy }, + { Zmap8, Cx0102, 0x0017, Z(Mode), &Z_Copy }, + { Zoctstr, Cx0102, 0x0018, Z(IntermediateSetpointsLift),&Z_Copy }, + { Zoctstr, Cx0102, 0x0019, Z(IntermediateSetpointsTilt),&Z_Copy }, // Color Control cluster - { 0x0300, 0x0000, Z(Hue), &Z_Copy }, - { 0x0300, 0x0001, Z(Sat), &Z_Copy }, - { 0x0300, 0x0002, Z(RemainingTime), &Z_Copy }, - { 0x0300, 0x0003, Z(X), &Z_Copy }, - { 0x0300, 0x0004, Z(Y), &Z_Copy }, - { 0x0300, 0x0005, Z(DriftCompensation), &Z_Copy }, - { 0x0300, 0x0006, Z(CompensationText), &Z_Copy }, - { 0x0300, 0x0007, Z(CT), &Z_Copy }, - { 0x0300, 0x0008, Z(ColorMode), &Z_Copy }, - { 0x0300, 0x0010, Z(NumberOfPrimaries), &Z_Copy }, - { 0x0300, 0x0011, Z(Primary1X), &Z_Copy }, - { 0x0300, 0x0012, Z(Primary1Y), &Z_Copy }, - { 0x0300, 0x0013, Z(Primary1Intensity), &Z_Copy }, - { 0x0300, 0x0015, Z(Primary2X), &Z_Copy }, - { 0x0300, 0x0016, Z(Primary2Y), &Z_Copy }, - { 0x0300, 0x0017, Z(Primary2Intensity), &Z_Copy }, - { 0x0300, 0x0019, Z(Primary3X), &Z_Copy }, - { 0x0300, 0x001A, Z(Primary3Y), &Z_Copy }, - { 0x0300, 0x001B, Z(Primary3Intensity), &Z_Copy }, - { 0x0300, 0x0030, Z(WhitePointX), &Z_Copy }, - { 0x0300, 0x0031, Z(WhitePointY), &Z_Copy }, - { 0x0300, 0x0032, Z(ColorPointRX), &Z_Copy }, - { 0x0300, 0x0033, Z(ColorPointRY), &Z_Copy }, - { 0x0300, 0x0034, Z(ColorPointRIntensity), &Z_Copy }, - { 0x0300, 0x0036, Z(ColorPointGX), &Z_Copy }, - { 0x0300, 0x0037, Z(ColorPointGY), &Z_Copy }, - { 0x0300, 0x0038, Z(ColorPointGIntensity), &Z_Copy }, - { 0x0300, 0x003A, Z(ColorPointBX), &Z_Copy }, - { 0x0300, 0x003B, Z(ColorPointBY), &Z_Copy }, - { 0x0300, 0x003C, Z(ColorPointBIntensity), &Z_Copy }, + { Zuint8, Cx0300, 0x0000, Z(Hue), &Z_Copy }, + { Zuint8, Cx0300, 0x0001, Z(Sat), &Z_Copy }, + { Zuint16, Cx0300, 0x0002, Z(RemainingTime), &Z_Copy }, + { Zuint16, Cx0300, 0x0003, Z(X), &Z_Copy }, + { Zuint16, Cx0300, 0x0004, Z(Y), &Z_Copy }, + { Zenum8, Cx0300, 0x0005, Z(DriftCompensation), &Z_Copy }, + { Zstring, Cx0300, 0x0006, Z(CompensationText), &Z_Copy }, + { Zuint16, Cx0300, 0x0007, Z(CT), &Z_Copy }, + { Zenum8, Cx0300, 0x0008, Z(ColorMode), &Z_Copy }, + { Zuint8, Cx0300, 0x0010, Z(NumberOfPrimaries), &Z_Copy }, + { Zuint16, Cx0300, 0x0011, Z(Primary1X), &Z_Copy }, + { Zuint16, Cx0300, 0x0012, Z(Primary1Y), &Z_Copy }, + { Zuint8, Cx0300, 0x0013, Z(Primary1Intensity), &Z_Copy }, + { Zuint16, Cx0300, 0x0015, Z(Primary2X), &Z_Copy }, + { Zuint16, Cx0300, 0x0016, Z(Primary2Y), &Z_Copy }, + { Zuint8, Cx0300, 0x0017, Z(Primary2Intensity), &Z_Copy }, + { Zuint16, Cx0300, 0x0019, Z(Primary3X), &Z_Copy }, + { Zuint16, Cx0300, 0x001A, Z(Primary3Y), &Z_Copy }, + { Zuint8, Cx0300, 0x001B, Z(Primary3Intensity), &Z_Copy }, + { Zuint16, Cx0300, 0x0030, Z(WhitePointX), &Z_Copy }, + { Zuint16, Cx0300, 0x0031, Z(WhitePointY), &Z_Copy }, + { Zuint16, Cx0300, 0x0032, Z(ColorPointRX), &Z_Copy }, + { Zuint16, Cx0300, 0x0033, Z(ColorPointRY), &Z_Copy }, + { Zuint8, Cx0300, 0x0034, Z(ColorPointRIntensity), &Z_Copy }, + { Zuint16, Cx0300, 0x0036, Z(ColorPointGX), &Z_Copy }, + { Zuint16, Cx0300, 0x0037, Z(ColorPointGY), &Z_Copy }, + { Zuint8, Cx0300, 0x0038, Z(ColorPointGIntensity), &Z_Copy }, + { Zuint16, Cx0300, 0x003A, Z(ColorPointBX), &Z_Copy }, + { Zuint16, Cx0300, 0x003B, Z(ColorPointBY), &Z_Copy }, + { Zuint8, Cx0300, 0x003C, Z(ColorPointBIntensity), &Z_Copy }, // Illuminance Measurement cluster - { 0x0400, 0x0000, Z(Illuminance), &Z_Copy }, // Illuminance (in Lux) - { 0x0400, 0x0001, Z(IlluminanceMinMeasuredValue), &Z_Copy }, // - { 0x0400, 0x0002, Z(IlluminanceMaxMeasuredValue), &Z_Copy }, // - { 0x0400, 0x0003, Z(IlluminanceTolerance), &Z_Copy }, // - { 0x0400, 0x0004, Z(IlluminanceLightSensorType), &Z_Copy }, // - { 0x0400, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values + { Zuint16, Cx0400, 0x0000, Z(Illuminance), &Z_Copy }, // Illuminance (in Lux) + { Zuint16, Cx0400, 0x0001, Z(IlluminanceMinMeasuredValue), &Z_Copy }, // + { Zuint16, Cx0400, 0x0002, Z(IlluminanceMaxMeasuredValue), &Z_Copy }, // + { Zuint16, Cx0400, 0x0003, Z(IlluminanceTolerance), &Z_Copy }, // + { Zenum8, Cx0400, 0x0004, Z(IlluminanceLightSensorType), &Z_Copy }, // + { Zunk, Cx0400, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Illuminance Level Sensing cluster - { 0x0401, 0x0000, Z(IlluminanceLevelStatus), &Z_Copy }, // Illuminance (in Lux) - { 0x0401, 0x0001, Z(IlluminanceLightSensorType), &Z_Copy }, // LightSensorType - { 0x0401, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values + { Zenum8, Cx0401, 0x0000, Z(IlluminanceLevelStatus), &Z_Copy }, // Illuminance (in Lux) + { Zenum8, Cx0401, 0x0001, Z(IlluminanceLightSensorType), &Z_Copy }, // LightSensorType + { Zuint16, Cx0401, 0x0010, Z(IlluminanceTargetLevel), &Z_Copy }, // + { Zunk, Cx0401, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Temperature Measurement cluster - { 0x0402, 0x0000, Z(Temperature), &Z_FloatDiv100 }, // Temperature - { 0x0402, 0x0001, Z(TemperatureMinMeasuredValue), &Z_FloatDiv100 }, // - { 0x0402, 0x0002, Z(TemperatureMaxMeasuredValue), &Z_FloatDiv100 }, // - { 0x0402, 0x0003, Z(TemperatureTolerance), &Z_FloatDiv100 }, // - { 0x0402, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values + { Zint16, Cx0402, 0x0000, Z(Temperature), &Z_FloatDiv100 }, // Temperature + { Zint16, Cx0402, 0x0001, Z(TemperatureMinMeasuredValue), &Z_FloatDiv100 }, // + { Zint16, Cx0402, 0x0002, Z(TemperatureMaxMeasuredValue), &Z_FloatDiv100 }, // + { Zuint16, Cx0402, 0x0003, Z(TemperatureTolerance), &Z_FloatDiv100 }, // + { Zunk, Cx0402, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Pressure Measurement cluster - { 0x0403, 0x0000, Z(PressureUnit), &Z_AddPressureUnit }, // Pressure Unit - { 0x0403, 0x0000, Z(Pressure), &Z_Copy }, // Pressure - { 0x0403, 0x0001, Z(PressureMinMeasuredValue), &Z_Copy }, // - { 0x0403, 0x0002, Z(PressureMaxMeasuredValue), &Z_Copy }, // - { 0x0403, 0x0003, Z(PressureTolerance), &Z_Copy }, // - { 0x0403, 0x0010, Z(PressureScaledValue), &Z_Copy }, // - { 0x0403, 0x0011, Z(PressureMinScaledValue), &Z_Copy }, // - { 0x0403, 0x0012, Z(PressureMaxScaledValue), &Z_Copy }, // - { 0x0403, 0x0013, Z(PressureScaledTolerance), &Z_Copy }, // - { 0x0403, 0x0014, Z(PressureScale), &Z_Copy }, // - { 0x0403, 0xFFFF, nullptr, &Z_Remove }, // Remove all other Pressure values + { Zunk, Cx0403, 0x0000, Z(PressureUnit), &Z_AddPressureUnit }, // Pressure Unit + { Zint16, Cx0403, 0x0000, Z(Pressure), &Z_Copy }, // Pressure + { Zint16, Cx0403, 0x0001, Z(PressureMinMeasuredValue), &Z_Copy }, // + { Zint16, Cx0403, 0x0002, Z(PressureMaxMeasuredValue), &Z_Copy }, // + { Zuint16, Cx0403, 0x0003, Z(PressureTolerance), &Z_Copy }, // + { Zint16, Cx0403, 0x0010, Z(PressureScaledValue), &Z_Copy }, // + { Zint16, Cx0403, 0x0011, Z(PressureMinScaledValue), &Z_Copy }, // + { Zint16, Cx0403, 0x0012, Z(PressureMaxScaledValue), &Z_Copy }, // + { Zuint16, Cx0403, 0x0013, Z(PressureScaledTolerance), &Z_Copy }, // + { Zint8, Cx0403, 0x0014, Z(PressureScale), &Z_Copy }, // + { Zunk, Cx0403, 0xFFFF, nullptr, &Z_Remove }, // Remove all other Pressure values // Flow Measurement cluster - { 0x0404, 0x0000, Z(FlowRate), &Z_FloatDiv10 }, // Flow (in m3/h) - { 0x0404, 0x0001, Z(FlowMinMeasuredValue), &Z_Copy }, // - { 0x0404, 0x0002, Z(FlowMaxMeasuredValue), &Z_Copy }, // - { 0x0404, 0x0003, Z(FlowTolerance), &Z_Copy }, // - { 0x0404, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values + { Zuint16, Cx0404, 0x0000, Z(FlowRate), &Z_FloatDiv10 }, // Flow (in m3/h) + { Zuint16, Cx0404, 0x0001, Z(FlowMinMeasuredValue), &Z_Copy }, // + { Zuint16, Cx0404, 0x0002, Z(FlowMaxMeasuredValue), &Z_Copy }, // + { Zuint16, Cx0404, 0x0003, Z(FlowTolerance), &Z_Copy }, // + { Zunk, Cx0404, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Relative Humidity Measurement cluster - { 0x0405, 0x0000, Z(Humidity), &Z_FloatDiv100 }, // Humidity - { 0x0405, 0x0001, Z(HumidityMinMeasuredValue), &Z_Copy }, // - { 0x0405, 0x0002, Z(HumidityMaxMeasuredValue), &Z_Copy }, // - { 0x0405, 0x0003, "HumidityTolerance", &Z_Copy }, // - { 0x0405, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values + { Zuint16, Cx0405, 0x0000, Z(Humidity), &Z_FloatDiv100 }, // Humidity + { Zuint16, Cx0405, 0x0001, Z(HumidityMinMeasuredValue), &Z_Copy }, // + { Zuint16, Cx0405, 0x0002, Z(HumidityMaxMeasuredValue), &Z_Copy }, // + { Zuint16, Cx0405, 0x0003, Z(HumidityTolerance), &Z_Copy }, // + { Zunk, Cx0405, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Occupancy Sensing cluster - { 0x0406, 0x0000, Z(Occupancy), &Z_Copy }, // Occupancy (map8) - { 0x0406, 0x0001, Z(OccupancySensorType), &Z_Copy }, // OccupancySensorType - { 0x0406, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values + { Zmap8, Cx0406, 0x0000, Z(Occupancy), &Z_Copy }, // Occupancy (map8) + { Zenum8, Cx0406, 0x0001, Z(OccupancySensorType), &Z_Copy }, // OccupancySensorType + { Zunk, Cx0406, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Meter Identification cluster - { 0x0B01, 0x0000, Z(CompanyName), &Z_Copy }, - { 0x0B01, 0x0001, Z(MeterTypeID), &Z_Copy }, - { 0x0B01, 0x0004, Z(DataQualityID), &Z_Copy }, - { 0x0B01, 0x0005, Z(CustomerName), &Z_Copy }, - { 0x0B01, 0x0006, Z(Model), &Z_Copy }, - { 0x0B01, 0x0007, Z(PartNumber), &Z_Copy }, - { 0x0B01, 0x000A, Z(SoftwareRevision), &Z_Copy }, - { 0x0B01, 0x000C, Z(POD), &Z_Copy }, - { 0x0B01, 0x000D, Z(AvailablePower), &Z_Copy }, - { 0x0B01, 0x000E, Z(PowerThreshold), &Z_Copy }, + { Zstring, Cx0B01, 0x0000, Z(CompanyName), &Z_Copy }, + { Zuint16, Cx0B01, 0x0001, Z(MeterTypeID), &Z_Copy }, + { Zuint16, Cx0B01, 0x0004, Z(DataQualityID), &Z_Copy }, + { Zstring, Cx0B01, 0x0005, Z(CustomerName), &Z_Copy }, + { Zoctstr, Cx0B01, 0x0006, Z(Model), &Z_Copy }, + { Zoctstr, Cx0B01, 0x0007, Z(PartNumber), &Z_Copy }, + { Zoctstr, Cx0B01, 0x0008, Z(ProductRevision), &Z_Copy }, + { Zoctstr, Cx0B01, 0x000A, Z(SoftwareRevision), &Z_Copy }, + { Zstring, Cx0B01, 0x000B, Z(UtilityName), &Z_Copy }, + { Zstring, Cx0B01, 0x000C, Z(POD), &Z_Copy }, + { Zint24, Cx0B01, 0x000D, Z(AvailablePower), &Z_Copy }, + { Zint24, Cx0B01, 0x000E, Z(PowerThreshold), &Z_Copy }, // Diagnostics cluster - { 0x0B05, 0x0000, Z(NumberOfResets), &Z_Copy }, - { 0x0B05, 0x0001, Z(PersistentMemoryWrites),&Z_Copy }, - { 0x0B05, 0x011C, Z(LastMessageLQI), &Z_Copy }, - { 0x0B05, 0x011D, Z(LastMessageRSSI), &Z_Copy }, + { Zuint16, Cx0B05, 0x0000, Z(NumberOfResets), &Z_Copy }, + { Zuint16, Cx0B05, 0x0001, Z(PersistentMemoryWrites),&Z_Copy }, + { Zuint8, Cx0B05, 0x011C, Z(LastMessageLQI), &Z_Copy }, + { Zuint8, Cx0B05, 0x011D, Z(LastMessageRSSI), &Z_Copy }, }; @@ -1245,7 +1325,7 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) { // Iterate on filter for (uint32_t i = 0; i < sizeof(Z_PostProcess) / sizeof(Z_PostProcess[0]); i++) { const Z_AttributeConverter *converter = &Z_PostProcess[i]; - uint16_t conv_cluster = pgm_read_word(&converter->cluster); + uint16_t conv_cluster = CxToCluster(pgm_read_byte(&converter->cluster_short)); uint16_t conv_attribute = pgm_read_word(&converter->attribute); if ((conv_cluster == cluster) && From 85d04dbc53f9e52f3e87b4b0073c55693a64749a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 16 Apr 2020 19:44:13 +0200 Subject: [PATCH 28/70] Fix minor errors --- 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 11c0d7ee0..8fdb61495 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -54,7 +54,7 @@ build_flags = ${core_active.build_flags} upload_port = COM5 extra_scripts = ${scripts_defaults.extra_scripts} - pio/obj-dump.py +; pio/obj-dump.py ; *** Upload file to OTA server using SCP ;upload_port = user@host:/path @@ -240,7 +240,7 @@ upload_resetmethod = ${common.upload_resetmethod} upload_speed = 921600 extra_scripts = ${common.extra_scripts} -build_flags = +build_flags = ${esp_defaults.build_flags} -D BUFFER_LENGTH=128 -D MQTT_MAX_PACKET_SIZE=1200 -D uint32=uint32_t From 8035590e95270e4536b40bc0927ef147ecff9295 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 16 Apr 2020 19:46:26 +0200 Subject: [PATCH 29/70] Defaults for ESP82xx and ESP32 --- platformio.ini | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/platformio.ini b/platformio.ini index 6a3820d02..f29d5f363 100755 --- a/platformio.ini +++ b/platformio.ini @@ -87,17 +87,21 @@ extra_scripts = pio/strip-floats.py pio/name-firmware.py pio/gzip-firmware.py -[esp82xx_defaults] -build_flags = -D NDEBUG - -mtarget-align - -Wl,-Map,firmware.map - -DFP_IN_IROM -; new mechanism to set the IRremoteESP8266 supported protocols: none except HASH, NEC, RC5, RC6 - -D_IR_ENABLE_DEFAULT_=false +[esp_defaults] +build_flags = -D_IR_ENABLE_DEFAULT_=false -DDECODE_HASH=true -DDECODE_NEC=true -DSEND_NEC=true -DDECODE_RC5=true -DSEND_RC5=true -DDECODE_RC6=true -DSEND_RC6=true +; new mechanism to set the IRremoteESP8266 supported protocols: none except HASH, NEC, RC5, RC6 -[irremoteesp8266_full] +[esp82xx_defaults] +build_flags = ${esp_defaults.build_flags} + -Wl,-Map,firmware.map + -D NDEBUG + -mtarget-align + -DFP_IN_IROM + + +[irremoteesp_full] build_flags = -DUSE_IR_REMOTE_FULL -U_IR_ENABLE_DEFAULT_ -DDECODE_PRONTO=false -DSEND_PRONTO=false From bfead88b7dd302c31489233da20fb5bd423eabdd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 16 Apr 2020 19:48:01 +0200 Subject: [PATCH 30/70] irremote full for esp8266 and esp32 --- platformio_tasmota_env32.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio_tasmota_env32.ini b/platformio_tasmota_env32.ini index 4f6661c17..71bef8558 100644 --- a/platformio_tasmota_env32.ini +++ b/platformio_tasmota_env32.ini @@ -129,7 +129,7 @@ extra_scripts = ${common32.extra_scripts} lib_extra_dirs = ${common32.lib_extra_dirs} lib_ignore = ${common32.lib_ignore} build_unflags = ${common32.build_unflags} -build_flags = ${common32.build_flags} ${irremoteesp8266_full.build_flags} -DFIRMWARE_IR +build_flags = ${common32.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR [env:tasmota32-ircustom] framework = ${common.framework} @@ -148,7 +148,7 @@ extra_scripts = ${common32.extra_scripts} lib_extra_dirs = ${common32.lib_extra_dirs} lib_ignore = ${common32.lib_ignore} build_unflags = ${common32.build_unflags} -build_flags = ${common32.build_flags} ${irremoteesp8266_full.build_flags} +build_flags = ${common32.build_flags} ${irremoteesp_full.build_flags} [env:tasmota32-BG] framework = ${common.framework} From fa51c6147b5b1495352676c0b0482375bf463e7c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 16 Apr 2020 19:52:57 +0200 Subject: [PATCH 31/70] Update platformio_tasmota_env.ini --- platformio_tasmota_env.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index a09f01ecd..f122eae1b 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -32,10 +32,10 @@ build_flags = ${common.build_flags} -DFIRMWARE_SENSORS build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS [env:tasmota-ir] -build_flags = ${common.build_flags} ${irremoteesp8266_full.build_flags} -DFIRMWARE_IR +build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} -DFIRMWARE_IR [env:tasmota-ircustom] -build_flags = ${common.build_flags} ${irremoteesp8266_full.build_flags} +build_flags = ${common.build_flags} ${irremoteesp_full.build_flags} [env:tasmota-BG] build_flags = ${common.build_flags} -DMY_LANGUAGE=bg-BG From f6863484c36b2ec6a390efeca6cead4411669708 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 16 Apr 2020 20:54:35 +0200 Subject: [PATCH 32/70] Install only one and latest esptool ESP32 still uses as default the outdated esptool 2.6. Since esptool 2.8 is already used for ESP8266 use it for ESP32 too and prevent install of version 2.6 --- 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 8fdb61495..701f9c119 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -227,7 +227,7 @@ build_type = debug [common32] platform = espressif32@1.12.0 -platform_packages = +platform_packages = tool-esptoolpy@1.20800.0 board = wemos_d1_mini32 board_build.ldscript = esp32_out.ld board_build.partitions = esp32_partition_app1984k_spiffs64k.csv From 5507ad889a01886432d24d9225546075959124f6 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 17 Apr 2020 09:11:27 +0200 Subject: [PATCH 33/70] Added types for AqaraVibration sensor --- tasmota/xdrv_23_zigbee_5_converters.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 5e39771c5..e8c4e4ab0 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -905,10 +905,10 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Zuint16, Cx0101, 0x0006, Z(OpenPeriod), &Z_Copy }, // Aqara Lumi Vibration Sensor - { Zunk, Cx0101, 0x0055, Z(AqaraVibrationMode), &Z_AqaraVibration }, - { Zunk, Cx0101, 0x0503, Z(AqaraVibrationsOrAngle), &Z_Copy }, - { Zunk, Cx0101, 0x0505, Z(AqaraVibration505), &Z_Copy }, - { Zunk, Cx0101, 0x0508, Z(AqaraAccelerometer), &Z_AqaraVibration }, + { Zuint16, Cx0101, 0x0055, Z(AqaraVibrationMode), &Z_AqaraVibration }, + { Zuint16, Cx0101, 0x0503, Z(AqaraVibrationsOrAngle), &Z_Copy }, + { Zuint32, Cx0101, 0x0505, Z(AqaraVibration505), &Z_Copy }, + { Zuint48, Cx0101, 0x0508, Z(AqaraAccelerometer), &Z_AqaraVibration }, // Window Covering cluster { Zenum8, Cx0102, 0x0000, Z(WindowCoveringType), &Z_Copy }, From e43f0e36a206ea25513a5b1c1eb914d523313f4f Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 17 Apr 2020 09:16:08 +0200 Subject: [PATCH 34/70] Removed unsupported types --- tasmota/xdrv_23_zigbee_5_converters.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index e8c4e4ab0..5cfb5c05f 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -779,7 +779,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Zsingle, Cx000D, 0x0045, Z(AnalogOutMinValue), &Z_Copy }, { Zbool, Cx000D, 0x0051, Z(AnalogOutOutOfService),&Z_Copy }, { Zsingle, Cx000D, 0x0055, Z(AnalogOutValue), &Z_Copy }, - { Zunk, Cx000D, 0x0057, Z(AnalogOutPriorityArray),&Z_Copy }, + // { Zunk, Cx000D, 0x0057, Z(AnalogOutPriorityArray),&Z_Copy }, { Zenum8, Cx000D, 0x0067, Z(AnalogOutReliability), &Z_Copy }, { Zsingle, Cx000D, 0x0068, Z(AnalogOutRelinquishDefault),&Z_Copy }, { Zsingle, Cx000D, 0x006A, Z(AnalogOutResolution), &Z_Copy }, @@ -819,7 +819,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Zbool, Cx0010, 0x0051, Z(BinaryOutOutOfService),&Z_Copy }, { Zenum8, Cx0010, 0x0054, Z(BinaryOutPolarity), &Z_Copy }, { Zbool, Cx0010, 0x0055, Z(BinaryOutValue), &Z_Copy }, - { Zunk, Cx0010, 0x0057, Z(BinaryOutPriorityArray),&Z_Copy }, + // { Zunk, Cx0010, 0x0057, Z(BinaryOutPriorityArray),&Z_Copy }, { Zenum8, Cx0010, 0x0067, Z(BinaryOutReliability), &Z_Copy }, { Zbool, Cx0010, 0x0068, Z(BinaryOutRelinquishDefault),&Z_Copy }, { Zmap8, Cx0010, 0x006F, Z(BinaryOutStatusFlags), &Z_Copy }, @@ -833,14 +833,14 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Zuint32, Cx0011, 0x0043, Z(BinaryMinimumOnTime), &Z_Copy }, { Zbool, Cx0011, 0x0051, Z(BinaryOutOfService), &Z_Copy }, { Zbool, Cx0011, 0x0055, Z(BinaryValue), &Z_Copy }, - { Zunk, Cx0011, 0x0057, Z(BinaryPriorityArray), &Z_Copy }, + // { Zunk, Cx0011, 0x0057, Z(BinaryPriorityArray), &Z_Copy }, { Zenum8, Cx0011, 0x0067, Z(BinaryReliability), &Z_Copy }, { Zbool, Cx0011, 0x0068, Z(BinaryRelinquishDefault),&Z_Copy }, { Zmap8, Cx0011, 0x006F, Z(BinaryStatusFlags), &Z_Copy }, { Zuint32, Cx0011, 0x0100, Z(BinaryApplicationType),&Z_Copy }, // Multistate Input cluster - { Zunk, Cx0012, 0x000E, Z(MultiInStateText), &Z_Copy }, + // { Zunk, Cx0012, 0x000E, Z(MultiInStateText), &Z_Copy }, { Zstring, Cx0012, 0x001C, Z(MultiInDescription), &Z_Copy }, { Zuint16, Cx0012, 0x004A, Z(MultiInNumberOfStates),&Z_Copy }, { Zbool, Cx0012, 0x0051, Z(MultiInOutOfService), &Z_Copy }, @@ -862,7 +862,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Zuint32, Cx0013, 0x0100, Z(MultiOutApplicationType),&Z_Copy }, // Multistate Value cluster - { Zunk, Cx0014, 0x000E, Z(MultiStateText), &Z_Copy }, + // { Zunk, Cx0014, 0x000E, Z(MultiStateText), &Z_Copy }, { Zstring, Cx0014, 0x001C, Z(MultiDescription), &Z_Copy }, { Zuint16, Cx0014, 0x004A, Z(MultiNumberOfStates), &Z_Copy }, { Zbool, Cx0014, 0x0051, Z(MultiOutOfService), &Z_Copy }, From 4551c5f91a01b85be6b689f02a085ca3f721e768 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 17 Apr 2020 09:22:47 +0200 Subject: [PATCH 35/70] Adding type for Aqara_FF05 --- tasmota/xdrv_23_zigbee_5_converters.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 5cfb5c05f..1e115d13f 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -771,7 +771,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Zmap8, Cx000C, 0x006F, Z(AnalogInStatusFlags), &Z_Copy }, { Zenum16, Cx000C, 0x0075, Z(AnalogInEngineeringUnits),&Z_Copy }, { Zuint32, Cx000C, 0x0100, Z(AnalogInApplicationType),&Z_Copy }, - { Zunk, Cx000C, 0xFF05, Z(Aqara_FF05), &Z_Copy }, + { Zuint16, Cx000C, 0xFF05, Z(Aqara_FF05), &Z_Copy }, // Analog Output cluster { Zstring, Cx000D, 0x001C, Z(AnalogOutDescription), &Z_Copy }, @@ -850,7 +850,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { Zuint32, Cx0012, 0x0100, Z(MultiInApplicationType),&Z_Copy }, // Multistate output - { Zunk, Cx0013, 0x000E, Z(MultiOutStateText), &Z_Copy }, + // { Zunk, Cx0013, 0x000E, Z(MultiOutStateText), &Z_Copy }, { Zstring, Cx0013, 0x001C, Z(MultiOutDescription), &Z_Copy }, { Zuint16, Cx0013, 0x004A, Z(MultiOutNumberOfStates),&Z_Copy }, { Zbool, Cx0013, 0x0051, Z(MultiOutOutOfService), &Z_Copy }, From d3b2f8c489b8cbe5197fa2248abb0520d17bc2fd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 17 Apr 2020 11:57:09 +0200 Subject: [PATCH 36/70] Add config version tag - Add config version tag - Bump version 8.2.0.4 --- RELEASENOTES.md | 2 +- tasmota/CHANGELOG.md | 4 ++++ tasmota/settings.h | 3 ++- tasmota/settings.ino | 9 +++++++++ tasmota/tasmota_version.h | 2 +- tasmota/xdrv_01_webserver.ino | 10 ++++++++++ 6 files changed, 27 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 81b066e38..2fcda28f5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,7 +52,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.2.0.3 +### Version 8.2.0.4 - Change HM-10 sensor type detection and add features (#7962) - Change light scheme 2,3,4 cycle time speed from 24,48,72,... seconds to 4,6,12,24,36,48,... seconds (#8034) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index ede692fb4..273c44db5 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased (development) +### 8.2.0.4 20200417 + +- Add config version tag + ### 8.2.0.3 20200329 - Change light scheme 2,3,4 cycle time speed from 24,48,72,... seconds to 4,6,12,24,36,48,... seconds (#8034) diff --git a/tasmota/settings.h b/tasmota/settings.h index 01f0cf174..2c3a22af4 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -524,8 +524,9 @@ struct SYSCFG { uint8_t zb_channel; // F32 uint8_t zb_free_byte; // F33 uint16_t pms_wake_interval; // F34 + uint8_t config_version; // F36 - uint8_t free_f36[130]; // F36 - Decrement if adding new Setting variables just above and below + uint8_t free_f37[129]; // F37 - Decrement if adding new Setting variables just above and below // Only 32 bit boundary variables below uint16_t pulse_counter_debounce_low; // FB8 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 53110155f..1769b676d 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1337,6 +1337,15 @@ void SettingsDelta(void) } #endif // ESP8266 + if (Settings.version < 0x08020004) { +#ifdef ESP8266 + Settings.config_version = 0; // ESP8266 (Has been 0 for long time) +#endif // ESP8266 +#ifdef ESP32 + Settings.config_version = 1; // ESP32 +#endif // ESP32 + } + Settings.version = VERSION; SettingsSave(1); } diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 3b8314f65..4014ea4d5 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x08020003; +const uint32_t VERSION = 0x08020004; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 8b5806938..5660a231d 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2509,6 +2509,16 @@ void HandleUploadLoop(void) } else { valid_settings = (settings_buffer[0] == CONFIG_FILE_SIGN); } + + if (valid_settings) { +#ifdef ESP8266 + valid_settings = (0 == settings_buffer[0xF36]); // Settings.config_version +#endif // ESP8266 +#ifdef ESP32 + valid_settings = (1 == settings_buffer[0xF36]); // Settings.config_version +#endif // ESP32 + } + if (valid_settings) { SettingsDefaultSet2(); memcpy((char*)&Settings +16, settings_buffer +16, sizeof(Settings) -16); From e5a78deaa3c5c50e269d3b2984b36d7a33e49412 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 17 Apr 2020 12:08:43 +0200 Subject: [PATCH 37/70] Fix compile warning --- tasmota/xdrv_20_hue.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index f9e21c3a3..201491d09 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -542,6 +542,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { } } else { #endif +/* switch(on) { case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE); @@ -549,6 +550,8 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) { case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE); break; } +*/ + ExecuteCommandPower(device, (on) ? POWER_ON : POWER_OFF, SRC_HUE); response += buf; resp = true; #ifdef USE_SHUTTER From 318cfe2681c09fa9a2b090d215a3f0dc6464a381 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 17 Apr 2020 12:27:36 +0200 Subject: [PATCH 38/70] Disarm timer for Occupancy:0 --- tasmota/xdrv_23_zigbee_2_devices.ino | 2 +- tasmota/xdrv_23_zigbee_8_parsers.ino | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_2_devices.ino b/tasmota/xdrv_23_zigbee_2_devices.ino index 9f5ef60a9..23970042e 100644 --- a/tasmota/xdrv_23_zigbee_2_devices.ino +++ b/tasmota/xdrv_23_zigbee_2_devices.ino @@ -65,7 +65,7 @@ typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t groupaddr, uint16_ typedef enum Z_Def_Category { Z_CAT_NONE = 0, // no category, it will happen anyways Z_CAT_READ_ATTR, // Attribute reporting, either READ_ATTRIBUTE or REPORT_ATTRIBUTE, we coalesce all attributes reported if we can - Z_CAT_VIRTUAL_ATTR, // Creation of a virtual attribute, typically after a time-out. Ex: Aqara presence sensor + Z_CAT_VIRTUAL_OCCUPANCY, // Creation of a virtual attribute, typically after a time-out. Ex: Aqara presence sensor Z_CAT_REACHABILITY, // timer set to measure reachability of device, i.e. if we don't get an answer after 1s, it is marked as unreachable (for Alexa) Z_CAT_READ_0006, // Read 0x0006 cluster Z_CAT_READ_0008, // Read 0x0008 cluster diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index aa9505bd7..acccbb8fe 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -534,7 +534,9 @@ void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint8_t endpoint, co uint32_t occupancy = strToUInt(val_endpoint); if (occupancy) { - zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, OCCUPANCY_TIMEOUT, cluster, endpoint, Z_CAT_VIRTUAL_ATTR, 0, &Z_OccupancyCallback); + zigbee_devices.setTimer(shortaddr, 0 /* groupaddr */, OCCUPANCY_TIMEOUT, cluster, endpoint, Z_CAT_VIRTUAL_OCCUPANCY, 0, &Z_OccupancyCallback); + } else { + zigbee_devices.resetTimersForDevice(shortaddr, 0 /* groupaddr */, Z_CAT_VIRTUAL_OCCUPANCY); } } } From 39440e56c236bb274395828a1efa2cbf72abe7a7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 17 Apr 2020 14:40:09 +0200 Subject: [PATCH 39/70] Prep ESP32 template --- tasmota/tasmota_template_ESP32.h | 68 +++++--------------------------- 1 file changed, 10 insertions(+), 58 deletions(-) diff --git a/tasmota/tasmota_template_ESP32.h b/tasmota/tasmota_template_ESP32.h index b2d7a5846..59820893f 100644 --- a/tasmota/tasmota_template_ESP32.h +++ b/tasmota/tasmota_template_ESP32.h @@ -46,34 +46,28 @@ // Supported hardware modules enum SupportedModules { WEMOS, - ESP32_CAM, MAXMODULE }; -const char kModuleNames[] PROGMEM = - "WeMos D1 ESP32|ESP32 CAM|" - ; +const char kModuleNames[] PROGMEM = "ESP32-DevKit"; // Default module settings -const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { - WEMOS, - ESP32_CAM -}; +const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { WEMOS }; const mytmplt kModules[MAXMODULE] PROGMEM = { - { // "WeMos D1 ESP32", // Any ESP32 device like WeMos and NodeMCU hardware (ESP32) + { // WEMOS - Espressif ESP32-DevKitC - Any ESP32 device like WeMos and NodeMCU hardware (ESP32) GPIO_USER, //0 (I)O GPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK GPIO_USER, //1 IO TXD0 GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2 GPIO_USER, //2 IO GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0 GPIO_USER, //3 IO RXD0 GPIO3, U0RXD, CLK_OUT2 GPIO_USER, //4 IO GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER GPIO_USER, //5 IO GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK -// 0, //6 -// 0, //7 -// 0, //8 -// 0, //9 -// 0, //10 -// 0, //11 + //6 IO GPIO6, Flash CLK + //7 IO GPIO7, Flash D0 + //8 IO GPIO8, Flash D1 + //9 IO GPIO9, Flash D2 + //10 IO GPIO10, Flash D3 + //11 IO GPIO11, Flash CMD GPIO_USER, //12 (I)O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 (If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is connected and pulled high. See ESP32 datasheet for more details.) GPIO_USER, //13 IO GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER GPIO_USER, //14 IO GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2 @@ -83,49 +77,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, //18 IO GPIO18, VSPICLK, HS1_DATA7 GPIO_USER, //19 IO GPIO19, VSPIQ, U0CTS, EMAC_TXD0 0, //20 - 0, //21 IO GPIO21, VSPIHD, EMAC_TX_EN - GPIO_USER, //22 IO LED GPIO22, VSPIWP, U0RTS, EMAC_TXD1 - GPIO_USER, //23 IO GPIO23, VSPID, HS1_STROBE - 0, //24 - GPIO_USER, //25 IO GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0 - GPIO_USER, //26 IO GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1 - GPIO_USER, //27 IO GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV - 0, //28 - 0, //29 - 0, //30 - 0, //31 - GPIO_USER, //32 IO GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9 - GPIO_USER, //33 IO GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8 - GPIO_USER, //34 I NO PULLUP GPIO34, ADC1_CH6, RTC_GPIO4 - GPIO_USER, //35 I NO PULLUP GPIO35, ADC1_CH7, RTC_GPIO5 - GPIO_USER, //36 I NO PULLUP GPIO36, SENSOR_VP, ADC_H, ADC1_CH0, RTC_GPIO0 - 0, //37 NO PULLUP - 0, //38 NO PULLUP - GPIO_USER //39 I NO PULLUP GPIO39, SENSOR_VN, ADC1_CH3, ADC_H, RTC_GPIO3 - }, - { //"ESP32 CAM", - GPIO_USER, //0 (I)O GPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK - GPIO_USER, //1 IO TXD0 GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2 - GPIO_USER, //2 IO GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0 - GPIO_USER, //3 IO RXD0 GPIO3, U0RXD, CLK_OUT2 - GPIO_USER, //4 IO GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER - GPIO_USER, //5 IO GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK -// 0, //6 -// 0, //7 -// 0, //8 -// 0, //9 -// 0, //10 -// 0, //11 - GPIO_USER, //12 (I)O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 (If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is connected and pulled high. See ESP32 datasheet for more details.) - GPIO_USER, //13 IO GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER - GPIO_USER, //14 IO GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2 - GPIO_USER, //15 (I)O GPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD, SD_CMD, EMAC_RXD3 (If driven Low, silences boot messages from normal boot. Has internal pull-up, so unconnected = High = normal output.) - GPIO_USER, //16 IO GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT - GPIO_USER, //17 IO GPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180 - GPIO_USER, //18 IO GPIO18, VSPICLK, HS1_DATA7 - GPIO_USER, //19 IO GPIO19, VSPIQ, U0CTS, EMAC_TXD0 - 0, //20 - 0, //21 IO GPIO21, VSPIHD, EMAC_TX_EN + GPIO_USER, //21 IO GPIO21, VSPIHD, EMAC_TX_EN GPIO_USER, //22 IO LED GPIO22, VSPIWP, U0RTS, EMAC_TXD1 GPIO_USER, //23 IO GPIO23, VSPID, HS1_STROBE 0, //24 From dfa20994060538b39670a23f8a39cec94beffa21 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 17 Apr 2020 16:15:41 +0200 Subject: [PATCH 40/70] No Map file is generated for ESP32 Fix error for ESP32. Scripts checks if exists and generates only in target folder if there --- pio/name-firmware.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pio/name-firmware.py b/pio/name-firmware.py index dfb9b7f85..1490ecc5c 100644 --- a/pio/name-firmware.py +++ b/pio/name-firmware.py @@ -28,6 +28,7 @@ def bin_map_copy(source, target, env): shutil.copy(str(target[0]), bin_file) # copy firmware.map to map/.map - shutil.copy("firmware.map", map_file) + if os.path.isfile("firmware.map"): + shutil.move("firmware.map", map_file) env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [bin_map_copy]) From 09599bb4a17d640cd0aaf5d991565783f2954693 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 17 Apr 2020 16:17:01 +0200 Subject: [PATCH 41/70] Provide ESP32 base module support --- tasmota/support.ino | 28 +++++++-- tasmota/support_command.ino | 5 +- tasmota/tasmota_template_ESP32.h | 99 ++++++++++++++++---------------- tasmota/xdrv_01_webserver.ino | 16 ++---- 4 files changed, 81 insertions(+), 67 deletions(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index 0435293e6..65605abd3 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -100,7 +100,7 @@ uint32_t ResetReason(void) REASON_EXT_SYS_RST = 6 // "External System" external system reset */ #ifdef ESP8266 - return resetInfo.reason; // Returns Tasmota reason codes + return resetInfo.reason; #else return ESP_ResetInfoReason(); #endif @@ -1131,7 +1131,11 @@ void ModuleGpios(myio *gp) if (USER_MODULE == Settings.module) { memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio)); } else { +#ifdef ESP8266 memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio)); +#else // ESP32 + memcpy_P(&src, &kModules.gp, sizeof(mycfgio)); +#endif // ESP8266 - ESP32 } // 11 85 00 85 85 00 00 00 15 38 85 00 00 81 @@ -1142,10 +1146,9 @@ void ModuleGpios(myio *gp) #ifdef ESP8266 if (6 == i) { j = 9; } if (8 == i) { j = 12; } -#endif // ESP8266 -#ifdef ESP32 +#else // ESP32 if (6 == i) { j = 12; } -#endif // ESP32 +#endif // ESP8266 - ESP32 dest[j] = src[i]; j++; } @@ -1158,11 +1161,24 @@ gpio_flag ModuleFlag(void) { gpio_flag flag; +#ifdef ESP8266 if (USER_MODULE == Settings.module) { flag = Settings.user_template.flag; } else { memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag)); } +#else // ESP32 + if (USER_MODULE == Settings.module) { +/* + gpio_flag gpio_adc0; + memcpy_P(&gpio_adc0, &Settings.user_template.gp + ADC0_PIN - MIN_FLASH_PINS, sizeof(gpio_flag)); + flag = Settings.user_template.flag.data + gpio_adc0.data; +*/ + memcpy_P(&flag, &Settings.user_template.gp + ADC0_PIN - MIN_FLASH_PINS, sizeof(gpio_flag)); + } else { + memcpy_P(&flag, &kModules.gp + ADC0_PIN - MIN_FLASH_PINS, sizeof(gpio_flag)); + } +#endif // ESP8266 - ESP32 return flag; } @@ -1173,7 +1189,11 @@ void ModuleDefault(uint32_t module) Settings.user_template_base = module; char name[TOPSZ]; SettingsUpdateText(SET_TEMPLATE_NAME, GetTextIndexed(name, sizeof(name), module, kModuleNames)); +#ifdef ESP8266 memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt)); +#else // ESP32 + memcpy_P(&Settings.user_template, &kModules, sizeof(mytmplt)); +#endif // ESP8266 - ESP32 } void SetModuleType(void) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 0d4e12236..28eae87f1 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1117,10 +1117,9 @@ void CmndTemplate(void) #ifdef ESP8266 if (6 == i) { j = 9; } if (8 == i) { j = 12; } -#endif // ESP8266 -#ifdef ESP32 +#else // ESP32 if (6 == i) { j = 12; } -#endif // ESP32 +#endif // ESP8266 - ESP32 if (my_module.io[j] > GPIO_NONE) { Settings.user_template.gp.io[i] = my_module.io[j]; } diff --git a/tasmota/tasmota_template_ESP32.h b/tasmota/tasmota_template_ESP32.h index 59820893f..967da9400 100644 --- a/tasmota/tasmota_template_ESP32.h +++ b/tasmota/tasmota_template_ESP32.h @@ -45,58 +45,61 @@ /********************************************************************************************/ // Supported hardware modules enum SupportedModules { - WEMOS, - MAXMODULE -}; + WEMOS, ESP32_CAM_AITHINKER, + MAXMODULE}; -const char kModuleNames[] PROGMEM = "ESP32-DevKit"; +const char kModuleNames[] PROGMEM = + "ESP32-DevKit|ESP32 Cam AiThinker"; // Default module settings -const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { WEMOS }; +const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { + WEMOS, + ESP32_CAM_AITHINKER +}; -const mytmplt kModules[MAXMODULE] PROGMEM = { - { // WEMOS - Espressif ESP32-DevKitC - Any ESP32 device like WeMos and NodeMCU hardware (ESP32) - GPIO_USER, //0 (I)O GPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK - GPIO_USER, //1 IO TXD0 GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2 - GPIO_USER, //2 IO GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0 - GPIO_USER, //3 IO RXD0 GPIO3, U0RXD, CLK_OUT2 - GPIO_USER, //4 IO GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER - GPIO_USER, //5 IO GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK - //6 IO GPIO6, Flash CLK - //7 IO GPIO7, Flash D0 - //8 IO GPIO8, Flash D1 - //9 IO GPIO9, Flash D2 - //10 IO GPIO10, Flash D3 - //11 IO GPIO11, Flash CMD - GPIO_USER, //12 (I)O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 (If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is connected and pulled high. See ESP32 datasheet for more details.) - GPIO_USER, //13 IO GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER - GPIO_USER, //14 IO GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2 - GPIO_USER, //15 (I)O GPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD, SD_CMD, EMAC_RXD3 (If driven Low, silences boot messages from normal boot. Has internal pull-up, so unconnected = High = normal output.) - GPIO_USER, //16 IO GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT - GPIO_USER, //17 IO GPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180 - GPIO_USER, //18 IO GPIO18, VSPICLK, HS1_DATA7 - GPIO_USER, //19 IO GPIO19, VSPIQ, U0CTS, EMAC_TXD0 - 0, //20 - GPIO_USER, //21 IO GPIO21, VSPIHD, EMAC_TX_EN - GPIO_USER, //22 IO LED GPIO22, VSPIWP, U0RTS, EMAC_TXD1 - GPIO_USER, //23 IO GPIO23, VSPID, HS1_STROBE - 0, //24 - GPIO_USER, //25 IO GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0 - GPIO_USER, //26 IO GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1 - GPIO_USER, //27 IO GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV - 0, //28 - 0, //29 - 0, //30 - 0, //31 - GPIO_USER, //32 IO GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9 - GPIO_USER, //33 IO GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8 - GPIO_USER, //34 I NO PULLUP GPIO34, ADC1_CH6, RTC_GPIO4 - GPIO_USER, //35 I NO PULLUP GPIO35, ADC1_CH7, RTC_GPIO5 - GPIO_USER, //36 I NO PULLUP GPIO36, SENSOR_VP, ADC_H, ADC1_CH0, RTC_GPIO0 - 0, //37 NO PULLUP - 0, //38 NO PULLUP - GPIO_USER //39 I NO PULLUP GPIO39, SENSOR_VN, ADC1_CH3, ADC_H, RTC_GPIO3 - } +const mytmplt kModules PROGMEM = +{ // WEMOS - Espressif ESP32-DevKitC - Any ESP32 device like WeMos and NodeMCU hardware (ESP32) + GPIO_USER, //0 (I)O GPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK + GPIO_USER, //1 IO TXD0 GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2 + GPIO_USER, //2 IO GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0 + GPIO_USER, //3 IO RXD0 GPIO3, U0RXD, CLK_OUT2 + GPIO_USER, //4 IO GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER + GPIO_USER, //5 IO GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK + //6 IO GPIO6, Flash CLK + //7 IO GPIO7, Flash D0 + //8 IO GPIO8, Flash D1 + //9 IO GPIO9, Flash D2 + //10 IO GPIO10, Flash D3 + //11 IO GPIO11, Flash CMD + GPIO_USER, //12 (I)O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 (If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is connected and pulled high. See ESP32 datasheet for more details.) + GPIO_USER, //13 IO GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER + GPIO_USER, //14 IO GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2 + GPIO_USER, //15 (I)O GPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD, SD_CMD, EMAC_RXD3 (If driven Low, silences boot messages from normal boot. Has internal pull-up, so unconnected = High = normal output.) + GPIO_USER, //16 IO GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT + GPIO_USER, //17 IO GPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180 + GPIO_USER, //18 IO GPIO18, VSPICLK, HS1_DATA7 + GPIO_USER, //19 IO GPIO19, VSPIQ, U0CTS, EMAC_TXD0 + 0, //20 + GPIO_USER, //21 IO GPIO21, VSPIHD, EMAC_TX_EN + GPIO_USER, //22 IO LED GPIO22, VSPIWP, U0RTS, EMAC_TXD1 + GPIO_USER, //23 IO GPIO23, VSPID, HS1_STROBE + 0, //24 + GPIO_USER, //25 IO GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0 + GPIO_USER, //26 IO GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1 + GPIO_USER, //27 IO GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV + 0, //28 + 0, //29 + 0, //30 + 0, //31 + GPIO_USER, //32 IO GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9 + GPIO_USER, //33 IO GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8 + GPIO_USER, //34 I NO PULLUP GPIO34, ADC1_CH6, RTC_GPIO4 + GPIO_USER, //35 I NO PULLUP GPIO35, ADC1_CH7, RTC_GPIO5 + GPIO_USER, //36 I NO PULLUP GPIO36, SENSOR_VP, ADC_H, ADC1_CH0, RTC_GPIO0 + 0, //37 NO PULLUP + 0, //38 NO PULLUP + GPIO_USER, //39 I NO PULLUP GPIO39, SENSOR_VN, ADC1_CH3, ADC_H, RTC_GPIO3 + 0 // Flag }; #endif // ESP32 diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 5660a231d..d2e2e1813 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -261,21 +261,18 @@ const char HTTP_SCRIPT_TEMPLATE[] PROGMEM = "as=o.shift();" // Complete ADC0 list "g=o.shift().split(',');" // Array separator "j=0;" -// "for(i=0;i<13;i++){" // Supports 13 GPIOs "for(i=0;i<" STR(MAX_USER_PINS) ";i++){" // Supports 13 GPIOs #ifdef ESP8266 "if(6==i){j=9;}" "if(8==i){j=12;}" -#endif -#ifdef ESP32 +#else // ESP32 "if(6==i){j=12;}" -#endif +#endif // ESP8266 - ESP32 "sk(g[i],j);" // Set GPIO "j++;" "}" "g=o.shift();" // FLAG "os=as;" -// "sk(g&15,17);" // Set ADC0 "sk(g&15," STR(ADC0_PIN) ");" // Set ADC0 "g>>=4;" "for(i=0;i<" STR(GPIO_FLAG_USED) ";i++){" @@ -295,7 +292,6 @@ const char HTTP_SCRIPT_TEMPLATE[] PROGMEM = "function x2(a){" "os=a.responseText;" -// "sk(17,99);" // 17 = WEMOS "sk(" STR(WEMOS_MODULE) ",99);" // 17 = WEMOS "st(" STR(USER_MODULE) ");" "}" @@ -321,13 +317,11 @@ const char HTTP_SCRIPT_MODULE2[] PROGMEM = "}" "function x3(a){" // ADC0 "os=a.responseText;" -// "sk(%d,17);" "sk(%d," STR(ADC0_PIN) ");" "}" "function sl(){" "ld('md?m=1',x1);" // ?m related to Webserver->hasArg("m") "ld('md?g=1',x2);" // ?g related to Webserver->hasArg("g") -// "if(eb('g17')){" "if(eb('g" STR(ADC0_PIN) "')){" "ld('md?a=1',x3);" // ?a related to Webserver->hasArg("a") "}" @@ -1532,10 +1526,9 @@ void TemplateSaveSettings(void) #ifdef ESP8266 if (6 == i) { j = 9; } if (8 == i) { j = 12; } -#endif // ESP8266 -#ifdef ESP32 +#else // ESP32 if (6 == i) { j = 12; } -#endif // ESP32 +#endif // ESP8266 - ESP32 snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), j); WebGetArg(webindex, tmp, sizeof(tmp)); // GPIO uint8_t gpio = atoi(tmp); @@ -1543,7 +1536,6 @@ void TemplateSaveSettings(void) j++; } -// WebGetArg("g17", tmp, sizeof(tmp)); // FLAG - ADC0 WebGetArg("g" STR(ADC0_PIN), tmp, sizeof(tmp)); // FLAG - ADC0 uint32_t flag = atoi(tmp); for (uint32_t i = 0; i < GPIO_FLAG_USED; i++) { From bd38f72ce7f20cc13077d0546aa04d6aa7296961 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 17 Apr 2020 17:14:06 +0200 Subject: [PATCH 42/70] Fix Zigbee DimmerUp/DimmerDown malformed --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_23_zigbee_6_commands.ino | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 273c44db5..0fb205aff 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 8.2.0.4 20200417 - Add config version tag +- Fix Zigbee DimmerUp/DimmerDown malformed ### 8.2.0.3 20200329 diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index 1893925f3..8cb695bd6 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -53,7 +53,7 @@ ZF(DimmerMove) ZF(DimmerStep) ZF(HueMove) ZF(HueStep) ZF(SatMove) ZF(SatStep) ZF(ColorMove) ZF(ColorStep) ZF(ArrowClick) ZF(ArrowHold) ZF(ArrowRelease) ZF(ZoneStatusChange) -ZF(xxxx00) ZF(xxxx) ZF(01xxxx) ZF(00) ZF(01) ZF() ZF(xxxxyy) ZF(001902) ZF(011902) ZF(xxyyyy) ZF(xx) +ZF(xxxx00) ZF(xxxx) ZF(01xxxx) ZF(00) ZF(01) ZF() ZF(xxxxyy) ZF(00190200) ZF(01190200) ZF(xxyyyy) ZF(xx) ZF(xx000A00) ZF(xx0A00) ZF(xxyy0A00) ZF(xxxxyyyy0A00) ZF(xxxx0A00) ZF(xx0A) ZF(xx190A00) ZF(xx19) ZF(xx190A) ZF(xxxxyyyy) ZF(xxxxyyzz) ZF(xxyyzzzz) ZF(xxyyyyzz) @@ -82,8 +82,8 @@ const Z_CommandConverter Z_Commands[] PROGMEM = { // Light & Shutter commands { Z(Power), 0x0006, 0xFF, 0x01, Z() }, // 0=Off, 1=On, 2=Toggle { Z(Dimmer), 0x0008, 0x04, 0x01, Z(xx0A00) }, // Move to Level with On/Off, xx=0..254 (255 is invalid) - { Z(DimmerUp), 0x0008, 0x06, 0x01, Z(001902) }, // Step up by 10%, 0.2 secs - { Z(DimmerDown), 0x0008, 0x06, 0x01, Z(011902) }, // Step down by 10%, 0.2 secs + { Z(DimmerUp), 0x0008, 0x06, 0x01, Z(00190200) }, // Step up by 10%, 0.2 secs + { Z(DimmerDown), 0x0008, 0x06, 0x01, Z(01190200) }, // Step down by 10%, 0.2 secs { Z(DimmerStop), 0x0008, 0x03, 0x01, Z() }, // Stop any Dimmer animation { Z(ResetAlarm), 0x0009, 0x00, 0x01, Z(xxyyyy) }, // Reset alarm (alarm code + cluster identifier) { Z(ResetAllAlarms), 0x0009, 0x01, 0x01, Z() }, // Reset all alarms From 8765223f75c480813a19dee300b57110567ea0ca Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 17 Apr 2020 17:20:46 +0200 Subject: [PATCH 43/70] Add the possibility to add Custom env to build special Tasmota versions with Compiler switches defined in [env:tasmota-xyz] in `platformio_tasmota_cenv.ini` to control user_config_override.h Example: "[env:tasmota-zigbee] build_flags = ${common.build_flags} -DHANS_CONFIG_ZIGBEE=true" which referrs to in user_config_override.h ```#ifdef HANS_CONFIG_ZIGBEE // ****************************************************************** #undef CODE_IMAGE_STR #define CODE_IMAGE_STR "ZIGBEE" #define USE_WEBSERVER // Enable web server and Wifi Manager (+66k code, +8k mem) #define USE_JAVASCRIPT_ES6 // Enable ECMAScript6 syntax using less JavaScript code bytes (fails on IE11) // #define USE_WEBSEND_RESPONSE // Enable command WebSend response message (+1k code) //#define USE_RULES // Add support for rules (+4k4 code) // #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) // #define SUPPORT_IF_STATEMENT // Add support for IF statement in rules (+4k2 code, -332 bytes mem) // #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) //#define USE_SCRIPT // Add support for script // #define USE_SCRIPT_FATFS 4 // Add support for script storage on SD card (+12k code, +4k mem) // #define USE_SCRIPT_WEB_DISPLAY #define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices // -- Zigbee interface ---------------------------- #define USE_ZIGBEE // Enable serial communication with Zigbee CC2530 flashed with ZNP (+35k code, +3.2k mem) #define USE_ZIGBEE_PANID 0x1A63 // arbitrary PAN ID for Zigbee network, must be unique in the home #define USE_ZIGBEE_EXTPANID 0xCCCCCCCCCCCCCCCCL // arbitrary extended PAN ID #define USE_ZIGBEE_CHANNEL 11 // Zigbee Channel (11-26) #define USE_ZIGBEE_PRECFGKEY_L 0x0F0D0B0907050301L // note: changing requires to re-pair all devices #define USE_ZIGBEE_PRECFGKEY_H 0x0D0C0A0806040200L // note: changing requires to re-pair all devices #define USE_ZIGBEE_PERMIT_JOIN false // don't allow joining by default #define USE_ZIGBEE_COALESCE_ATTR_TIMER 350 // timer to coalesce attribute values (in ms) #endif ``` --- platformio_override_sample.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 701f9c119..8e898f6b6 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -12,6 +12,7 @@ [platformio] extra_configs = platformio_tasmota_env32.ini + platformio_tasmota_cenv.ini ; *** Build/upload environment default_envs = From a98b719f82796732b7b91fae3cf155156c736e88 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 17 Apr 2020 17:52:44 +0200 Subject: [PATCH 44/70] Remove warning/errors when compiling Zigbee for ESP32 --- tasmota/xdrv_23_zigbee_1_headers.ino | 8 ++++---- tasmota/xdrv_23_zigbee_3_hue.ino | 10 ++++------ tasmota/xdrv_23_zigbee_5_converters.ino | 4 ++-- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/xdrv_23_zigbee_1_headers.ino index 051858697..5a250c781 100644 --- a/tasmota/xdrv_23_zigbee_1_headers.ino +++ b/tasmota/xdrv_23_zigbee_1_headers.ino @@ -25,15 +25,15 @@ void ZigbeeZCLSend_Raw(uint16_t dtsAddr, uint16_t groupaddr, uint16_t clusterId, // Get an JSON attribute, with case insensitive key search -JsonVariant &getCaseInsensitive(const JsonObject &json, const char *needle) { +const JsonVariant &getCaseInsensitive(const JsonObject &json, const char *needle) { // key can be in PROGMEM if ((nullptr == &json) || (nullptr == needle) || (0 == pgm_read_byte(needle))) { return *(JsonVariant*)nullptr; } - for (auto kv : json) { - const char *key = kv.key; - JsonVariant &value = kv.value; + for (JsonObject::const_iterator it=json.begin(); it!=json.end(); ++it) { + const char *key = it->key; + const JsonVariant &value = it->value; if (0 == strcasecmp_P(key, needle)) { return value; diff --git a/tasmota/xdrv_23_zigbee_3_hue.ino b/tasmota/xdrv_23_zigbee_3_hue.ino index e534134dc..87b7d39da 100644 --- a/tasmota/xdrv_23_zigbee_3_hue.ino +++ b/tasmota/xdrv_23_zigbee_3_hue.ino @@ -201,12 +201,10 @@ void ZigbeeHandleHue(uint16_t shortaddr, uint32_t device_id, String &response) { PSTR("{\"success\":{\"/lights/%d/state/on\":%s}}"), device_id, on ? "true" : "false"); - switch(on) - { - case false : ZigbeeHuePower(shortaddr, 0x00); - break; - case true : ZigbeeHuePower(shortaddr, 0x01); - break; + if (on) { + ZigbeeHuePower(shortaddr, 0x01); + } else { + ZigbeeHuePower(shortaddr, 0x00); } response += buf; resp = true; diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 1e115d13f..67ff8993f 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -109,7 +109,7 @@ public: uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, uint32_t timestamp): - _cmd_id(cmd_id), _manuf_code(manuf_code), _transact_seq(transact_seq), + _manuf_code(manuf_code), _transact_seq(transact_seq), _cmd_id(cmd_id), _payload(buf_len ? buf_len : 250), // allocate the data frame from source or preallocate big enough _cluster_id(clusterid), _groupaddr(groupaddr), _srcaddr(srcaddr), _srcendpoint(srcendpoint), _dstendpoint(dstendpoint), _wasbroadcast(wasbroadcast), @@ -215,9 +215,9 @@ private: uint16_t _manuf_code = 0; // optional uint8_t _transact_seq = 0; // transaction sequence number uint8_t _cmd_id = 0; + SBuffer _payload; uint16_t _cluster_id = 0; uint16_t _groupaddr = 0; - SBuffer _payload; // information from decoded ZCL frame uint16_t _srcaddr; uint8_t _srcendpoint; From b70ca01231b9fc54d5ab23d458f3e124ce78acad Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 17 Apr 2020 18:27:31 +0200 Subject: [PATCH 45/70] Add ESP32 optional brownout disable Add ESP32 brownout disable for weak onboard LDO's - eventually you'll need to change the LDO to a better one. --- libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp | 9 +++++++++ libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h | 1 + tasmota/tasmota.ino | 6 ++++++ 3 files changed, 16 insertions(+) diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp index 029d41470..6635f6d4d 100644 --- a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp +++ b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp @@ -109,3 +109,12 @@ uint32_t ESP_getSketchSize(void) } return sketchsize; } + +#include "soc/soc.h" +#include "soc/rtc_cntl_reg.h" + +void DisableBrownout(void) +{ + // https://github.com/espressif/arduino-esp32/issues/863#issuecomment-347179737 + WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // Disable brownout detector +} diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h index 28e187d52..276772b95 100644 --- a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h +++ b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h @@ -43,6 +43,7 @@ uint32_t ESP_getFlashChipId(); uint32_t ESP_getChipId(); String String_ESP_getChipId(); uint32_t ESP_getSketchSize(); +void DisableBrownout(void); // Analog inline void analogWrite(uint8_t pin, int val) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 1a7c250ae..a0d684517 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -192,6 +192,12 @@ void setup(void) { global_state.data = 3; // Init global state (wifi_down, mqtt_down) to solve possible network issues +#ifdef ESP32 +#ifdef DISABLE_BROWNOUT + DisableBrownout(); +#endif +#endif + RtcRebootLoad(); if (!RtcRebootValid()) { RtcReboot.fast_reboot_count = 0; From d69b8a158dc32ef596b9b8841758e0ce5258f39c Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Fri, 17 Apr 2020 19:23:41 -0300 Subject: [PATCH 46/70] Inverted buttons V2 --- tasmota/support_button_v2.ino | 44 +++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/tasmota/support_button_v2.ino b/tasmota/support_button_v2.ino index d345b58d2..9548a2b4f 100644 --- a/tasmota/support_button_v2.ino +++ b/tasmota/support_button_v2.ino @@ -1,7 +1,7 @@ /* - support_button.ino - button support for Tasmota + support_button_v2.ino - button support for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2020 Federico Leoni and Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,12 +23,8 @@ * Button support \*********************************************************************************************/ -#define MAX_BUTTON_COMMANDS_V2 3 // Max number of button commands supported #define MAX_RELAY_BUTTON1 4 // Max number of relay controlled by button1 -const char kCommands[] PROGMEM = - D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1"; - //D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1"; const char kMultiPress[] PROGMEM = "|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|"; @@ -107,7 +103,6 @@ uint8_t ButtonSerial(uint8_t serial_in_byte) * SetOption11 (0) - If set perform single press action on double press and reverse * SetOption13 (0) - If set act on single press only * SetOption32 (40) - Max button hold time in Seconds - * SetOption40 (0) - Number of 0.1 seconds until hold is discarded if SetOption1 1 and SetOption13 0 * SetOption73 (0) - Decouple button from relay and send just mqtt topic \*********************************************************************************************/ @@ -177,16 +172,19 @@ void ButtonHandler(void) if (!Button.hold_timer[button_index]) { button_pressed = true; } // Do not allow within 1 second } if (button_pressed) { - if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set - ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally - - } + if (!Settings.flag3.mqtt_buttons) { + if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set + ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally + } else { + MqttButtonTopic(button_index +1, 1, 0); // SetOption73 (0) - Decouple button from relay and send just mqtt topic } + } + } } } #endif // ESP8266 else { - - if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { + if (((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index]) && !Button.inverted_mask) || + ((NOT_PRESSED == button) && (PRESSED == Button.last_state[button_index]) && Button.inverted_mask)) { if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action, SetOption73 (0) - Decouple button from relay and send just mqtt topic if (!Settings.flag3.mqtt_buttons) { @@ -203,9 +201,9 @@ void ButtonHandler(void) Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window } blinks = 201; - } + } - if (NOT_PRESSED == button) { + if (((NOT_PRESSED == button) && !Button.inverted_mask) || ((PRESSED == button) && Button.inverted_mask)) { Button.hold_timer[button_index] = 0; } else { Button.hold_timer[button_index]++; @@ -223,11 +221,11 @@ void ButtonHandler(void) SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); // Execute Hold command via MQTT if ButtonTopic is set } } else { - if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer + if ((Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10)) { // SetOption32 (40) - Button held for factor times longer Button.press_counter[button_index] = 0; snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); ExecuteCommand(scmnd, SRC_BUTTON); - } + } } } } @@ -236,7 +234,9 @@ void ButtonHandler(void) if (Button.window_timer[button_index]) { Button.window_timer[button_index]--; } else { - if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS_V2 +6)) { + // if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS_V2 +6)) { + if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < 7)) { + bool single_press = false; if (Button.press_counter[button_index] < 3) { // Single or Double press #ifdef ESP8266 @@ -280,8 +280,12 @@ void ButtonHandler(void) } } } - } else { // 6 - 8 press are used to send commands - GetTextIndexed(scmnd, sizeof(scmnd), Button.press_counter[button_index] -6, kCommands); + // } else { // 6 - 8 press are used to send commands + // GetTextIndexed(scmnd, sizeof(scmnd), Button.press_counter[button_index] -6, kCommands); + // ExecuteCommand(scmnd, SRC_BUTTON); + // } + } else { // 6 press start wificonfig 2 + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2")); ExecuteCommand(scmnd, SRC_BUTTON); } if (Settings.flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic From e0753eeeada909553ed1c186b5ebbb198519a0d3 Mon Sep 17 00:00:00 2001 From: bovirus <1262554+bovirus@users.noreply.github.com> Date: Sat, 18 Apr 2020 09:59:25 +0200 Subject: [PATCH 47/70] Update Italian tarnslation Align Italian enw string to the scheme of translation of previous strings (see up/down) --- tasmota/language/it-IT.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index 934fcfc75..4f1cfbe17 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -567,8 +567,8 @@ #define D_SENSOR_SPI_MOSI "SPI - MOSI" #define D_SENSOR_SPI_CLK "SPI - CLK" #define D_SENSOR_BACKLIGHT "Retroilluminazione" -#define D_SENSOR_PMS5003_TX "PMS5003 Tx" -#define D_SENSOR_PMS5003_RX "PMS5003 Rx" +#define D_SENSOR_PMS5003_TX "PMS5003 - TX" +#define D_SENSOR_PMS5003_RX "PMS5003 - RX" #define D_SENSOR_SDS0X1_RX "SDS0X1 - RX" #define D_SENSOR_SDS0X1_TX "SDS0X1 - TX" #define D_SENSOR_HPMA_RX "HPMA - RX" From 9d838c001c5e6a9c40a470e7c6caec785827e6a2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 18 Apr 2020 16:30:36 +0200 Subject: [PATCH 48/70] Fix possible powerretain failure Fix possible powerretain failure (#8219) --- tasmota/xdrv_02_mqtt.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 6ad843980..eaa2562e8 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -1028,6 +1028,9 @@ void CmndPowerRetain(void) } } Settings.flag.mqtt_power_retain = XdrvMailbox.payload; // CMND_POWERRETAIN + if (Settings.flag.mqtt_power_retain) { + Settings.flag4.only_json_message = 0; // SetOption90 - Disable non-json MQTT response + } } ResponseCmndStateText(Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN } From 684b7dc3a474eba93d5468b2d16d020d03a414fb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 18 Apr 2020 16:34:29 +0200 Subject: [PATCH 49/70] Update ESP32 optional brownout disable --- tasmota/tasmota.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index a0d684517..7ae7d60bb 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -190,14 +190,14 @@ char web_log[WEB_LOG_SIZE] = {'\0'}; // Web log buffer void setup(void) { - global_state.data = 3; // Init global state (wifi_down, mqtt_down) to solve possible network issues - #ifdef ESP32 -#ifdef DISABLE_BROWNOUT - DisableBrownout(); +#ifdef DISABLE_ESP32_BROWNOUT + DisableBrownout(); // Workaround possible weak LDO resulting in brownout detection during Wifi connection #endif #endif + global_state.data = 3; // Init global state (wifi_down, mqtt_down) to solve possible network issues + RtcRebootLoad(); if (!RtcRebootValid()) { RtcReboot.fast_reboot_count = 0; From 48dd608da954d69c9d5064c1d65d989caaf8d1d2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 18 Apr 2020 17:04:00 +0200 Subject: [PATCH 50/70] Fix HTU21 sensor loss after ESP32 restart --- tasmota/xsns_08_htu21.ino | 82 +++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/tasmota/xsns_08_htu21.ino b/tasmota/xsns_08_htu21.ino index e0cab5d1c..1dc4d4fb1 100644 --- a/tasmota/xsns_08_htu21.ino +++ b/tasmota/xsns_08_htu21.ino @@ -59,14 +59,18 @@ const char kHtuTypes[] PROGMEM = "HTU21|SI7013|SI7020|SI7021|T/RH?"; -uint8_t htu_address; -uint8_t htu_type = 0; -uint8_t htu_delay_temp; -uint8_t htu_delay_humidity = 50; -uint8_t htu_valid = 0; -float htu_temperature = 0; -float htu_humidity = 0; -char htu_types[7]; +struct { + float temperature = 0; + float humidity = 0; + uint8_t address; + uint8_t type = 0; + uint8_t delay_temp; + uint8_t delay_humidity = 50; + uint8_t valid = 0; + char types[7]; +} Htu; + +/*********************************************************************************************/ uint8_t HtuCheckCrc8(uint16_t data) { @@ -82,6 +86,8 @@ uint8_t HtuCheckCrc8(uint16_t data) uint8_t HtuReadDeviceId(void) { + HtuReset(); // Fixes ESP32 sensor loss at restart + uint16_t deviceID = 0; uint8_t checksum = 0; @@ -146,12 +152,12 @@ bool HtuRead(void) uint8_t checksum = 0; uint16_t sensorval = 0; - if (htu_valid) { htu_valid--; } + if (Htu.valid) { Htu.valid--; } Wire.beginTransmission(HTU21_ADDR); Wire.write(HTU21_READTEMP); if (Wire.endTransmission() != 0) { return false; } // In case of error - delay(htu_delay_temp); // Sensor time at max resolution + delay(Htu.delay_temp); // Sensor time at max resolution Wire.requestFrom(HTU21_ADDR, 3); if (3 == Wire.available()) { @@ -161,12 +167,12 @@ bool HtuRead(void) } if (HtuCheckCrc8(sensorval) != checksum) { return false; } // Checksum mismatch - htu_temperature = ConvertTemp(0.002681 * (float)sensorval - 46.85); + Htu.temperature = ConvertTemp(0.002681 * (float)sensorval - 46.85); Wire.beginTransmission(HTU21_ADDR); Wire.write(HTU21_READHUM); if (Wire.endTransmission() != 0) { return false; } // In case of error - delay(htu_delay_humidity); // Sensor time at max resolution + delay(Htu.delay_humidity); // Sensor time at max resolution Wire.requestFrom(HTU21_ADDR, 3); if (3 <= Wire.available()) { @@ -177,19 +183,19 @@ bool HtuRead(void) if (HtuCheckCrc8(sensorval) != checksum) { return false; } // Checksum mismatch sensorval ^= 0x02; // clear status bits - htu_humidity = 0.001907 * (float)sensorval - 6; - if (htu_humidity > 100) { htu_humidity = 100.0; } - if (htu_humidity < 0) { htu_humidity = 0.01; } + Htu.humidity = 0.001907 * (float)sensorval - 6; + if (Htu.humidity > 100) { Htu.humidity = 100.0; } + if (Htu.humidity < 0) { Htu.humidity = 0.01; } - if ((0.00 == htu_humidity) && (0.00 == htu_temperature)) { - htu_humidity = 0.0; + if ((0.00 == Htu.humidity) && (0.00 == Htu.temperature)) { + Htu.humidity = 0.0; } - if ((htu_temperature > 0.00) && (htu_temperature < 80.00)) { - htu_humidity = (-0.15) * (25 - htu_temperature) + htu_humidity; + if ((Htu.temperature > 0.00) && (Htu.temperature < 80.00)) { + Htu.humidity = (-0.15) * (25 - Htu.temperature) + Htu.humidity; } - htu_humidity = ConvertHumidity(htu_humidity); + Htu.humidity = ConvertHumidity(Htu.humidity); - htu_valid = SENSOR_MAX_MISS; + Htu.valid = SENSOR_MAX_MISS; return true; } @@ -197,17 +203,17 @@ bool HtuRead(void) void HtuDetect(void) { - htu_address = HTU21_ADDR; - if (I2cActive(htu_address)) { return; } + Htu.address = HTU21_ADDR; + if (I2cActive(Htu.address)) { return; } - htu_type = HtuReadDeviceId(); - if (htu_type) { + Htu.type = HtuReadDeviceId(); + if (Htu.type) { uint8_t index = 0; HtuInit(); - switch (htu_type) { + switch (Htu.type) { case HTU21_CHIPID: - htu_delay_temp = 50; - htu_delay_humidity = 16; + Htu.delay_temp = 50; + Htu.delay_humidity = 16; break; case SI7021_CHIPID: index++; // 3 @@ -215,16 +221,16 @@ void HtuDetect(void) index++; // 2 case SI7013_CHIPID: index++; // 1 - htu_delay_temp = 12; - htu_delay_humidity = 23; + Htu.delay_temp = 12; + Htu.delay_humidity = 23; break; default: index = 4; - htu_delay_temp = 50; - htu_delay_humidity = 23; + Htu.delay_temp = 50; + Htu.delay_humidity = 23; } - GetTextIndexed(htu_types, sizeof(htu_types), index, kHtuTypes); - I2cSetActiveFound(htu_address, htu_types); + GetTextIndexed(Htu.types, sizeof(Htu.types), index, kHtuTypes); + I2cSetActiveFound(Htu.address, Htu.types); } } @@ -233,15 +239,15 @@ void HtuEverySecond(void) if (uptime &1) { // Every 2 seconds // HTU21: 68mS, SI70xx: 37mS if (!HtuRead()) { - AddLogMissed(htu_types, htu_valid); + AddLogMissed(Htu.types, Htu.valid); } } } void HtuShow(bool json) { - if (htu_valid) { - TempHumDewShow(json, (0 == tele_period), htu_types, htu_temperature, htu_humidity); + if (Htu.valid) { + TempHumDewShow(json, (0 == tele_period), Htu.types, Htu.temperature, Htu.humidity); } } @@ -258,7 +264,7 @@ bool Xsns08(uint8_t function) if (FUNC_INIT == function) { HtuDetect(); } - else if (htu_type) { + else if (Htu.type) { switch (function) { case FUNC_EVERY_SECOND: HtuEverySecond(); From e1d7416a36062ab832cdee4251ded26c1f02974c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 18 Apr 2020 18:10:41 +0200 Subject: [PATCH 51/70] Add features to ESP32 - Decided to support ONLY flash mode DOUT (no software change but allows for RX1/TX1) - Add GPIO9 (RX1) and GPIO10 (TX1) for hardware serial support - Add above two GPIOs to template - Moved basic ADC0 support from GPIO36 to GPIO33 --- tasmota/settings.h | 4 ++-- tasmota/support.ino | 9 --------- tasmota/support_command.ino | 4 ---- tasmota/tasmota_template.h | 7 ++++--- tasmota/tasmota_template_ESP32.h | 4 ++-- tasmota/xdrv_01_webserver.ino | 11 ++--------- 6 files changed, 10 insertions(+), 29 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 2c3a22af4..e1b63beff 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -407,9 +407,9 @@ struct SYSCFG { char ex_mqtt_fulltopic[100]; // 558 #else // ESP32 myio my_gp; // 558 - 40 bytes (ESP32) - mytmplt user_template; // 580 - 35 bytes (ESP32) + mytmplt user_template; // 580 - 37 bytes (ESP32) - uint8_t free_esp32_5a3[25]; // 5A3 + uint8_t free_esp32_5a5[23]; // 5A5 #endif // ESP8266 - ESP32 SysBitfield2 flag2; // 5BC diff --git a/tasmota/support.ino b/tasmota/support.ino index 65605abd3..4b9961e94 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1143,12 +1143,8 @@ void ModuleGpios(myio *gp) uint32_t j = 0; for (uint32_t i = 0; i < sizeof(mycfgio); i++) { -#ifdef ESP8266 if (6 == i) { j = 9; } if (8 == i) { j = 12; } -#else // ESP32 - if (6 == i) { j = 12; } -#endif // ESP8266 - ESP32 dest[j] = src[i]; j++; } @@ -1203,12 +1199,7 @@ void SetModuleType(void) bool FlashPin(uint32_t pin) { -#ifdef ESP8266 return (((pin > 5) && (pin < 9)) || (11 == pin)); -#endif // ESP8266 -#ifdef ESP32 - return ((pin > 5) && (pin < 12)); -#endif // ESP32 } uint8_t ValidPin(uint32_t pin, uint32_t gpio) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 28eae87f1..18ead323a 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1114,12 +1114,8 @@ void CmndTemplate(void) SettingsUpdateText(SET_TEMPLATE_NAME, "Merged"); uint32_t j = 0; for (uint32_t i = 0; i < sizeof(mycfgio); i++) { -#ifdef ESP8266 if (6 == i) { j = 9; } if (8 == i) { j = 12; } -#else // ESP32 - if (6 == i) { j = 12; } -#endif // ESP8266 - ESP32 if (my_module.io[j] > GPIO_NONE) { Settings.user_template.gp.io[i] = my_module.io[j]; } diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index f235147bf..6a047f25f 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -713,11 +713,12 @@ const char PINS_WEMOS[] PROGMEM = "D3TXD4RXD2D1flashcFLFLolD6D7D5D8D0A0"; // esp32 has more pins #define USER_MODULE 255 #define MAX_GPIO_PIN 40 // Number of supported GPIO -#define MIN_FLASH_PINS 6 // Number of flash chip pins unusable for configuration (GPIO6, 7, 8, 9, 10 and 11) -#define ADC0_PIN 36 // Pin number of ADC0 +#define MIN_FLASH_PINS 4 // Number of flash chip pins unusable for configuration (GPIO6, 7, 8 and 11) +#define ADC0_PIN 33 // Pin number of ADC0 #define WEMOS_MODULE 0 // Wemos module -const char PINS_WEMOS[] PROGMEM = "00TX02RX04050607080910111213141516171819202122232425262728293031A4A5A6A7A03738A3"; +//const char PINS_WEMOS[] PROGMEM = "00TX02RX0405060708R1T11112131415R2T21819202122232425262728293031A4A5A6A7A03738A3"; +const char PINS_WEMOS[] PROGMEM = "I00TX0I02RX0I04I05I06I07I08RX1TX1I11I12I13I14I15RX2TX2I18I19I20I21I22I23I24I25I26I27I28I29I30I31AD4AD5AD6AD7AD0I37I38AD3"; #endif // ESP8266 diff --git a/tasmota/tasmota_template_ESP32.h b/tasmota/tasmota_template_ESP32.h index 967da9400..831532a59 100644 --- a/tasmota/tasmota_template_ESP32.h +++ b/tasmota/tasmota_template_ESP32.h @@ -68,8 +68,8 @@ const mytmplt kModules PROGMEM = //6 IO GPIO6, Flash CLK //7 IO GPIO7, Flash D0 //8 IO GPIO8, Flash D1 - //9 IO GPIO9, Flash D2 - //10 IO GPIO10, Flash D3 + GPIO_USER, //9 IO GPIO9, Flash D2, U1RXD + GPIO_USER, //10 IO GPIO10, Flash D3, U1TXD //11 IO GPIO11, Flash CMD GPIO_USER, //12 (I)O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 (If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is connected and pulled high. See ESP32 datasheet for more details.) GPIO_USER, //13 IO GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index d2e2e1813..1a54edb76 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -262,12 +262,8 @@ const char HTTP_SCRIPT_TEMPLATE[] PROGMEM = "g=o.shift().split(',');" // Array separator "j=0;" "for(i=0;i<" STR(MAX_USER_PINS) ";i++){" // Supports 13 GPIOs -#ifdef ESP8266 "if(6==i){j=9;}" "if(8==i){j=12;}" -#else // ESP32 - "if(6==i){j=12;}" -#endif // ESP8266 - ESP32 "sk(g[i],j);" // Set GPIO "j++;" "}" @@ -1523,12 +1519,8 @@ void TemplateSaveSettings(void) uint32_t j = 0; for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { -#ifdef ESP8266 if (6 == i) { j = 9; } if (8 == i) { j = 12; } -#else // ESP32 - if (6 == i) { j = 12; } -#endif // ESP8266 - ESP32 snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), j); WebGetArg(webindex, tmp, sizeof(tmp)); // GPIO uint8_t gpio = atoi(tmp); @@ -1622,13 +1614,14 @@ void HandleModuleConfiguration(void) WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); for (uint32_t i = 0; i < sizeof(cmodule); i++) { if (ValidGPIO(i, cmodule.io[i])) { - snprintf_P(stemp, 3, PINS_WEMOS +i*2); #ifdef ESP8266 + snprintf_P(stemp, 3, PINS_WEMOS +i*2); char sesp8285[40]; snprintf_P(sesp8285, sizeof(sesp8285), PSTR("ESP8285"), WebColor(COL_TEXT_WARNING)); WSContentSend_P(PSTR("%s " D_GPIO "%d %s"), (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? sesp8285 :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i); #else // ESP32 + snprintf_P(stemp, 4, PINS_WEMOS +i*3); WSContentSend_P(PSTR("%s " D_GPIO "%d"), (WEMOS==my_module_type)?stemp:"", i, i); #endif // ESP8266 From f040b905834c75b46f22f6883455c5fd592c5114 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Sat, 18 Apr 2020 22:37:05 -0500 Subject: [PATCH 52/70] Add DGR Event item, Rework item parsing --- tasmota/support_device_groups.ino | 319 +++++++++++++----------------- tasmota/tasmota.h | 3 +- tasmota/tasmota_configurations.h | 2 +- tasmota/xdrv_10_rules.ino | 2 +- 4 files changed, 142 insertions(+), 184 deletions(-) diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index 3a9258a60..6ed072490 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -155,6 +155,9 @@ bool DeviceGroupItemShared(bool incoming, uint8_t item) case DGR_ITEM_BRI_PRESET_HIGH: mask = DGR_SHARE_DIMMER_SETTINGS; break; + case DGR_ITEM_EVENT: + mask = DGR_SHARE_EVENT; + break; } return (!mask || ((incoming ? Settings.device_group_share_in : Settings.device_group_share_out) & mask)); } @@ -225,24 +228,29 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes else { #ifdef USE_DEVICE_GROUPS_SEND + bool escaped; bool use_command; + char chr; char oper; uint32_t old_value; - char * delim_ptr; + char * out_ptr; #endif // USE_DEVICE_GROUPS_SEND + struct item { + uint8_t item; + uint32_t value; + void * value_ptr; + } item_array[32]; bool shared; uint8_t item; uint32_t value; char * value_ptr; + struct item * item_ptr; va_list ap; #ifdef DEVICE_GROUPS_DEBUG AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Building device group %s packet"), device_group->group_name); #endif // DEVICE_GROUPS_DEBUG -#ifdef USE_DEVICE_GROUPS_SEND - use_command = (message_type == DGR_MSGTYPE_UPDATE_COMMAND); -#endif // USE_DEVICE_GROUPS_SEND value = 0; if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) value |= DGR_FLAG_MORE_TO_COME; @@ -253,73 +261,96 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes #endif // DEVICE_GROUPS_DEBUG message_ptr = BeginDeviceGroupMessage(device_group, value, building_status_message || message_type == DGR_MSGTYP_PARTIAL_UPDATE); + // Build an array of all the items and values in this update. + memset(item_array, 0, sizeof(item_array)); + item_ptr = item_array; +#ifdef USE_DEVICE_GROUPS_SEND + use_command = (message_type == DGR_MSGTYPE_UPDATE_COMMAND); + if (use_command) { + value_ptr = XdrvMailbox.data; + while ((item = strtoul(value_ptr, &value_ptr, 0))) { + item_ptr->item = item; + if (*value_ptr == '=') { + value_ptr++; + if (item <= DGR_ITEM_MAX_32BIT) { + oper = 0; + if (*value_ptr == '@') { + oper = value_ptr[1]; + value_ptr += 2; + } + value = strtoul(value_ptr, &value_ptr, 0); + if (oper) { + old_value = (item <= DGR_ITEM_MAX_8BIT ? device_group->values_8bit[item] : (item <= DGR_ITEM_MAX_16BIT ? device_group->values_16bit[item - DGR_ITEM_MAX_8BIT - 1] : device_group->values_32bit[item - DGR_ITEM_MAX_16BIT - 1])); + value = (oper == '+' ? old_value + value : (oper == '-' ? old_value - value : (oper == '^' ? old_value ^ (value ? value : 0xffffffff) : old_value))); + } + item_ptr->value = value; + } + else if (item <= DGR_ITEM_MAX_STRING) { + item_ptr->value_ptr = out_ptr = value_ptr; + escaped = false; + while ((chr = *value_ptr++)) { + if (chr == ' ' && !escaped) break; + if (!(escaped = (chr == '\\' && !escaped))) *out_ptr++ = chr; + } + *out_ptr = 0; + } + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + item_ptr->value_ptr = out_ptr = value_ptr; + for (int i = 0; i < 5; i++) { + *out_ptr = strtoul(value_ptr, &value_ptr, 0); + if (*value_ptr == ',') value_ptr++; + } + break; + } + } + } + item_ptr++; + } + } + else { +#endif // USE_DEVICE_GROUPS_SEND + va_start(ap, message_type); + while ((item = va_arg(ap, int))) { + item_ptr->item = item; + if (item <= DGR_ITEM_MAX_32BIT) + item_ptr->value = va_arg(ap, int); + else if (item <= DGR_ITEM_MAX_STRING) + item_ptr->value_ptr = va_arg(ap, char *); + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + item_ptr->value_ptr = va_arg(ap, uint8_t *); + break; + } + } + item_ptr++; + } + va_end(ap); +#ifdef USE_DEVICE_GROUPS_SEND + } +#endif // USE_DEVICE_GROUPS_SEND + // If we're still building this update or all group members haven't acknowledged the previous // update yet, update the message to include these new updates. First we need to rebuild the // previous update message to remove any items and their values that are included in this new // update. if (device_group->message_length) { - uint8_t item_array[32]; - int item_index = 0; int kept_item_count = 0; - // Build an array of all the items in this new update. -#ifdef USE_DEVICE_GROUPS_SEND - if (use_command) - value_ptr = XdrvMailbox.data; - else -#endif // USE_DEVICE_GROUPS_SEND - va_start(ap, message_type); -#ifdef USE_DEVICE_GROUPS_SEND - while (use_command ? (item = strtoul(value_ptr, &delim_ptr, 0)) : (item = va_arg(ap, int))) { -#else // USE_DEVICE_GROUPS_SEND - while ((item = va_arg(ap, int))) { -#endif // !USE_DEVICE_GROUPS_SEND - item_array[item_index++] = item; -#ifdef USE_DEVICE_GROUPS_SEND - if (use_command) { - if (!*delim_ptr) break; - if (*delim_ptr == '=') { - delim_ptr = strchr(delim_ptr, ' '); - if (!delim_ptr) break; - } - value_ptr = delim_ptr + 1; - } - else { -#endif // USE_DEVICE_GROUPS_SEND - if (item <= DGR_ITEM_MAX_32BIT) - va_arg(ap, int); - else if (item <= DGR_ITEM_MAX_STRING) - va_arg(ap, char *); - else { - switch (item) { - case DGR_ITEM_LIGHT_CHANNELS: - va_arg(ap, uint8_t *); - break; - } - } -#ifdef USE_DEVICE_GROUPS_SEND - } -#endif // USE_DEVICE_GROUPS_SEND - } -#ifdef USE_DEVICE_GROUPS_SEND - if (!use_command) va_end(ap); -#else // USE_DEVICE_GROUPS_SEND - va_end(ap); -#endif // !USE_DEVICE_GROUPS_SEND - item_array[item_index] = 0; - // Rebuild the previous update message, removing any items whose values are included in this // new update. char * previous_message_ptr = message_ptr; while (item = *previous_message_ptr++) { // Search for this item in the new update. - for (item_index = 0; item_array[item_index]; item_index++) { - if (item_array[item_index] == item) break; + for (item_ptr = item_array; item_ptr->item; item_ptr++) { + if (item_ptr->item == item) break; } // If this item was found in the new update skip over it and it's value. - if (item_array[item_index]) { + if (item_ptr->item) { if (item <= DGR_ITEM_MAX_32BIT) { previous_message_ptr++; if (item > DGR_ITEM_MAX_8BIT) { @@ -330,8 +361,9 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes } } } - else if (item <= DGR_ITEM_MAX_STRING) - previous_message_ptr += *previous_message_ptr++; + else if (item <= DGR_ITEM_MAX_STRING) { + previous_message_ptr += strlen(previous_message_ptr) + 1; + } else { switch (item) { case DGR_ITEM_LIGHT_CHANNELS: @@ -355,7 +387,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes } } else if (item <= DGR_ITEM_MAX_STRING) { - *message_ptr++ = value = *previous_message_ptr++; + value = strlen(previous_message_ptr) + 1; memmove(message_ptr, previous_message_ptr, value); previous_message_ptr += value; message_ptr += value; @@ -378,58 +410,20 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes } // Itertate through the passed items adding them and their values to the message. -#ifdef USE_DEVICE_GROUPS_SEND - if (use_command) - value_ptr = XdrvMailbox.data; - else -#endif // USE_DEVICE_GROUPS_SEND - va_start(ap, message_type); -#ifdef USE_DEVICE_GROUPS_SEND - while (use_command ? (item = strtoul(value_ptr, &delim_ptr, 0)) : (item = va_arg(ap, int))) { -#else // !USE_DEVICE_GROUPS_SEND - while ((item = va_arg(ap, int))) { -#endif // !USE_DEVICE_GROUPS_SEND + for (item_ptr = item_array; (item = item_ptr->item); item_ptr++) { - // Find out if this item is shared with the group and add the item code to the message if yes. + // If this item is shared with the group add it to the message. shared = true; if (!device_group_index) shared = DeviceGroupItemShared(false, item); - if (shared) *message_ptr++ = item; + if (shared) { + *message_ptr++ = item; -#ifdef USE_DEVICE_GROUPS_SEND - // If we're processing a command, get a pointer to the value if one was specified. - if (use_command) value_ptr = (*delim_ptr == '=' ? delim_ptr + 1 : nullptr); -#endif // USE_DEVICE_GROUPS_SEND - - // For numeric items, get the specified value. - if (item <= DGR_ITEM_MAX_32BIT) { - -#ifdef USE_DEVICE_GROUPS_SEND - // If we're processing a command, get the final value after processing any specified - // operators. - if (use_command) { - value = 0; - if (value_ptr) { - oper = 0; - if (*value_ptr == '@') { - oper = value_ptr[1]; - value_ptr += 2; - } - value = strtoul(value_ptr, nullptr, 0); - if (oper) { - old_value = (item <= DGR_ITEM_MAX_8BIT ? device_group->values_8bit[item] : (item <= DGR_ITEM_MAX_16BIT ? device_group->values_16bit[item - DGR_ITEM_MAX_8BIT - 1] : device_group->values_32bit[item - DGR_ITEM_MAX_16BIT - 1])); - value = (oper == '+' ? old_value + value : (oper == '-' ? old_value - value : (oper == '^' ? old_value ^ (value ? value : 0xffffffff) : old_value))); - } - } - } - else -#endif // USE_DEVICE_GROUPS_SEND - value = va_arg(ap, int); - - // If the item is shared, add it to the message. - if (shared) { -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u"), item, value); -#endif // DEVICE_GROUPS_DEBUG + // For integer items, add the value to the message. + if (item <= DGR_ITEM_MAX_32BIT) { + value = item_ptr->value; +//#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(">%u=%u"), item, value); +//#endif // DEVICE_GROUPS_DEBUG *message_ptr++ = value & 0xff; if (item > DGR_ITEM_MAX_8BIT) { #ifdef USE_DEVICE_GROUPS_SEND @@ -469,77 +463,36 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes } #endif // USE_DEVICE_GROUPS_SEND } - } - // For string items, add the string to the message prefixed by the length. - else if (item <= DGR_ITEM_MAX_STRING) { -#ifdef USE_DEVICE_GROUPS_SEND - if (!use_command) -#endif // USE_DEVICE_GROUPS_SEND - value_ptr = va_arg(ap, char *); - if (shared) { - value = (value_ptr ? strlen((const char *)value_ptr) : 0); -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%s"), item, value_ptr); -#endif // DEVICE_GROUPS_DEBUG - *message_ptr++ = value; - memcpy(message_ptr, value_ptr, value); - message_ptr += value; + // For string items, add the null-terminated string to the message. + else if (item <= DGR_ITEM_MAX_STRING) { + if (item_ptr->value_ptr) { + value = strlen((const char *)item_ptr->value_ptr); + memcpy(message_ptr, item_ptr->value_ptr, value); + message_ptr += value; + } + *message_ptr++ = 0; +//#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(">%u='%s'"), item, item_ptr->value_ptr); +//#endif // DEVICE_GROUPS_DEBUG } - } - // For special items, handle them individually. - else { - switch (item) { - case DGR_ITEM_LIGHT_CHANNELS: -#ifdef USE_DEVICE_GROUPS_SEND - if (use_command) { - if (shared) { - for (int i = 0; i < 5; i++) { - value = 0; - if (value_ptr) { - value = strtoul(value_ptr, &value_ptr, 0); - value_ptr = (*value_ptr == ',' ? value_ptr + 1 : nullptr); - } - *message_ptr++ = value; - } + // For special items, handle them individually. + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + value_ptr = (char *)item_ptr->value_ptr; + for (int i = 0; i < 5; i++) { + *message_ptr++ = (value_ptr ? *value_ptr++ : 0); } - } - else { -#endif // USE_DEVICE_GROUPS_SEND - value_ptr = va_arg(ap, char *); - if (shared) { - memmove(message_ptr, value_ptr, 5); - message_ptr += 5; - } -#ifdef USE_DEVICE_GROUPS_SEND - } -#endif // USE_DEVICE_GROUPS_SEND -#ifdef DEVICE_GROUPS_DEBUG - if (shared) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u,%u,%u,%u,%u"), item, *(message_ptr - 5), *(message_ptr - 4), *(message_ptr - 3), *(message_ptr - 2), *(message_ptr - 1)); -#endif // DEVICE_GROUPS_DEBUG - break; +//#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(">%u=%u,%u,%u,%u,%u"), item, *(message_ptr - 5), *(message_ptr - 4), *(message_ptr - 3), *(message_ptr - 2), *(message_ptr - 1)); +//#endif // DEVICE_GROUPS_DEBUG + break; + } } } - -#ifdef USE_DEVICE_GROUPS_SEND - // If we're processing a command, advance to the next item. If there are no more, break out of - // the loop. - if (use_command) { - if (!*delim_ptr) break; - if (*delim_ptr == '=') { - delim_ptr = strchr(delim_ptr, ' '); - if (!delim_ptr) break; - } - value_ptr = delim_ptr + 1; - } -#endif // USE_DEVICE_GROUPS_SEND } -#ifdef USE_DEVICE_GROUPS_SEND - if (!use_command) va_end(ap); -#else // USE_DEVICE_GROUPS_SEND - va_end(ap); -#endif // !USE_DEVICE_GROUPS_SEND // Add the EOL item code and calculate the message length. *message_ptr++ = 0; @@ -715,6 +668,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) case DGR_ITEM_BRI_PRESET_HIGH: case DGR_ITEM_BRI_POWER_ON: case DGR_ITEM_POWER: + case DGR_ITEM_EVENT: case DGR_ITEM_LIGHT_CHANNELS: break; default: @@ -746,27 +700,27 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) } #endif // USE_DEVICE_GROUPS_SEND -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("= packet_length - (message_ptr - packet)) goto badmsg; // Malformed message -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(" 0) { strlcpy(Rules.event_data, XdrvMailbox.data, sizeof(Rules.event_data)); } - ResponseCmndDone(); + if (XdrvMailbox.command) ResponseCmndDone(); } void CmndVariable(void) From b116f070038968d40abb21fa579b326797391987 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Sat, 18 Apr 2020 23:42:51 -0500 Subject: [PATCH 53/70] Send Event command to device group --- tasmota/xdrv_10_rules.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index c7a83491f..36328cb98 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -1797,6 +1797,9 @@ void CmndEvent(void) { if (XdrvMailbox.data_len > 0) { strlcpy(Rules.event_data, XdrvMailbox.data, sizeof(Rules.event_data)); +#ifdef USE_DEVICE_GROUPS + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_EVENT, XdrvMailbox.data); +#endif // USE_DEVICE_GROUPS } if (XdrvMailbox.command) ResponseCmndDone(); } From 2c83dc7765dd9a70c6b64b74edac1bbef356a884 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Sun, 19 Apr 2020 00:36:26 -0500 Subject: [PATCH 54/70] Fix remote device group update index and power state, Ignore power buttonhold after tap --- tasmota/xdrv_35_pwm_dimmer.ino | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index 1f04db8c6..67890ac92 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -40,7 +40,7 @@ void (* const PWMDimmerCommand[])(void) PROGMEM = { #ifdef USE_PWM_DIMMER_REMOTE struct remote_pwm_dimmer { - power_t power; + bool power_on; uint8_t bri_power_on; uint8_t bri_preset_low; uint8_t bri_preset_high; @@ -178,7 +178,7 @@ void PWMDimmerHandleDevGroupItem(void) uint8_t device_group_index = *(uint8_t *)XdrvMailbox.topic; if (device_group_index > remote_pwm_dimmer_count) return; bool device_is_local = device_groups[device_group_index].local; - struct remote_pwm_dimmer * remote_pwm_dimmer = &remote_pwm_dimmers[device_group_index]; + struct remote_pwm_dimmer * remote_pwm_dimmer = &remote_pwm_dimmers[device_group_index - 1]; #else // USE_PWM_DIMMER_REMOTE if (*(uint8_t *)XdrvMailbox.topic) return; #endif // !USE_PWM_DIMMER_REMOTE @@ -190,7 +190,7 @@ void PWMDimmerHandleDevGroupItem(void) break; case DGR_ITEM_POWER: if (!device_is_local) { - remote_pwm_dimmer->power = value; + remote_pwm_dimmer->power_on = value & 1; remote_pwm_dimmer->power_button_increases_bri = (remote_pwm_dimmer->bri < 128); } break; @@ -286,7 +286,7 @@ void PWMDimmerHandleButton(void) // Initialize some variables. #ifdef USE_PWM_DIMMER_REMOTE - bool power_is_on = (!active_device_is_local ? active_remote_pwm_dimmer->power : power); + bool power_is_on = (!active_device_is_local ? active_remote_pwm_dimmer->power_on : power); bool is_power_button = (button_index == power_button_index); #else // USE_PWM_DIMMER_REMOTE bool power_is_on = power; @@ -344,8 +344,9 @@ void PWMDimmerHandleButton(void) // If this is about the power button, ... if (is_power_button) { - // If no other buttons are pressed, ... - if (buttons_pressed == 1) { + // If no other buttons are pressed and the up or down button was tapped while holding the + // power button before this, ... + if (buttons_pressed == 1 && !tap_count) { // If the power is on, adjust the brightness. Set the direction based on the current // direction for the device and then invert the direction when the power button is @@ -628,8 +629,8 @@ void PWMDimmerHandleButton(void) #ifdef USE_DEVICE_GROUPS #ifdef USE_PWM_DIMMER_REMOTE if (!active_device_is_local) { - active_remote_pwm_dimmer->power ^= 1; - new_power = active_remote_pwm_dimmer->power; + active_remote_pwm_dimmer->power_on ^= 1; + new_power = active_remote_pwm_dimmer->power_on; } else { #endif // USE_PWM_DIMMER_REMOTE From 0f3619238fc3fbba8d76178a7e487fd872aa77da Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 19 Apr 2020 13:08:04 +0200 Subject: [PATCH 55/70] Add ESP32 bootloop control --- .../src/esp8266toEsp32.cpp | 30 +++++++++++++++++-- tasmota/settings.h | 10 ++++--- tasmota/settings.ino | 16 +++++----- tasmota/support.ino | 2 -- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp index 6635f6d4d..971cb2ec4 100644 --- a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp +++ b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp @@ -65,14 +65,40 @@ uint32_t ESP_getBootVersion(void) return 1; } +// ESP32 RTC memory is kept ONLY on deep_sleep wake. Any other restart will erase RTC memory +// Current solution is using NVS hopig it survives many writes ;-) bool ESP_rtcUserMemoryWrite(uint32_t offset, uint32_t *data, size_t size) { - return false; + char sName[16]; + snprintf_P(sName, sizeof(sName), PSTR("rtc%d"), offset); + + nvs_handle handle; + noInterrupts(); + nvs_open("tasrtc", NVS_READWRITE, &handle); + nvs_set_blob(handle, sName, data, size); + nvs_commit(handle); + nvs_close(handle); + interrupts(); + + return true; } +// ESP32 RTC memory is kept ONLY on deep_sleep wake. Any other restart will erase RTC memory +// Current solution is using NVS hopig it survives many writes ;-) bool ESP_rtcUserMemoryRead(uint32_t offset, uint32_t *data, size_t size) { - return false; + char sName[16]; + snprintf_P(sName, sizeof(sName), PSTR("rtc%d"), offset); + + nvs_handle handle; + noInterrupts(); + nvs_open("tasrtc", NVS_READONLY, &handle); + size_t tsize = size; + nvs_get_blob(handle, sName, data, &tsize); + nvs_close(handle); + interrupts(); + + return true; } void ESP_reset() diff --git a/tasmota/settings.h b/tasmota/settings.h index e1b63beff..e5b1c9f7a 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -545,13 +545,14 @@ struct SYSCFG { uint32_t cfg_crc32; // FFC } Settings; -struct RTCRBT { +typedef struct { uint16_t valid; // 280 (RTC memory offset 100 - sizeof(RTCRBT)) uint8_t fast_reboot_count; // 282 uint8_t free_003[1]; // 283 -} RtcReboot; +} TRtcReboot; +TRtcReboot RtcReboot; -struct RTCMEM { +typedef struct { uint16_t valid; // 290 (RTC memory offset 100) uint8_t oswatch_blocked_loop; // 292 uint8_t ota_loader; // 293 @@ -567,7 +568,8 @@ struct RTCMEM { uint8_t free_022[22]; // 2D6 // 2EC - 2FF free locations -} RtcSettings; +} TRtcSettings; +TRtcSettings RtcSettings; struct TIME_T { uint8_t second; diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 1769b676d..62fda63d8 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -30,7 +30,7 @@ uint32_t GetRtcSettingsCrc(void) uint32_t crc = 0; uint8_t *bytes = (uint8_t*)&RtcSettings; - for (uint32_t i = 0; i < sizeof(RTCMEM); i++) { + for (uint32_t i = 0; i < sizeof(RtcSettings); i++) { crc += bytes[i]*(i+1); } return crc; @@ -40,16 +40,16 @@ void RtcSettingsSave(void) { if (GetRtcSettingsCrc() != rtc_settings_crc) { RtcSettings.valid = RTC_MEM_VALID; - ESP_rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); + ESP_rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RtcSettings)); rtc_settings_crc = GetRtcSettingsCrc(); } } void RtcSettingsLoad(void) { - ESP_rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); // 0x290 + ESP_rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RtcSettings)); // 0x290 if (RtcSettings.valid != RTC_MEM_VALID) { - memset(&RtcSettings, 0, sizeof(RTCMEM)); + memset(&RtcSettings, 0, sizeof(RtcSettings)); RtcSettings.valid = RTC_MEM_VALID; RtcSettings.energy_kWhtoday = Settings.energy_kWhtoday; RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal; @@ -77,7 +77,7 @@ uint32_t GetRtcRebootCrc(void) uint32_t crc = 0; uint8_t *bytes = (uint8_t*)&RtcReboot; - for (uint32_t i = 0; i < sizeof(RTCRBT); i++) { + for (uint32_t i = 0; i < sizeof(RtcReboot); i++) { crc += bytes[i]*(i+1); } return crc; @@ -87,7 +87,7 @@ void RtcRebootSave(void) { if (GetRtcRebootCrc() != rtc_reboot_crc) { RtcReboot.valid = RTC_MEM_VALID; - ESP_rtcUserMemoryWrite(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); + ESP_rtcUserMemoryWrite(100 - sizeof(RtcReboot), (uint32_t*)&RtcReboot, sizeof(RtcReboot)); rtc_reboot_crc = GetRtcRebootCrc(); } } @@ -100,9 +100,9 @@ void RtcRebootReset(void) void RtcRebootLoad(void) { - ESP_rtcUserMemoryRead(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); // 0x280 + ESP_rtcUserMemoryRead(100 - sizeof(RtcReboot), (uint32_t*)&RtcReboot, sizeof(RtcReboot)); // 0x280 if (RtcReboot.valid != RTC_MEM_VALID) { - memset(&RtcReboot, 0, sizeof(RTCRBT)); + memset(&RtcReboot, 0, sizeof(RtcReboot)); RtcReboot.valid = RTC_MEM_VALID; // RtcReboot.fast_reboot_count = 0; // Explicit by memset RtcRebootSave(); diff --git a/tasmota/support.ino b/tasmota/support.ino index 4b9961e94..5e7764bf9 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1208,14 +1208,12 @@ uint8_t ValidPin(uint32_t pin, uint32_t gpio) return GPIO_NONE; // Disable flash pins GPIO6, GPIO7, GPIO8 and GPIO11 } -#ifdef ESP8266 // if (!is_8285 && !Settings.flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's if ((WEMOS == Settings.module) && !Settings.flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's if ((pin == 9) || (pin == 10)) { return GPIO_NONE; // Disable possible flash GPIO9 and GPIO10 } } -#endif // ESP8266 return gpio; } From eab612871c3c7f693a3a1c170245da31f4a54581 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 19 Apr 2020 14:18:12 +0200 Subject: [PATCH 56/70] Fix ESP32 bootloop control using RTC memory --- .../src/esp8266toEsp32.cpp | 36 ------------------- .../src/esp8266toEsp32.h | 2 -- tasmota/settings.h | 6 ++++ tasmota/settings.ino | 24 ++++++++++--- tasmota/tasmota_compat.h | 2 -- 5 files changed, 26 insertions(+), 44 deletions(-) diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp index 971cb2ec4..bfbf26419 100644 --- a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp +++ b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp @@ -65,42 +65,6 @@ uint32_t ESP_getBootVersion(void) return 1; } -// ESP32 RTC memory is kept ONLY on deep_sleep wake. Any other restart will erase RTC memory -// Current solution is using NVS hopig it survives many writes ;-) -bool ESP_rtcUserMemoryWrite(uint32_t offset, uint32_t *data, size_t size) -{ - char sName[16]; - snprintf_P(sName, sizeof(sName), PSTR("rtc%d"), offset); - - nvs_handle handle; - noInterrupts(); - nvs_open("tasrtc", NVS_READWRITE, &handle); - nvs_set_blob(handle, sName, data, size); - nvs_commit(handle); - nvs_close(handle); - interrupts(); - - return true; -} - -// ESP32 RTC memory is kept ONLY on deep_sleep wake. Any other restart will erase RTC memory -// Current solution is using NVS hopig it survives many writes ;-) -bool ESP_rtcUserMemoryRead(uint32_t offset, uint32_t *data, size_t size) -{ - char sName[16]; - snprintf_P(sName, sizeof(sName), PSTR("rtc%d"), offset); - - nvs_handle handle; - noInterrupts(); - nvs_open("tasrtc", NVS_READONLY, &handle); - size_t tsize = size; - nvs_get_blob(handle, sName, data, &tsize); - nvs_close(handle); - interrupts(); - - return true; -} - void ESP_reset() { ESP.restart(); diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h index 276772b95..3af2c12c5 100644 --- a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h +++ b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h @@ -36,8 +36,6 @@ String ESP_getResetReason(void); uint32_t ESP_ResetInfoReason(void); uint32_t ESP_getBootVersion(void); -bool ESP_rtcUserMemoryWrite(uint32_t offset, uint32_t *data, size_t size); -bool ESP_rtcUserMemoryRead(uint32_t offset, uint32_t *data, size_t size); void ESP_reset(); uint32_t ESP_getFlashChipId(); uint32_t ESP_getChipId(); diff --git a/tasmota/settings.h b/tasmota/settings.h index e5b1c9f7a..5b862280e 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -551,6 +551,9 @@ typedef struct { uint8_t free_003[1]; // 283 } TRtcReboot; TRtcReboot RtcReboot; +#ifdef ESP32 +RTC_NOINIT_ATTR TRtcReboot RtcDataReboot; +#endif typedef struct { uint16_t valid; // 290 (RTC memory offset 100) @@ -570,6 +573,9 @@ typedef struct { // 2EC - 2FF free locations } TRtcSettings; TRtcSettings RtcSettings; +#ifdef ESP32 +RTC_NOINIT_ATTR TRtcSettings RtcDataSettings; +#endif struct TIME_T { uint8_t second; diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 62fda63d8..cff437d67 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -40,14 +40,22 @@ void RtcSettingsSave(void) { if (GetRtcSettingsCrc() != rtc_settings_crc) { RtcSettings.valid = RTC_MEM_VALID; - ESP_rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RtcSettings)); +#ifdef ESP8266 + ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RtcSettings)); +#else + RtcDataSettings = RtcSettings; +#endif rtc_settings_crc = GetRtcSettingsCrc(); } } void RtcSettingsLoad(void) { - ESP_rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RtcSettings)); // 0x290 +#ifdef ESP8266 + ESP.rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RtcSettings)); // 0x290 +#else + RtcSettings = RtcDataSettings; +#endif if (RtcSettings.valid != RTC_MEM_VALID) { memset(&RtcSettings, 0, sizeof(RtcSettings)); RtcSettings.valid = RTC_MEM_VALID; @@ -87,7 +95,11 @@ void RtcRebootSave(void) { if (GetRtcRebootCrc() != rtc_reboot_crc) { RtcReboot.valid = RTC_MEM_VALID; - ESP_rtcUserMemoryWrite(100 - sizeof(RtcReboot), (uint32_t*)&RtcReboot, sizeof(RtcReboot)); +#ifdef ESP8266 + ESP.rtcUserMemoryWrite(100 - sizeof(RtcReboot), (uint32_t*)&RtcReboot, sizeof(RtcReboot)); +#else + RtcDataReboot = RtcReboot; +#endif rtc_reboot_crc = GetRtcRebootCrc(); } } @@ -100,7 +112,11 @@ void RtcRebootReset(void) void RtcRebootLoad(void) { - ESP_rtcUserMemoryRead(100 - sizeof(RtcReboot), (uint32_t*)&RtcReboot, sizeof(RtcReboot)); // 0x280 +#ifdef ESP8266 + ESP.rtcUserMemoryRead(100 - sizeof(RtcReboot), (uint32_t*)&RtcReboot, sizeof(RtcReboot)); // 0x280 +#else + RtcReboot = RtcDataReboot; +#endif if (RtcReboot.valid != RTC_MEM_VALID) { memset(&RtcReboot, 0, sizeof(RtcReboot)); RtcReboot.valid = RTC_MEM_VALID; diff --git a/tasmota/tasmota_compat.h b/tasmota/tasmota_compat.h index 839f5cef8..7ca5615b1 100644 --- a/tasmota/tasmota_compat.h +++ b/tasmota/tasmota_compat.h @@ -11,8 +11,6 @@ #ifdef ESP8266 // ESP8266 #define PACKED -#define ESP_rtcUserMemoryWrite(offset, data, size) ESP.rtcUserMemoryWrite(offset, data, size) -#define ESP_rtcUserMemoryRead(offset, data, size) ESP.rtcUserMemoryRead(offset, data, size) #define ESP_getResetReason() ESP.getResetReason() #define ESP_reset() ESP.reset() #define ESP_getBootVersion() ESP.getBootVersion() From f4ea26749c375fea612be71ff8ce646e4d28ee84 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Sun, 19 Apr 2020 08:19:05 -0500 Subject: [PATCH 57/70] Fix fixed color bug introduced by pallete code --- tasmota/xdrv_04_light.ino | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 1c5751829..70d5b06d5 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2384,9 +2384,6 @@ bool LightColorEntry(char *buffer, uint32_t buffer_length) } } else { value = atoi(buffer); -#ifdef USE_LIGHT_PALETTE - value--; -#endif // USE_LIGHT_PALETTE } #ifdef USE_LIGHT_PALETTE if (Light.palette_count) value = value % Light.palette_count; @@ -2417,6 +2414,7 @@ bool LightColorEntry(char *buffer, uint32_t buffer_length) } #ifdef USE_LIGHT_PALETTE else if (Light.palette_count) { + value--; Light.wheel = value; memcpy_P(&Light.entry_color, &Light.palette[value * LST_MAX], LST_MAX); entry_type = 1; // Hexadecimal From c37dde93c244d7e4e86189fde13d4c56f34863b1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 19 Apr 2020 15:36:04 +0200 Subject: [PATCH 58/70] Add ESP32 QuickPowerCycle control --- .../src/esp8266toEsp32.cpp | 9 -- .../src/esp8266toEsp32.h | 3 - tasmota/settings.h | 2 +- tasmota/settings.ino | 50 +++++--- tasmota/support_esp32.ino | 116 ++++++++++-------- tasmota/tasmota_compat.h | 5 - tasmota/xdrv_99_debug.ino | 6 +- 7 files changed, 100 insertions(+), 91 deletions(-) diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp index bfbf26419..c25845922 100644 --- a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp +++ b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp @@ -99,12 +99,3 @@ uint32_t ESP_getSketchSize(void) } return sketchsize; } - -#include "soc/soc.h" -#include "soc/rtc_cntl_reg.h" - -void DisableBrownout(void) -{ - // https://github.com/espressif/arduino-esp32/issues/863#issuecomment-347179737 - WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // Disable brownout detector -} diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h index 3af2c12c5..92184d4a7 100644 --- a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h +++ b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h @@ -31,8 +31,6 @@ // // ESP32 // -#define ESP_flashReadHeader(offset, data, size) ESP32_flashRead(offset, data, size) -#define ESP_flashRead(offset, data, size) ESP32_flashRead(offset, data, size) String ESP_getResetReason(void); uint32_t ESP_ResetInfoReason(void); uint32_t ESP_getBootVersion(void); @@ -41,7 +39,6 @@ uint32_t ESP_getFlashChipId(); uint32_t ESP_getChipId(); String String_ESP_getChipId(); uint32_t ESP_getSketchSize(); -void DisableBrownout(void); // Analog inline void analogWrite(uint8_t pin, int val) diff --git a/tasmota/settings.h b/tasmota/settings.h index 5b862280e..7ea3b5e3e 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -253,7 +253,7 @@ typedef struct { const uint32_t settings_text_size = 699; // Settings.text_pool[size] = Settings.display_model (2D2) - Settings.text_pool (017) const uint8_t MAX_TUYA_FUNCTIONS = 16; -struct SYSCFG { +struct { uint16_t cfg_holder; // 000 v6 header uint16_t cfg_size; // 002 unsigned long save_flag; // 004 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index cff437d67..c6cc355b4 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -305,7 +305,7 @@ uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size) uint16_t GetSettingsCrc(void) { // Fix miscalculation if previous Settings was 3584 and current Settings is 4096 between 0x06060007 and 0x0606000A - uint32_t size = ((Settings.version < 0x06060007) || (Settings.version > 0x0606000A)) ? 3584 : sizeof(SYSCFG); + uint32_t size = ((Settings.version < 0x06060007) || (Settings.version > 0x0606000A)) ? 3584 : sizeof(Settings); return GetCfgCrc16((uint8_t*)&Settings, size); } @@ -325,7 +325,7 @@ uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size) uint32_t GetSettingsCrc32(void) { - return GetCfgCrc32((uint8_t*)&Settings, sizeof(SYSCFG) -4); // Skip crc32 + return GetCfgCrc32((uint8_t*)&Settings, sizeof(Settings) -4); // Skip crc32 } void SettingsSaveAll(void) @@ -351,7 +351,11 @@ void UpdateQuickPowerCycle(bool update) uint32_t pc_register; uint32_t pc_location = SETTINGS_LOCATION - CFG_ROTATES; +#ifdef ESP8266 ESP.flashRead(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); +#else + QPCRead(&pc_register, sizeof(pc_register)); +#endif if (update && ((pc_register & 0xFFFFFFF0) == 0xFFA55AB0)) { uint32_t counter = ((pc_register & 0xF) << 1) & 0xF; if (0 == counter) { // 4 power cycles in a row @@ -359,16 +363,24 @@ void UpdateQuickPowerCycle(bool update) EspRestart(); // And restart } else { pc_register = 0xFFA55AB0 | counter; +#ifdef ESP8266 ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); +#else + QPCWrite(&pc_register, sizeof(pc_register)); +#endif AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Flag %02X"), counter); } } else if (pc_register != 0xFFA55ABF) { pc_register = 0xFFA55ABF; +#ifdef ESP8266 // Assume flash is default all ones and setting a bit to zero does not need an erase if (ESP.flashEraseSector(pc_location)) { ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); } +#else + QPCWrite(&pc_register, sizeof(pc_register)); +#endif AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Reset")); } } @@ -501,13 +513,13 @@ void SettingsSave(uint8_t rotate) } else { Settings.cfg_timestamp++; } - Settings.cfg_size = sizeof(SYSCFG); + Settings.cfg_size = sizeof(Settings); Settings.cfg_crc = GetSettingsCrc(); // Keep for backward compatibility in case of fall-back just after upgrade Settings.cfg_crc32 = GetSettingsCrc32(); #ifdef ESP8266 if (ESP.flashEraseSector(settings_location)) { - ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); } if (!stop_flash_rotate && rotate) { @@ -516,12 +528,12 @@ void SettingsSave(uint8_t rotate) delay(1); } } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(Settings)); #else // ESP32 - SettingsSaveMain(&Settings, sizeof(SYSCFG)); + SettingsWrite(&Settings, sizeof(Settings)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "Saved, " D_COUNT " %d, " D_BYTES " %d"), Settings.save_flag, sizeof(Settings)); #endif // ESP8266 - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG)); - settings_crc32 = Settings.cfg_crc32; } #endif // FIRMWARE_MINIMAL @@ -530,8 +542,9 @@ void SettingsSave(uint8_t rotate) void SettingsLoad(void) { +#ifdef ESP8266 // Load configuration from eeprom or one of 7 slots below if first valid load does not stop_flash_rotate - struct SYSCFGH { + struct { uint16_t cfg_holder; // 000 uint16_t cfg_size; // 002 unsigned long save_flag; // 004 @@ -543,7 +556,7 @@ void SettingsLoad(void) uint16_t cfg_holder = 0; for (uint32_t i = 0; i < CFG_ROTATES; i++) { flash_location--; - ESP_flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); bool valid = false; if (Settings.version > 0x06000000) { bool almost_valid = (Settings.cfg_crc32 == GetSettingsCrc32()); @@ -554,7 +567,7 @@ void SettingsLoad(void) if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } // At FB always active cfg_holder valid = (cfg_holder == Settings.cfg_holder); } else { - ESP_flashReadHeader((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); + ESP.flashRead((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(_SettingsH)); valid = (Settings.cfg_holder == _SettingsH.cfg_holder); } if (valid) { @@ -566,13 +579,16 @@ void SettingsLoad(void) } } } - delay(1); } if (settings_location > 0) { - ESP_flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); } +#else // ESP32 + SettingsRead(&Settings, sizeof(Settings)); + AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG "Loaded, " D_COUNT " %lu"), Settings.save_flag); +#endif // ESP8266 - ESP32 #ifndef FIRMWARE_MINIMAL if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { // Init defaults if cfg_holder differs from user settings in my_user_config.h @@ -683,10 +699,10 @@ void SettingsDefault(void) void SettingsDefaultSet1(void) { - memset(&Settings, 0x00, sizeof(SYSCFG)); + memset(&Settings, 0x00, sizeof(Settings)); Settings.cfg_holder = (uint16_t)CFG_HOLDER; - Settings.cfg_size = sizeof(SYSCFG); + Settings.cfg_size = sizeof(Settings); // Settings.save_flag = 0; Settings.version = VERSION; // Settings.bootcount = 0; @@ -695,7 +711,7 @@ void SettingsDefaultSet1(void) void SettingsDefaultSet2(void) { - memset((char*)&Settings +16, 0x00, sizeof(SYSCFG) -16); + memset((char*)&Settings +16, 0x00, sizeof(Settings) -16); Settings.flag.stop_flash_rotate = APP_FLASH_CYCLE; Settings.flag.global_state = APP_ENABLE_LEDLINK; @@ -1064,7 +1080,7 @@ void SettingsDelta(void) #ifdef ESP8266 if (Settings.version < 0x06000000) { - Settings.cfg_size = sizeof(SYSCFG); + Settings.cfg_size = sizeof(Settings); Settings.cfg_crc = GetSettingsCrc(); } if (Settings.version < 0x06000002) { @@ -1148,7 +1164,7 @@ void SettingsDelta(void) Settings.param[P_OVER_TEMP] = ENERGY_OVERTEMP; } if (Settings.version < 0x06060007) { - memset((char*)&Settings +0xE00, 0x00, sizeof(SYSCFG) -0xE00); + memset((char*)&Settings +0xE00, 0x00, sizeof(Settings) -0xE00); } if (Settings.version < 0x06060008) { // Move current tuya dimmer range to the new param. diff --git a/tasmota/support_esp32.ino b/tasmota/support_esp32.ino index 1e2a4e0ca..d9f6ab390 100644 --- a/tasmota/support_esp32.ino +++ b/tasmota/support_esp32.ino @@ -22,6 +22,39 @@ #include #include +void NvmLoad(const char *sNvsName, const char *sName, void *pSettings, unsigned nSettingsLen) +{ + nvs_handle handle; + noInterrupts(); + nvs_open(sNvsName, NVS_READONLY, &handle); + size_t size = nSettingsLen; + nvs_get_blob(handle, sName, pSettings, &size); + nvs_close(handle); + interrupts(); +} + +void NvmSave(const char *sNvsName, const char *sName, const void *pSettings, unsigned nSettingsLen) +{ + nvs_handle handle; + noInterrupts(); + nvs_open(sNvsName, NVS_READWRITE, &handle); + nvs_set_blob(handle, sName, pSettings, nSettingsLen); + nvs_commit(handle); + nvs_close(handle); + interrupts(); +} + +void NvmErase(const char *sNvsName) +{ + nvs_handle handle; + noInterrupts(); + nvs_open(sNvsName, NVS_READWRITE, &handle); + nvs_erase_all(handle); + nvs_commit(handle); + nvs_close(handle); + interrupts(); +} + void SettingsErase(uint8_t type) { if (1 == type) // SDK parameter area @@ -34,75 +67,39 @@ void SettingsErase(uint8_t type) { } - noInterrupts(); - nvs_handle handle; - nvs_open("main", NVS_READWRITE, &handle); - nvs_erase_all(handle); - nvs_commit(handle); - nvs_close(handle); - interrupts(); + NvmErase("main"); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " t=%d"), type); } -void SettingsLoad(const char *sNvsName, const char *sName, void *pSettings, unsigned nSettingsLen) +void SettingsRead(void *data, size_t size) { - noInterrupts(); - nvs_handle handle; - size_t size; - nvs_open(sNvsName, NVS_READONLY, &handle); - size = nSettingsLen; - nvs_get_blob(handle, sName, pSettings, &size); - nvs_close(handle); - interrupts(); + NvmLoad("main", "Settings", data, size); } -void SettingsSave(const char *sNvsName, const char *sName, const void *pSettings, unsigned nSettingsLen) +void SettingsWrite(const void *pSettings, unsigned nSettingsLen) { - nvs_handle handle; - noInterrupts(); - nvs_open(sNvsName, NVS_READWRITE, &handle); - nvs_set_blob(handle, sName, pSettings, nSettingsLen); - nvs_commit(handle); - nvs_close(handle); - interrupts(); + NvmSave("main", "Settings", pSettings, nSettingsLen); } -void ESP32_flashRead(uint32_t offset, uint32_t *data, size_t size) -{ - SettingsLoad("main", "Settings", data, size); -} - -void ESP32_flashReadHeader(uint32_t offset, uint32_t *data, size_t size) -{ - SettingsLoad("main", "SettingsH", data, size); -} - -void SettingsSaveMain(const void *pSettings, unsigned nSettingsLen) -{ - SettingsSave("main", "Settings", pSettings, nSettingsLen); -} - -/* -void SettingsLoadMain(void *pSettings, unsigned nSettingsLen) -{ - SettingsLoad("main", "Settings", pSettings, nSettingsLen); -} - -void SettingsLoadMainH(void *pSettingsH, unsigned nSettingsLenH) -{ - SettingsLoad("main", "SettingsH", pSettingsH, nSettingsLenH); -} -*/ - void SettingsLoadUpg(void *pSettings, unsigned nSettingsLen) { - SettingsLoad("upg", "Settings", pSettings, nSettingsLen); + NvmLoad("upg", "Settings", pSettings, nSettingsLen); } void SettingsLoadUpgH(void *pSettings, unsigned nSettingsLen) { - SettingsLoad("upg", "SettingsH", pSettings, nSettingsLen); + NvmLoad("upg", "SettingsH", pSettings, nSettingsLen); +} + +void QPCRead(void *pSettings, unsigned nSettingsLen) +{ + NvmLoad("qpc", "pcreg", pSettings, nSettingsLen); +} + +void QPCWrite(const void *pSettings, unsigned nSettingsLen) +{ + NvmSave("qpc", "pcreg", pSettings, nSettingsLen); } // @@ -174,4 +171,17 @@ void CmndBlockedLoop(void) */ } +// +// ESP32 specific +// + +#include "soc/soc.h" +#include "soc/rtc_cntl_reg.h" + +void DisableBrownout(void) +{ + // https://github.com/espressif/arduino-esp32/issues/863#issuecomment-347179737 + WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // Disable brownout detector +} + #endif // ESP32 diff --git a/tasmota/tasmota_compat.h b/tasmota/tasmota_compat.h index 7ca5615b1..5119c9021 100644 --- a/tasmota/tasmota_compat.h +++ b/tasmota/tasmota_compat.h @@ -18,11 +18,6 @@ #define ESP_getSketchSize() ESP.getSketchSize() #define ESP_getChipId() ESP.getChipId() // -// we need different ESP_flashRead for ESP32 -// -#define ESP_flashReadHeader(offset, data, size) ESP.flashRead(offset, data, size) -#define ESP_flashRead(offset, data, size) ESP.flashRead(offset, data, size) -// // UDP #define PortUdp_write(p,n) PortUdp.write(p, n) // diff --git a/tasmota/xdrv_99_debug.ino b/tasmota/xdrv_99_debug.ino index feb04cabd..eeb4e7ca1 100644 --- a/tasmota/xdrv_99_debug.ino +++ b/tasmota/xdrv_99_debug.ino @@ -312,7 +312,7 @@ void DebugCfgDump(char* parms) char *p; uint8_t *buffer = (uint8_t *) &Settings; - maxrow = ((sizeof(SYSCFG)+CFG_COLS)/CFG_COLS); + maxrow = ((sizeof(Settings)+CFG_COLS)/CFG_COLS); uint16_t srow = strtol(parms, &p, 16) / CFG_COLS; uint16_t mrow = strtol(p, &p, 10); @@ -356,7 +356,7 @@ void DebugCfgPeek(char* parms) char *p; uint16_t address = strtol(parms, &p, 16); - if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; + if (address > sizeof(Settings)) address = sizeof(Settings) -4; address = (address >> 2) << 2; uint8_t *buffer = (uint8_t *) &Settings; @@ -381,7 +381,7 @@ void DebugCfgPoke(char* parms) char *p; uint16_t address = strtol(parms, &p, 16); - if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; + if (address > sizeof(Settings)) address = sizeof(Settings) -4; address = (address >> 2) << 2; uint32_t data = strtol(p, &p, 16); From 3bfb62bc0bdd4a23dfc50fe54e4f1fc67c001081 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 19 Apr 2020 16:38:49 +0200 Subject: [PATCH 59/70] Add platformio_tasmota_cenv.ini to .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index caa3d240b..5baf6b919 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ tasmota*.bin tasmota*.bin.gz tasmota*.map platformio_override.ini +platformio_tasmota_cenv.ini ## Visual Studio Code specific ###### .vscode @@ -24,4 +25,4 @@ platformio_override.ini .vscode/c_cpp_properties.json .vscode/launch.json *.bak -*.code-workspace \ No newline at end of file +*.code-workspace From 19796a7f97c296b18bdb827a53746997e96b64c5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 19 Apr 2020 16:58:13 +0200 Subject: [PATCH 60/70] Refactor ESP32 code --- .../src/esp8266toEsp32.cpp | 77 ------------ .../src/esp8266toEsp32.h | 12 -- tasmota/support.ino | 4 - tasmota/support_command.ino | 38 ++++-- tasmota/support_esp32.ino | 117 ++++++++++++++++-- tasmota/support_wifi.ino | 3 +- tasmota/tasmota_compat.h | 8 -- tasmota/xdrv_01_webserver.ino | 8 +- 8 files changed, 145 insertions(+), 122 deletions(-) diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp index c25845922..e15770022 100644 --- a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp +++ b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp @@ -22,80 +22,3 @@ #include "esp8266toEsp32.h" // ESP Stuff - -String ESP32GetResetReason(uint32_t cpu_no) -{ - // tools\sdk\include\esp32\rom\rtc.h - switch (rtc_get_reset_reason( (RESET_REASON) cpu_no)) { - case POWERON_RESET : return F("Vbat power on reset"); // 1 - case SW_RESET : return F("Software reset digital core"); // 3 - case OWDT_RESET : return F("Legacy watch dog reset digital core"); // 4 - case DEEPSLEEP_RESET : return F("Deep Sleep reset digital core"); // 5 - case SDIO_RESET : return F("Reset by SLC module, reset digital core"); // 6 - case TG0WDT_SYS_RESET : return F("Timer Group0 Watch dog reset digital core"); // 7 - case TG1WDT_SYS_RESET : return F("Timer Group1 Watch dog reset digital core"); // 8 - case RTCWDT_SYS_RESET : return F("RTC Watch dog Reset digital core"); // 9 - case INTRUSION_RESET : return F("Instrusion tested to reset CPU"); // 10 - case TGWDT_CPU_RESET : return F("Time Group reset CPU"); // 11 - case SW_CPU_RESET : return F("Software reset CPU"); // 12 - case RTCWDT_CPU_RESET : return F("RTC Watch dog Reset CPU"); // 13 - case EXT_CPU_RESET : return F("or APP CPU, reseted by PRO CPU"); // 14 - case RTCWDT_BROWN_OUT_RESET : return F("Reset when the vdd voltage is not stable"); // 15 - case RTCWDT_RTC_RESET : return F("RTC Watch dog reset digital core and rtc module"); // 16 - default : return F("NO_MEAN"); // 0 - } -} - -String ESP_getResetReason(void) -{ - return ESP32GetResetReason(0); // CPU 0 -} - -uint32_t ESP_ResetInfoReason(void) -{ - RESET_REASON reason = rtc_get_reset_reason(0); - if (POWERON_RESET == reason) { return REASON_DEFAULT_RST; } - if (SW_CPU_RESET == reason) { return REASON_SOFT_RESTART; } - if (DEEPSLEEP_RESET == reason) { return REASON_DEEP_SLEEP_AWAKE; } - if (SW_RESET == reason) { return REASON_EXT_SYS_RST; } -} - -uint32_t ESP_getBootVersion(void) -{ - return 1; -} - -void ESP_reset() -{ - ESP.restart(); -} - -uint32_t ESP_getFlashChipId() -{ - return 0; -} - -uint32_t ESP_getChipId() -{ - uint32_t id = 0; - for (uint32_t i = 0; i < 17; i = i +8) { - id |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i; - } - return id; -} - -String String_ESP_getChipId() -{ - uint64_t mac = ESP.getEfuseMac(); - return String(uint32_t(mac >> 32)) + String(uint32_t(mac)); -} - -uint32_t ESP_getSketchSize(void) -{ - static uint32_t sketchsize = 0; - - if (!sketchsize) { - sketchsize = ESP.getSketchSize(); // This takes almost 2 seconds on an ESP32 - } - return sketchsize; -} diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h index 92184d4a7..6023507ae 100644 --- a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h +++ b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h @@ -28,18 +28,6 @@ #include -// -// ESP32 -// -String ESP_getResetReason(void); -uint32_t ESP_ResetInfoReason(void); -uint32_t ESP_getBootVersion(void); -void ESP_reset(); -uint32_t ESP_getFlashChipId(); -uint32_t ESP_getChipId(); -String String_ESP_getChipId(); -uint32_t ESP_getSketchSize(); - // Analog inline void analogWrite(uint8_t pin, int val) { diff --git a/tasmota/support.ino b/tasmota/support.ino index 5e7764bf9..0afbe811f 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -99,11 +99,7 @@ uint32_t ResetReason(void) REASON_DEEP_SLEEP_AWAKE = 5, // "Deep-Sleep Wake" wake up from deep-sleep REASON_EXT_SYS_RST = 6 // "External System" external system reset */ -#ifdef ESP8266 - return resetInfo.reason; -#else return ESP_ResetInfoReason(); -#endif } String GetResetReason(void) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 18ead323a..b3beea79d 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -413,20 +413,34 @@ void CmndStatus(void) if ((0 == payload) || (1 == payload)) { Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_SERIALCONFIG "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" - D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"BCResetTime\":\"%s\",\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), + D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"BCResetTime\":\"%s\",\"" D_JSON_SAVECOUNT "\":%d" +#ifdef ESP8266 + ",\"" D_JSON_SAVEADDRESS "\":\"%X\"" +#endif + "}}"), Settings.baudrate * 300, GetSerialConfig().c_str(), SettingsText(SET_MQTT_GRP_TOPIC), SettingsText(SET_OTAURL), GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, - Settings.cfg_holder, Settings.bootcount, GetDateAndTime(DT_BOOTCOUNT).c_str(), Settings.save_flag, GetSettingsAddress()); + Settings.cfg_holder, Settings.bootcount, GetDateAndTime(DT_BOOTCOUNT).c_str(), Settings.save_flag +#ifdef ESP8266 + , GetSettingsAddress() +#endif + ); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1")); } if ((0 == payload) || (2 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" - D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_CORE_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\"" +#ifdef ESP8266 + ",\"" D_JSON_BOOTVERSION "\":%d" +#endif + ",\"" D_JSON_COREVERSION "\":\"" ARDUINO_CORE_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," "\"Hardware\":\"%s\"" "%s}}"), - my_version, my_image, GetBuildDateAndTime().c_str(), - ESP_getBootVersion(), ESP.getSdkVersion(), + my_version, my_image, GetBuildDateAndTime().c_str() +#ifdef ESP8266 + , ESP.getBootVersion() +#endif + , ESP.getSdkVersion(), GetDeviceHardware().c_str(), GetStatistics().c_str()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2")); @@ -445,10 +459,18 @@ void CmndStatus(void) if ((0 == payload) || (4 == payload)) { Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\"" - D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\"" + D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d" +#ifdef ESP8266 + ",\"" D_JSON_FLASHCHIPID "\":\"%06X\"" +#endif + ",\"" D_JSON_FLASHMODE "\":%d,\"" D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"), ESP_getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, - ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP_getFlashChipId(), ESP.getFlashChipMode(), + ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024 +#ifdef ESP8266 + , ESP.getFlashChipId() +#endif + , ESP.getFlashChipMode(), LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2, feature5, feature6); XsnsDriverState(); ResponseAppend_P(PSTR(",\"Sensors\":")); diff --git a/tasmota/support_esp32.ino b/tasmota/support_esp32.ino index d9f6ab390..14ce6ac82 100644 --- a/tasmota/support_esp32.ino +++ b/tasmota/support_esp32.ino @@ -17,6 +17,48 @@ along with this program. If not, see . */ +/*********************************************************************************************\ + * ESP8266 Support +\*********************************************************************************************/ + +#ifdef ESP8266 + +extern "C" { +extern struct rst_info resetInfo; +} + +uint32_t ESP_ResetInfoReason(void) +{ + return resetInfo.reason; +} + +String ESP_getResetReason(void) +{ + return ESP.getResetReason(); +} + +uint32_t ESP_getChipId(void) +{ + return ESP.getChipId(); +} + +uint32_t ESP_getSketchSize(void) +{ + return ESP.getSketchSize(); +} + +void ESP_Restart(void) +{ +// ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 + ESP.reset(); +} + +#endif + +/*********************************************************************************************\ + * ESP32 Support +\*********************************************************************************************/ + #ifdef ESP32 #include @@ -82,16 +124,6 @@ void SettingsWrite(const void *pSettings, unsigned nSettingsLen) NvmSave("main", "Settings", pSettings, nSettingsLen); } -void SettingsLoadUpg(void *pSettings, unsigned nSettingsLen) -{ - NvmLoad("upg", "Settings", pSettings, nSettingsLen); -} - -void SettingsLoadUpgH(void *pSettings, unsigned nSettingsLen) -{ - NvmLoad("upg", "SettingsH", pSettings, nSettingsLen); -} - void QPCRead(void *pSettings, unsigned nSettingsLen) { NvmLoad("qpc", "pcreg", pSettings, nSettingsLen); @@ -184,4 +216,69 @@ void DisableBrownout(void) WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // Disable brownout detector } +// +// ESP32 Alternatives +// + +String ESP32GetResetReason(uint32_t cpu_no) +{ + // tools\sdk\include\esp32\rom\rtc.h + switch (rtc_get_reset_reason( (RESET_REASON) cpu_no)) { + case POWERON_RESET : return F("Vbat power on reset"); // 1 + case SW_RESET : return F("Software reset digital core"); // 3 + case OWDT_RESET : return F("Legacy watch dog reset digital core"); // 4 + case DEEPSLEEP_RESET : return F("Deep Sleep reset digital core"); // 5 + case SDIO_RESET : return F("Reset by SLC module, reset digital core"); // 6 + case TG0WDT_SYS_RESET : return F("Timer Group0 Watch dog reset digital core"); // 7 + case TG1WDT_SYS_RESET : return F("Timer Group1 Watch dog reset digital core"); // 8 + case RTCWDT_SYS_RESET : return F("RTC Watch dog Reset digital core"); // 9 + case INTRUSION_RESET : return F("Instrusion tested to reset CPU"); // 10 + case TGWDT_CPU_RESET : return F("Time Group reset CPU"); // 11 + case SW_CPU_RESET : return F("Software reset CPU"); // 12 + case RTCWDT_CPU_RESET : return F("RTC Watch dog Reset CPU"); // 13 + case EXT_CPU_RESET : return F("or APP CPU, reseted by PRO CPU"); // 14 + case RTCWDT_BROWN_OUT_RESET : return F("Reset when the vdd voltage is not stable"); // 15 + case RTCWDT_RTC_RESET : return F("RTC Watch dog reset digital core and rtc module"); // 16 + default : return F("NO_MEAN"); // 0 + } +} + +String ESP_getResetReason(void) +{ + return ESP32GetResetReason(0); // CPU 0 +} + +uint32_t ESP_ResetInfoReason(void) +{ + RESET_REASON reason = rtc_get_reset_reason(0); + if (POWERON_RESET == reason) { return REASON_DEFAULT_RST; } + if (SW_CPU_RESET == reason) { return REASON_SOFT_RESTART; } + if (DEEPSLEEP_RESET == reason) { return REASON_DEEP_SLEEP_AWAKE; } + if (SW_RESET == reason) { return REASON_EXT_SYS_RST; } +} + +uint32_t ESP_getChipId(void) +{ + uint32_t id = 0; + for (uint32_t i = 0; i < 17; i = i +8) { + id |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i; + } + return id; +} + +uint32_t ESP_getSketchSize(void) +{ + static uint32_t sketchsize = 0; + + if (!sketchsize) { + sketchsize = ESP.getSketchSize(); // This takes almost 2 seconds on an ESP32 + } + return sketchsize; +} + +void ESP_Restart(void) +{ + ESP.restart(); +} + #endif // ESP32 diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 18c026562..4648db9a1 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -708,8 +708,7 @@ void EspRestart(void) ResetPwm(); WifiShutdown(true); CrashDumpClear(); // Clear the stack dump in RTC -// ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 - ESP_reset(); + ESP_Restart(); } #ifndef ARDUINO_ESP8266_RELEASE_2_3_0 diff --git a/tasmota/tasmota_compat.h b/tasmota/tasmota_compat.h index 5119c9021..598ca5619 100644 --- a/tasmota/tasmota_compat.h +++ b/tasmota/tasmota_compat.h @@ -2,7 +2,6 @@ #ifdef ESP32 #include -#define PACKED __attribute((__packed__)) // Modul #undef MODULE #define MODULE WEMOS // [Module] Select default model @@ -10,13 +9,6 @@ #ifdef ESP8266 // ESP8266 -#define PACKED -#define ESP_getResetReason() ESP.getResetReason() -#define ESP_reset() ESP.reset() -#define ESP_getBootVersion() ESP.getBootVersion() -#define ESP_getFlashChipId() ESP.getFlashChipId() -#define ESP_getSketchSize() ESP.getSketchSize() -#define ESP_getChipId() ESP.getChipId() // // UDP #define PortUdp_write(p,n) PortUdp.write(p, n) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 1a54edb76..693a8f1a7 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2123,7 +2123,11 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1" D_BUILD_DATE_AND_TIME "}2%s"), GetBuildDateAndTime().c_str()); WSContentSend_P(PSTR("}1" D_CORE_AND_SDK_VERSION "}2" ARDUINO_CORE_RELEASE "/%s"), ESP.getSdkVersion()); WSContentSend_P(PSTR("}1" D_UPTIME "}2%s"), GetUptime().c_str()); +#ifdef ESP8266 WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d at 0x%X"), Settings.save_flag, GetSettingsAddress()); +#else + WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d"), Settings.save_flag); +#endif WSContentSend_P(PSTR("}1" D_BOOT_COUNT "}2%d"), Settings.bootcount); WSContentSend_P(PSTR("}1" D_RESTART_REASON "}2%s"), GetResetReason().c_str()); uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : devices_present; @@ -2197,7 +2201,9 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1}2 ")); // Empty line WSContentSend_P(PSTR("}1" D_ESP_CHIP_ID "}2%d"), ESP_getChipId()); - WSContentSend_P(PSTR("}1" D_FLASH_CHIP_ID "}20x%06X"), ESP_getFlashChipId()); +#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); From 1099789bf6bc140364a4a4fc06992b31e4e442b0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 19 Apr 2020 17:41:28 +0200 Subject: [PATCH 61/70] Add hardware serial support to ESP32 --- lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp b/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp index 212992775..967fe5992 100644 --- a/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp @@ -87,12 +87,15 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fal m_stop_bits = 1; m_nwmode = nwmode; serial_buffer_size = buffer_size; +#ifdef ESP8266 if (!((isValidGPIOpin(receive_pin)) && (isValidGPIOpin(transmit_pin) || transmit_pin == 16))) { return; } +#endif m_rx_pin = receive_pin; m_tx_pin = transmit_pin; m_in_pos = m_out_pos = 0; +#ifdef ESP8266 if (hardware_fallback && (((3 == m_rx_pin) && (1 == m_tx_pin)) || ((3 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (1 == m_tx_pin)))) { m_hardserial = true; } @@ -120,6 +123,9 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fal digitalWrite(m_tx_pin, HIGH); } } +#else + m_hardserial = true; +#endif m_valid = true; } @@ -144,17 +150,24 @@ bool TasmotaSerial::isValidGPIOpin(int pin) bool TasmotaSerial::begin(long speed, int stop_bits) { m_stop_bits = ((stop_bits -1) &1) +1; if (m_hardserial) { +#ifdef ESP8266 Serial.flush(); if (2 == m_stop_bits) { Serial.begin(speed, SERIAL_8N2); } else { Serial.begin(speed, SERIAL_8N1); } -#ifdef ESP8266 if (m_hardswap) { Serial.swap(); } -#endif // ESP8266 +#else // ESP32 + Serial2.flush(); + if (2 == m_stop_bits) { + Serial2.begin(speed, SERIAL_8N2, m_rx_pin, m_tx_pin); + } else { + Serial2.begin(speed, SERIAL_8N1, m_rx_pin, m_tx_pin); + } +#endif // ESP8266 - ESP32 } else { // Use getCycleCount() loop to get as exact timing as possible m_bit_time = ESP.getCpuFreqMHz() * 1000000 / speed; @@ -170,12 +183,20 @@ bool TasmotaSerial::begin() { } bool TasmotaSerial::hardwareSerial() { +#ifdef ESP8266 return m_hardserial; +#else + return false; // On ESP32 do not mess with Serial0 buffers +#endif } void TasmotaSerial::flush() { if (m_hardserial) { +#ifdef ESP8266 Serial.flush(); +#else + Serial2.flush(); +#endif } else { m_in_pos = m_out_pos = 0; } @@ -183,7 +204,11 @@ void TasmotaSerial::flush() { int TasmotaSerial::peek() { if (m_hardserial) { +#ifdef ESP8266 return Serial.peek(); +#else + return Serial2.peek(); +#endif } else { if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1; return m_buffer[m_out_pos]; @@ -193,7 +218,11 @@ int TasmotaSerial::peek() { int TasmotaSerial::read() { if (m_hardserial) { +#ifdef ESP8266 return Serial.read(); +#else + return Serial2.read(); +#endif } else { if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1; uint32_t ch = m_buffer[m_out_pos]; @@ -205,7 +234,11 @@ int TasmotaSerial::read() int TasmotaSerial::available() { if (m_hardserial) { +#ifdef ESP8266 return Serial.available(); +#else + return Serial2.available(); +#endif } else { int avail = m_in_pos - m_out_pos; if (avail < 0) avail += serial_buffer_size; @@ -250,7 +283,11 @@ void TasmotaSerial::_fast_write(uint8_t b) { size_t TasmotaSerial::write(uint8_t b) { if (m_hardserial) { +#ifdef ESP8266 return Serial.write(b); +#else + return Serial2.write(b); +#endif } else { if (-1 == m_tx_pin) return 0; if (m_high_speed) { From 06b91c4a374a58ffa96969014a0cbecc07f37346 Mon Sep 17 00:00:00 2001 From: Staars Date: Sun, 19 Apr 2020 21:51:56 +0200 Subject: [PATCH 62/70] revert serial related ESP32-changes, not needed anymore --- tasmota/xsns_60_GPS.ino | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/tasmota/xsns_60_GPS.ino b/tasmota/xsns_60_GPS.ino index 87e15d6a2..b789222fe 100644 --- a/tasmota/xsns_60_GPS.ino +++ b/tasmota/xsns_60_GPS.ino @@ -119,10 +119,6 @@ rule3 on tele-FLOG#sec do DisplayText [f0c1l4]SAV:%value% endon on tele-FLOG#r #include "NTPServer.h" #include "NTPPacket.h" -#ifdef ESP32 -#include -#endif - /*********************************************************************************************\ * constants \*********************************************************************************************/ @@ -299,11 +295,7 @@ enum UBXMsgType { #ifdef USE_FLOG FLOG *Flog = nullptr; #endif //USE_FLOG -#ifdef ESP8266 TasmotaSerial *UBXSerial; -#else -HardwareSerial *UBXSerial; -#endif NtpServer timeServer(PortUdp); @@ -363,21 +355,13 @@ void UBXDetect(void) { UBX.mode.init = 0; if ((pin[GPIO_GPS_RX] < 99) && (pin[GPIO_GPS_TX] < 99)) { -#ifdef ESP8266 UBXSerial = new TasmotaSerial(pin[GPIO_GPS_RX], pin[GPIO_GPS_TX], 1, 0, UBX_SERIAL_BUFFER_SIZE); // 64 byte buffer is NOT enough if (UBXSerial->begin(9600)) { -#else - UBXSerial = new HardwareSerial(2); - UBXSerial->begin(9600,SERIAL_8N1,pin[GPIO_GPS_RX], pin[GPIO_GPS_TX]); - { -#endif DEBUG_SENSOR_LOG(PSTR("UBX: started serial")); -#ifdef ESP8266 if (UBXSerial->hardwareSerial()) { ClaimSerial(); DEBUG_SENSOR_LOG(PSTR("UBX: claim HW")); } -#endif } } else { From 7be570d06064293d4e27c00745d08e6c87e91538 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 20 Apr 2020 10:40:54 +0200 Subject: [PATCH 63/70] Update ESP32 GPIO labelling --- tasmota/tasmota_template.h | 4 ++-- tasmota/xdrv_01_webserver.ino | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 6a047f25f..ae95705c7 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -717,8 +717,8 @@ const char PINS_WEMOS[] PROGMEM = "D3TXD4RXD2D1flashcFLFLolD6D7D5D8D0A0"; #define ADC0_PIN 33 // Pin number of ADC0 #define WEMOS_MODULE 0 // Wemos module -//const char PINS_WEMOS[] PROGMEM = "00TX02RX0405060708R1T11112131415R2T21819202122232425262728293031A4A5A6A7A03738A3"; -const char PINS_WEMOS[] PROGMEM = "I00TX0I02RX0I04I05I06I07I08RX1TX1I11I12I13I14I15RX2TX2I18I19I20I21I22I23I24I25I26I27I28I29I30I31AD4AD5AD6AD7AD0I37I38AD3"; +// 0 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930313233343536373839 +const char PINS_WEMOS[] PROGMEM = "IOTXIORXIOIOflashcFLFLolIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOA6A7A0IoIoA3"; #endif // ESP8266 diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 693a8f1a7..d900d83f0 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1614,14 +1614,13 @@ void HandleModuleConfiguration(void) WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); for (uint32_t i = 0; i < sizeof(cmodule); i++) { if (ValidGPIO(i, cmodule.io[i])) { -#ifdef ESP8266 snprintf_P(stemp, 3, PINS_WEMOS +i*2); +#ifdef ESP8266 char sesp8285[40]; snprintf_P(sesp8285, sizeof(sesp8285), PSTR("ESP8285"), WebColor(COL_TEXT_WARNING)); WSContentSend_P(PSTR("%s " D_GPIO "%d %s"), (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? sesp8285 :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i); #else // ESP32 - snprintf_P(stemp, 4, PINS_WEMOS +i*3); WSContentSend_P(PSTR("%s " D_GPIO "%d"), (WEMOS==my_module_type)?stemp:"", i, i); #endif // ESP8266 From 0d48f5a4a8431905119b7ca8dd0cce60a9dc5568 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 20 Apr 2020 12:27:29 +0200 Subject: [PATCH 64/70] Add ESP32 dual UART to TasmotaSerial --- .../README.md | 1 + .../examples/swsertest/swsertest.ino | 0 .../keywords.txt | 2 +- .../library.json | 4 +- .../library.properties | 4 +- .../src/TasmotaSerial.cpp | 61 ++++++++++++++++--- .../src/TasmotaSerial.h | 8 +++ 7 files changed, 65 insertions(+), 15 deletions(-) rename lib/{TasmotaSerial-2.4.1 => TasmotaSerial-3.0.0}/README.md (86%) rename lib/{TasmotaSerial-2.4.1 => TasmotaSerial-3.0.0}/examples/swsertest/swsertest.ino (100%) rename lib/{TasmotaSerial-2.4.1 => TasmotaSerial-3.0.0}/keywords.txt (96%) rename lib/{TasmotaSerial-2.4.1 => TasmotaSerial-3.0.0}/library.json (83%) rename lib/{TasmotaSerial-2.4.1 => TasmotaSerial-3.0.0}/library.properties (82%) rename lib/{TasmotaSerial-2.4.1 => TasmotaSerial-3.0.0}/src/TasmotaSerial.cpp (91%) rename lib/{TasmotaSerial-2.4.1 => TasmotaSerial-3.0.0}/src/TasmotaSerial.h (96%) diff --git a/lib/TasmotaSerial-2.4.1/README.md b/lib/TasmotaSerial-3.0.0/README.md similarity index 86% rename from lib/TasmotaSerial-2.4.1/README.md rename to lib/TasmotaSerial-3.0.0/README.md index 019aafc07..d2196ed4c 100644 --- a/lib/TasmotaSerial-2.4.1/README.md +++ b/lib/TasmotaSerial-3.0.0/README.md @@ -1,6 +1,7 @@ # TasmotaSerial Implementation of software serial with hardware serial fallback library for the ESP8266 +Implementation of dual UART hardware serial for the ESP32 Allows for several instances to be active at the same time. diff --git a/lib/TasmotaSerial-2.4.1/examples/swsertest/swsertest.ino b/lib/TasmotaSerial-3.0.0/examples/swsertest/swsertest.ino similarity index 100% rename from lib/TasmotaSerial-2.4.1/examples/swsertest/swsertest.ino rename to lib/TasmotaSerial-3.0.0/examples/swsertest/swsertest.ino diff --git a/lib/TasmotaSerial-2.4.1/keywords.txt b/lib/TasmotaSerial-3.0.0/keywords.txt similarity index 96% rename from lib/TasmotaSerial-2.4.1/keywords.txt rename to lib/TasmotaSerial-3.0.0/keywords.txt index 9cf6d825c..f9bde9254 100644 --- a/lib/TasmotaSerial-2.4.1/keywords.txt +++ b/lib/TasmotaSerial-3.0.0/keywords.txt @@ -1,6 +1,6 @@ ####################################### # Syntax Coloring Map for TasmotaSerial -# (esp8266) +# (esp8266 and esp32) ####################################### ####################################### diff --git a/lib/TasmotaSerial-2.4.1/library.json b/lib/TasmotaSerial-3.0.0/library.json similarity index 83% rename from lib/TasmotaSerial-2.4.1/library.json rename to lib/TasmotaSerial-3.0.0/library.json index 64cde09c9..0ebba7f95 100644 --- a/lib/TasmotaSerial-2.4.1/library.json +++ b/lib/TasmotaSerial-3.0.0/library.json @@ -1,10 +1,10 @@ { "name": "TasmotaSerial", - "version": "2.4.1", + "version": "3.0.0", "keywords": [ "serial", "io", "TasmotaSerial" ], - "description": "Implementation of software serial with hardware serial fallback for ESP8266.", + "description": "Implementation of software serial with hardware serial fallback for ESP8266 and ESP32.", "repository": { "type": "git", diff --git a/lib/TasmotaSerial-2.4.1/library.properties b/lib/TasmotaSerial-3.0.0/library.properties similarity index 82% rename from lib/TasmotaSerial-2.4.1/library.properties rename to lib/TasmotaSerial-3.0.0/library.properties index b326d7404..e2d92a4e8 100644 --- a/lib/TasmotaSerial-2.4.1/library.properties +++ b/lib/TasmotaSerial-3.0.0/library.properties @@ -1,8 +1,8 @@ name=TasmotaSerial -version=2.4.1 +version=3.0.0 author=Theo Arends maintainer=Theo Arends -sentence=Implementation of software serial with hardware serial fallback for ESP8266. +sentence=Implementation of software serial with hardware serial fallback for ESP8266 and ESP32. paragraph= category=Signal Input/Output url= diff --git a/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp b/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.cpp similarity index 91% rename from lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp rename to lib/TasmotaSerial-3.0.0/src/TasmotaSerial.cpp index 967fe5992..947e9dcc8 100644 --- a/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.cpp @@ -79,6 +79,10 @@ static void (*ISRList[16])() = { tms_isr_15 }; +#ifdef ESP32 +static uint8_t tasmota_serial_index = 3; +#endif + TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback, int nwmode, int buffer_size) { m_valid = false; @@ -161,12 +165,29 @@ bool TasmotaSerial::begin(long speed, int stop_bits) { Serial.swap(); } #else // ESP32 - Serial2.flush(); - if (2 == m_stop_bits) { - Serial2.begin(speed, SERIAL_8N2, m_rx_pin, m_tx_pin); - } else { - Serial2.begin(speed, SERIAL_8N1, m_rx_pin, m_tx_pin); + tasmota_serial_index--; + if (2 == tasmota_serial_index) { + m_uart = 2; + Serial2.flush(); + if (2 == m_stop_bits) { + Serial2.begin(speed, SERIAL_8N2, m_rx_pin, m_tx_pin); + } else { + Serial2.begin(speed, SERIAL_8N1, m_rx_pin, m_tx_pin); + } } + else if (1 == tasmota_serial_index) { + m_uart = 1; + Serial1.flush(); + if (2 == m_stop_bits) { + Serial1.begin(speed, SERIAL_8N2, m_rx_pin, m_tx_pin); + } else { + Serial1.begin(speed, SERIAL_8N1, m_rx_pin, m_tx_pin); + } + } + else { + m_valid = false; + } + Serial.printf("TSR: Using UART%d\n", m_uart); #endif // ESP8266 - ESP32 } else { // Use getCycleCount() loop to get as exact timing as possible @@ -195,7 +216,11 @@ void TasmotaSerial::flush() { #ifdef ESP8266 Serial.flush(); #else - Serial2.flush(); + if (2 == m_uart) { + Serial2.flush(); + } else { + Serial1.flush(); + } #endif } else { m_in_pos = m_out_pos = 0; @@ -207,7 +232,11 @@ int TasmotaSerial::peek() { #ifdef ESP8266 return Serial.peek(); #else - return Serial2.peek(); + if (2 == m_uart) { + return Serial2.peek(); + } else{ + return Serial1.peek(); + } #endif } else { if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1; @@ -221,7 +250,11 @@ int TasmotaSerial::read() #ifdef ESP8266 return Serial.read(); #else - return Serial2.read(); + if (2 == m_uart) { + return Serial2.read(); + } else { + return Serial1.read(); + } #endif } else { if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1; @@ -237,7 +270,11 @@ int TasmotaSerial::available() #ifdef ESP8266 return Serial.available(); #else - return Serial2.available(); + if (2 == m_uart) { + return Serial2.available(); + } else { + return Serial1.available(); + } #endif } else { int avail = m_in_pos - m_out_pos; @@ -286,7 +323,11 @@ size_t TasmotaSerial::write(uint8_t b) #ifdef ESP8266 return Serial.write(b); #else - return Serial2.write(b); + if (2 == m_uart) { + return Serial2.write(b); + } else { + return Serial1.write(b); + } #endif } else { if (-1 == m_tx_pin) return 0; diff --git a/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.h b/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.h similarity index 96% rename from lib/TasmotaSerial-2.4.1/src/TasmotaSerial.h rename to lib/TasmotaSerial-3.0.0/src/TasmotaSerial.h index 3ef4ee43b..d52660a54 100644 --- a/lib/TasmotaSerial-2.4.1/src/TasmotaSerial.h +++ b/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.h @@ -55,6 +55,10 @@ class TasmotaSerial : public Stream { uint32_t getLoopReadMetric(void) const { return m_bit_follow_metric; } +#ifdef ESP32 + uint32_t getUart(void) const { return m_uart; } +#endif + using Print::write; private: @@ -82,6 +86,10 @@ class TasmotaSerial : public Stream { bool m_very_high_speed = false; // above 100000 bauds uint8_t *m_buffer; +#ifdef ESP32 + uint8_t m_uart = 0; +#endif + void _fast_write(uint8_t b); // IRAM minimized version }; From 18de0e2b2f4c59745943c0a2971adba9ef32afad Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 20 Apr 2020 12:33:29 +0200 Subject: [PATCH 65/70] Remove debug message from TasmotaSerial --- lib/TasmotaSerial-3.0.0/src/TasmotaSerial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.cpp index 947e9dcc8..c1f7fe52e 100644 --- a/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.cpp @@ -187,7 +187,7 @@ bool TasmotaSerial::begin(long speed, int stop_bits) { else { m_valid = false; } - Serial.printf("TSR: Using UART%d\n", m_uart); +// Serial.printf("TSR: Using UART%d\n", m_uart); #endif // ESP8266 - ESP32 } else { // Use getCycleCount() loop to get as exact timing as possible From 6f207402cadd2791a96c2f7bd1bcb16ece3751f0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 20 Apr 2020 14:54:08 +0200 Subject: [PATCH 66/70] Make TasmotaSerial more generic --- lib/TasmotaSerial-3.0.0/src/TasmotaSerial.cpp | 81 +++++++------------ lib/TasmotaSerial-3.0.0/src/TasmotaSerial.h | 12 ++- 2 files changed, 37 insertions(+), 56 deletions(-) diff --git a/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.cpp index c1f7fe52e..6b41d068c 100644 --- a/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.cpp @@ -1,5 +1,5 @@ /* - TasmotaSerial.cpp - Minimal implementation of software serial for Tasmota + TasmotaSerial.cpp - Implementation of software serial with hardware serial fallback for Tasmota Copyright (C) 2020 Theo Arends @@ -27,6 +27,8 @@ extern "C" { #include +#ifdef ESP8266 + // for STAGE and pre-2.6, we can have a single wrapper using attachInterruptArg() void ICACHE_RAM_ATTR callRxRead(void *self) { ((TasmotaSerial*)self)->rxRead(); }; @@ -79,9 +81,11 @@ static void (*ISRList[16])() = { tms_isr_15 }; -#ifdef ESP32 -static uint8_t tasmota_serial_index = 3; -#endif +#else // ESP32 + + static int tasmota_serial_index = 2; // Allow UART2 and UART1 only + +#endif // ESP8266 TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback, int nwmode, int buffer_size) { @@ -91,15 +95,13 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fal m_stop_bits = 1; m_nwmode = nwmode; serial_buffer_size = buffer_size; -#ifdef ESP8266 - if (!((isValidGPIOpin(receive_pin)) && (isValidGPIOpin(transmit_pin) || transmit_pin == 16))) { - return; - } -#endif m_rx_pin = receive_pin; m_tx_pin = transmit_pin; m_in_pos = m_out_pos = 0; #ifdef ESP8266 + if (!((isValidGPIOpin(receive_pin)) && (isValidGPIOpin(transmit_pin) || transmit_pin == 16))) { + return; + } if (hardware_fallback && (((3 == m_rx_pin) && (1 == m_tx_pin)) || ((3 == m_rx_pin) && (-1 == m_tx_pin)) || ((-1 == m_rx_pin) && (1 == m_tx_pin)))) { m_hardserial = true; } @@ -127,14 +129,16 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fal digitalWrite(m_tx_pin, HIGH); } } -#else +#else // ESP32 + if (transmit_pin > 33) { return; } // GPIO34 - GPIO39 are Input only m_hardserial = true; -#endif +#endif // ESP8266 - ESP32 m_valid = true; } TasmotaSerial::~TasmotaSerial() { +#ifdef ESP8266 if (!m_hardserial) { if (m_rx_pin > -1) { detachInterrupt(m_rx_pin); @@ -144,6 +148,7 @@ TasmotaSerial::~TasmotaSerial() } } } +#endif // ESP8266 } bool TasmotaSerial::isValidGPIOpin(int pin) @@ -165,26 +170,16 @@ bool TasmotaSerial::begin(long speed, int stop_bits) { Serial.swap(); } #else // ESP32 - tasmota_serial_index--; - if (2 == tasmota_serial_index) { - m_uart = 2; - Serial2.flush(); + if (tasmota_serial_index > 0) { // We only support UART1 and UART2 and keep UART0 for debugging + m_uart = tasmota_serial_index; + tasmota_serial_index--; + TSerial = new HardwareSerial(m_uart); if (2 == m_stop_bits) { - Serial2.begin(speed, SERIAL_8N2, m_rx_pin, m_tx_pin); + TSerial->begin(speed, SERIAL_8N2, m_rx_pin, m_tx_pin); } else { - Serial2.begin(speed, SERIAL_8N1, m_rx_pin, m_tx_pin); + TSerial->begin(speed, SERIAL_8N1, m_rx_pin, m_tx_pin); } - } - else if (1 == tasmota_serial_index) { - m_uart = 1; - Serial1.flush(); - if (2 == m_stop_bits) { - Serial1.begin(speed, SERIAL_8N2, m_rx_pin, m_tx_pin); - } else { - Serial1.begin(speed, SERIAL_8N1, m_rx_pin, m_tx_pin); - } - } - else { + } else { m_valid = false; } // Serial.printf("TSR: Using UART%d\n", m_uart); @@ -216,11 +211,7 @@ void TasmotaSerial::flush() { #ifdef ESP8266 Serial.flush(); #else - if (2 == m_uart) { - Serial2.flush(); - } else { - Serial1.flush(); - } + TSerial->flush(); #endif } else { m_in_pos = m_out_pos = 0; @@ -232,11 +223,7 @@ int TasmotaSerial::peek() { #ifdef ESP8266 return Serial.peek(); #else - if (2 == m_uart) { - return Serial2.peek(); - } else{ - return Serial1.peek(); - } + return TSerial->peek(); #endif } else { if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1; @@ -250,11 +237,7 @@ int TasmotaSerial::read() #ifdef ESP8266 return Serial.read(); #else - if (2 == m_uart) { - return Serial2.read(); - } else { - return Serial1.read(); - } + return TSerial->read(); #endif } else { if ((-1 == m_rx_pin) || (m_in_pos == m_out_pos)) return -1; @@ -270,11 +253,7 @@ int TasmotaSerial::available() #ifdef ESP8266 return Serial.available(); #else - if (2 == m_uart) { - return Serial2.available(); - } else { - return Serial1.available(); - } + return TSerial->available(); #endif } else { int avail = m_in_pos - m_out_pos; @@ -323,11 +302,7 @@ size_t TasmotaSerial::write(uint8_t b) #ifdef ESP8266 return Serial.write(b); #else - if (2 == m_uart) { - return Serial2.write(b); - } else { - return Serial1.write(b); - } + return TSerial->write(b); #endif } else { if (-1 == m_tx_pin) return 0; diff --git a/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.h b/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.h index d52660a54..42a3f120e 100644 --- a/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.h +++ b/lib/TasmotaSerial-3.0.0/src/TasmotaSerial.h @@ -1,5 +1,5 @@ /* - TasmotaSerial.h - Minimal implementation of software serial for Tasmota + TasmotaSerial.h - Implementation of software serial with hardware serial fallback for Tasmota Copyright (C) 2020 Theo Arends @@ -36,6 +36,10 @@ #include #include +#ifdef ESP32 +#include +#endif + class TasmotaSerial : public Stream { public: TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fallback = 0, int nwmode = 0, int buffer_size = TM_SERIAL_BUFFER_SIZE); @@ -86,11 +90,13 @@ class TasmotaSerial : public Stream { bool m_very_high_speed = false; // above 100000 bauds uint8_t *m_buffer; + void _fast_write(uint8_t b); // IRAM minimized version + #ifdef ESP32 - uint8_t m_uart = 0; + HardwareSerial *TSerial; + int m_uart = 0; #endif - void _fast_write(uint8_t b); // IRAM minimized version }; #endif // TasmotaSerial_h From 78b771901fbf390330c1b45b5a033e6b1d308d0d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 20 Apr 2020 15:08:27 +0200 Subject: [PATCH 67/70] Update TasmotaSerial Library info --- lib/TasmotaSerial-3.0.0/library.json | 2 +- lib/TasmotaSerial-3.0.0/library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/TasmotaSerial-3.0.0/library.json b/lib/TasmotaSerial-3.0.0/library.json index 0ebba7f95..47b45c4ad 100644 --- a/lib/TasmotaSerial-3.0.0/library.json +++ b/lib/TasmotaSerial-3.0.0/library.json @@ -11,5 +11,5 @@ "url": "https://github.com/arendst/Tasmota/lib/TasmotaSerial" }, "frameworks": "arduino", - "platforms": "espressif8266" + "platforms": "espressif8266","espressif32" } diff --git a/lib/TasmotaSerial-3.0.0/library.properties b/lib/TasmotaSerial-3.0.0/library.properties index e2d92a4e8..d1d9e718a 100644 --- a/lib/TasmotaSerial-3.0.0/library.properties +++ b/lib/TasmotaSerial-3.0.0/library.properties @@ -6,4 +6,4 @@ sentence=Implementation of software serial with hardware serial fallback for ESP paragraph= category=Signal Input/Output url= -architectures=esp8266 +architectures=esp8266,esp32 From 8fb436c2e4b9846ffe500981ed98ed57b72c55f7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 20 Apr 2020 15:20:43 +0200 Subject: [PATCH 68/70] Fix updated TasmotaSerial Library info --- lib/TasmotaSerial-3.0.0/library.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/TasmotaSerial-3.0.0/library.json b/lib/TasmotaSerial-3.0.0/library.json index 47b45c4ad..19197cce4 100644 --- a/lib/TasmotaSerial-3.0.0/library.json +++ b/lib/TasmotaSerial-3.0.0/library.json @@ -11,5 +11,7 @@ "url": "https://github.com/arendst/Tasmota/lib/TasmotaSerial" }, "frameworks": "arduino", - "platforms": "espressif8266","espressif32" + "platforms": [ + "espressif8266", "espressif32" + ] } From 9958c5f0f18975bdf7556410b3b0df20df35dca5 Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Mon, 20 Apr 2020 11:15:45 -0300 Subject: [PATCH 69/70] BUTTON V2 --- tasmota/support_button_v2.ino | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/tasmota/support_button_v2.ino b/tasmota/support_button_v2.ino index 9548a2b4f..d29073a79 100644 --- a/tasmota/support_button_v2.ino +++ b/tasmota/support_button_v2.ino @@ -23,7 +23,7 @@ * Button support \*********************************************************************************************/ -#define MAX_RELAY_BUTTON1 4 // Max number of relay controlled by button1 +#define MAX_RELAY_BUTTON1 5 // Max number of relay controlled by BUTTON1 const char kMultiPress[] PROGMEM = "|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|"; @@ -99,10 +99,8 @@ uint8_t ButtonSerial(uint8_t serial_in_byte) * Button handler with single press only or multi-press and hold on all buttons * * ButtonDebounce (50) - Debounce time in mSec - * SetOption1 (0) - If set do not execute config commands * SetOption11 (0) - If set perform single press action on double press and reverse * SetOption13 (0) - If set act on single press only - * SetOption32 (40) - Max button hold time in Seconds * SetOption73 (0) - Decouple button from relay and send just mqtt topic \*********************************************************************************************/ @@ -114,8 +112,6 @@ void ButtonHandler(void) uint16_t loops_per_second = 1000 / Settings.button_debounce; // ButtonDebounce (50) char scmnd[20]; -// uint8_t maxdev = (devices_present > MAX_KEYS) ? MAX_KEYS : devices_present; -// for (uint32_t button_index = 0; button_index < maxdev; button_index++) { for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { uint8_t button = NOT_PRESSED; uint8_t button_present = 0; @@ -175,16 +171,15 @@ void ButtonHandler(void) if (!Settings.flag3.mqtt_buttons) { if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally - } else { - MqttButtonTopic(button_index +1, 1, 0); // SetOption73 (0) - Decouple button from relay and send just mqtt topic } - } - } + } + } else { + MqttButtonTopic(button_index +1, 1, 0); // SetOption73 (0) - Decouple button from relay and send just mqtt topic + } } } #endif // ESP8266 else { - if (((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index]) && !Button.inverted_mask) || - ((NOT_PRESSED == button) && (PRESSED == Button.last_state[button_index]) && Button.inverted_mask)) { + if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action, SetOption73 (0) - Decouple button from relay and send just mqtt topic if (!Settings.flag3.mqtt_buttons) { @@ -203,7 +198,7 @@ void ButtonHandler(void) blinks = 201; } - if (((NOT_PRESSED == button) && !Button.inverted_mask) || ((PRESSED == button) && Button.inverted_mask)) { + if (NOT_PRESSED == button) { Button.hold_timer[button_index] = 0; } else { Button.hold_timer[button_index]++; @@ -230,11 +225,10 @@ void ButtonHandler(void) } } - if (!Settings.flag.button_single) { // SetOption13 (0) - Allow multi-press + if (!Settings.flag.button_single) { // SetOption13 (0) - Allow multi-press if (Button.window_timer[button_index]) { Button.window_timer[button_index]--; } else { - // if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS_V2 +6)) { if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < 7)) { bool single_press = false; @@ -250,10 +244,6 @@ void ButtonHandler(void) if (Settings.flag.button_swap) { // SetOption11 (0) Button.press_counter[button_index] = (single_press) ? 1 : 2; } - // } else { - // if (!Settings.flag3.mqtt_buttons && button_index != 0) { - // Button.press_counter[button_index] = 1; - // } } } } @@ -272,7 +262,7 @@ void ButtonHandler(void) ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); } else { SendKey(KEY_BUTTON, button_index +1, Button.press_counter[button_index] +9); // 2,3,4 and 5 press send just the key value (11,12,13 and 14) for rules - if (0 == button_index) { // First button can toggle up to 4 relays if present + if (0 == button_index) { // BUTTON1 can toggle up to 5 relays if present. If a relay is not present will send out the key value (2,11,12,13 and 14) for rules if ((Button.press_counter[button_index] > 1 && pin[GPIO_REL1 + Button.press_counter[button_index]-1] < 99) && Button.press_counter[button_index] <= MAX_RELAY_BUTTON1) { ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: Relay%d found on GPIO%d"), Button.press_counter[button_index], pin[GPIO_REL1 + Button.press_counter[button_index]-1]); @@ -280,10 +270,7 @@ void ButtonHandler(void) } } } - // } else { // 6 - 8 press are used to send commands - // GetTextIndexed(scmnd, sizeof(scmnd), Button.press_counter[button_index] -6, kCommands); - // ExecuteCommand(scmnd, SRC_BUTTON); - // } + } else { // 6 press start wificonfig 2 snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2")); ExecuteCommand(scmnd, SRC_BUTTON); From 0b08c72247583fe004b5b2b00a652f937827a67b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 20 Apr 2020 17:47:40 +0200 Subject: [PATCH 70/70] Add command ``SetOption73 1`` for button decoupling Add command ``SetOption73 1`` for button decoupling and send multi-press and hold MQTT messages by Federico Leoni (#8235) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 3 ++- tasmota/support_button.ino | 2 +- tasmota/support_button_v2.ino | 31 ++++++++++++++++++------------- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2fcda28f5..93e1d8ac1 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -71,6 +71,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add commands ``NrfPage``, ``NrfIgnore``, ``NrfScan`` and ``NrfBeacon`` to NRF24 Bluetooth driver (#8075) - Add commands ``GlobalTemp`` and ``GlobalHum`` to init sensor data (#8152) - Add command ``SetOption41 `` to force sending gratuitous ARP every seconds +- Add command ``SetOption73 1`` for button decoupling and send multi-press and hold MQTT messages by Federico Leoni (#8235) - Add command ``SetOption90 1`` to disable non-json MQTT messages (#8044) - Add command ``SetOption91 1`` to enable fading at startup / power on - Add command ``Sensor10 0/1/2`` to control BH1750 resolution - 0 = High (default), 1 = High2, 2 = Low (#8016) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 0fb205aff..8785f69df 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,8 +2,9 @@ ### 8.2.0.4 20200417 -- Add config version tag - Fix Zigbee DimmerUp/DimmerDown malformed +- Add config version tag +- Add command ``SetOption73 1`` for button decoupling and send multi-press and hold MQTT messages by Federico Leoni (#8235) ### 8.2.0.3 20200329 diff --git a/tasmota/support_button.ino b/tasmota/support_button.ino index 914263add..c3b8e0dd7 100644 --- a/tasmota/support_button.ino +++ b/tasmota/support_button.ino @@ -17,7 +17,7 @@ along with this program. If not, see . */ -#define BUTTON_V1 +//#define BUTTON_V1 #ifdef BUTTON_V1 /*********************************************************************************************\ * Button support diff --git a/tasmota/support_button_v2.ino b/tasmota/support_button_v2.ino index d29073a79..456caa45c 100644 --- a/tasmota/support_button_v2.ino +++ b/tasmota/support_button_v2.ino @@ -17,7 +17,7 @@ along with this program. If not, see . */ -//#define BUTTON_V2 +#define BUTTON_V2 #ifdef BUTTON_V2 /*********************************************************************************************\ * Button support @@ -99,7 +99,8 @@ uint8_t ButtonSerial(uint8_t serial_in_byte) * Button handler with single press only or multi-press and hold on all buttons * * ButtonDebounce (50) - Debounce time in mSec - * SetOption11 (0) - If set perform single press action on double press and reverse + * SetOption1 (0) - If set do not execute commands WifiConfig and Reset + * SetOption11 (0) - If set perform single press action on double press and reverse (on two relay devices only) * SetOption13 (0) - If set act on single press only * SetOption73 (0) - Decouple button from relay and send just mqtt topic \*********************************************************************************************/ @@ -171,10 +172,10 @@ void ButtonHandler(void) if (!Settings.flag3.mqtt_buttons) { if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally - } + } } else { MqttButtonTopic(button_index +1, 1, 0); // SetOption73 (0) - Decouple button from relay and send just mqtt topic - } + } } } #endif // ESP8266 @@ -196,7 +197,7 @@ void ButtonHandler(void) Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window } blinks = 201; - } + } if (NOT_PRESSED == button) { Button.hold_timer[button_index] = 0; @@ -214,13 +215,15 @@ void ButtonHandler(void) MqttButtonTopic(button_index +1, 3, 1); } else { SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); // Execute Hold command via MQTT if ButtonTopic is set - } + } } else { - if ((Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10)) { // SetOption32 (40) - Button held for factor times longer - Button.press_counter[button_index] = 0; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); - ExecuteCommand(scmnd, SRC_BUTTON); - } + if (!Settings.flag.button_restrict) { + if ((Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10)) { // SetOption32 (40) - Button held for factor times longer + Button.press_counter[button_index] = 0; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); + ExecuteCommand(scmnd, SRC_BUTTON); + } + } } } } @@ -272,8 +275,10 @@ void ButtonHandler(void) } } else { // 6 press start wificonfig 2 + if (!Settings.flag.button_restrict) { snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2")); ExecuteCommand(scmnd, SRC_BUTTON); + } } if (Settings.flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic if (Button.press_counter[button_index] >= 1 && Button.press_counter[button_index] <= 5) { @@ -288,7 +293,7 @@ void ButtonHandler(void) } } } - + } } Button.last_state[button_index] = button; @@ -301,7 +306,7 @@ void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold) char stopic[TOPSZ]; char mqttstate[7]; - GetTextIndexed(mqttstate, sizeof(mqttstate), action, kMultiPress); + GetTextIndexed(mqttstate, sizeof(mqttstate), action, kMultiPress); SendKey(KEY_BUTTON, button_id, (hold) ? 3 : action +9); snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_id);