diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml
index 438d657cd..eec1bccf5 100644
--- a/.github/workflows/Tasmota_build_devel.yml
+++ b/.github/workflows/Tasmota_build_devel.yml
@@ -39,6 +39,10 @@ jobs:
- tasmota32-lvgl
- tasmota32c3
- tasmota32solo1
+ - tasmota32-safemode
+ - tasmota32c3-safemode
+ - tasmota32s2-safemode
+ - tasmota32s3-safemode
steps:
- uses: actions/checkout@v2
with:
@@ -117,7 +121,9 @@ jobs:
[ ! -f ./mv_firmware/firmware/tasmota32-core2.* ] || mv ./mv_firmware/firmware/tasmota32-core2.* ./firmware/tasmota32/
[ ! -f ./mv_firmware/firmware/tasmota32-bluetooth.* ] || mv ./mv_firmware/firmware/tasmota32-bluetooth.* ./firmware/tasmota32/
[ ! -f ./mv_firmware/firmware/tasmota32c3*.* ] || mv ./mv_firmware/firmware/tasmota32c3*.* ./firmware/tasmota32/
- [ ! -f ./mv_firmware/firmware/tasmota32* ] || mv ./mv_firmware/firmware/tasmota32* ./firmware/tasmota32/languages/
+ [ ! -f ./mv_firmware/firmware/tasmota32-safemode* ] || mv ./mv_firmware/firmware/tasmota32-safemode* ./firmware/tasmota32/
+ [ ! -f ./mv_firmware/firmware/tasmota32-* ] || mv ./mv_firmware/firmware/tasmota32-* ./firmware/tasmota32/languages/
+ [ ! -f ./mv_firmware/firmware/tasmota32* ] || mv ./mv_firmware/firmware/tasmota32* ./firmware/tasmota32/
[ ! -f ./mv_firmware/firmware/* ] || mv ./mv_firmware/firmware/* ./firmware/tasmota/languages/
- name: Display files to transfer
run: ls -R ./*
diff --git a/.github/workflows/build_all_the_things.yml b/.github/workflows/build_all_the_things.yml
index 9259cdf50..6c9f09770 100644
--- a/.github/workflows/build_all_the_things.yml
+++ b/.github/workflows/build_all_the_things.yml
@@ -43,6 +43,10 @@ jobs:
- tasmota32s2
- tasmota32c3
- tasmota32solo1
+ - tasmota32-safemode
+ - tasmota32c3-safemode
+ - tasmota32s2-safemode
+ - tasmota32s3-safemode
steps:
- uses: actions/checkout@v2
- name: Set up Python
diff --git a/.github/workflows/copy_change.yml b/.github/workflows/copy_change.yml
index 4840853cb..1306ccd50 100644
--- a/.github/workflows/copy_change.yml
+++ b/.github/workflows/copy_change.yml
@@ -12,6 +12,7 @@ jobs:
copy_change:
runs-on: ubuntu-latest
+ if: github.repository == 'arendst/Tasmota'
steps:
- uses: actions/checkout@v2
- name: Push I2CDevices.md to https://github.com/Tasmota/docs
diff --git a/BUILDS.md b/BUILDS.md
index 44b82d93a..c3d70ad51 100644
--- a/BUILDS.md
+++ b/BUILDS.md
@@ -216,6 +216,7 @@ Note: `minimal` variant is not listed as it shouldn't be used outside of the [up
| USE_HRE | - | - / x | - | x | - | - |
| USE_A4988_STEPPER | - | - / - | - | - | - | - |
| USE_NEOPOOL | - | - / - | - | - | - | - |
+| USE_FLOWRATEMETER | - | - / - | - | - | - | - |
| | | | | | | |
| Feature or Sensor | l | t | k | s | i | d | Remarks
| USE_DISPLAY | - | - / - | - | - | - | x |
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b4fafaadc..deb2e5f28 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file.
- Command ``EnergyExportActive`` to (p)reset energy export active for supported devices. Currently ADE7880 only (#13515)
- Sonoff SPM delayed SetPowerOnState (#13447)
- Command ``SetOption139 0/1`` to switch between pressure unit "mmHg" (0) or "inHg" (1) when ``SO24 1`` (#15350)
+- Support for flowrate meters like YF-DN50 and similary
### Changed
diff --git a/README.md b/README.md
index aad266191..59d85d472 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
![Tasmota logo](/tools/logo/TASMOTA_FullLogo_Vector.svg)
Alternative firmware for [ESP8266](https://en.wikipedia.org/wiki/ESP8266) and [ESP32](https://en.wikipedia.org/wiki/ESP32) based devices with **easy configuration using webUI, OTA updates, automation using timers or rules, expandability and entirely local control over MQTT, HTTP, Serial or KNX**.
-_Written for PlatformIO with limited support for Arduino IDE._
+_Written for PlatformIO._
[![GitHub version](https://img.shields.io/github/release/arendst/Tasmota.svg)](http://ota.tasmota.com/tasmota/release)
[![GitHub download](https://img.shields.io/github/downloads/arendst/Tasmota/total.svg)](https://github.com/arendst/Tasmota/releases/latest)
diff --git a/boards/esp32_4M_2APP.json b/boards/esp32_4M_2APP.json
index 34e8248e6..a998cdc7f 100644
--- a/boards/esp32_4M_2APP.json
+++ b/boards/esp32_4M_2APP.json
@@ -30,8 +30,8 @@
"arduino": {
"flash_extra_images": [
[
- "0x2E0000",
- "variants/tasmota/tasmota32-minicustom.bin"
+ "0x10000",
+ "variants/tasmota/tasmota32-safemode.bin"
]
]
},
diff --git a/boards/esp32c3_2APP.json b/boards/esp32c3_2APP.json
new file mode 100644
index 000000000..1d21ff1df
--- /dev/null
+++ b/boards/esp32c3_2APP.json
@@ -0,0 +1,43 @@
+{
+ "build": {
+ "arduino":{
+ "ldscript": "esp32c3_out.ld"
+ },
+ "core": "esp32",
+ "extra_flags": "-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M -DESP32C3",
+ "f_cpu": "160000000L",
+ "f_flash": "80000000L",
+ "flash_mode": "dout",
+ "mcu": "esp32c3",
+ "variant": "esp32c3",
+ "partitions": "esp32_partition_app2880k_spiffs320k.csv"
+ },
+ "connectivity": [
+ "wifi"
+ ],
+ "debug": {
+ "openocd_target": "esp32c3.cfg"
+ },
+ "frameworks": [
+ "arduino",
+ "espidf"
+ ],
+ "name": "Espressif Generic ESP32-C3 4M Flash, Tasmota 2880k Code/OTA, 320k FS",
+ "upload": {
+ "arduino": {
+ "flash_extra_images": [
+ [
+ "0x10000",
+ "variants/tasmota/tasmota32c3-safemode.bin"
+ ]
+ ]
+ },
+ "flash_size": "4MB",
+ "maximum_ram_size": 327680,
+ "maximum_size": 4194304,
+ "require_upload_port": true,
+ "speed": 460800
+ },
+ "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html",
+ "vendor": "Espressif"
+ }
diff --git a/boards/esp32s2_2APP.json b/boards/esp32s2_2APP.json
new file mode 100644
index 000000000..0227a4a11
--- /dev/null
+++ b/boards/esp32s2_2APP.json
@@ -0,0 +1,43 @@
+{
+ "build": {
+ "arduino":{
+ "ldscript": "esp32s2_out.ld"
+ },
+ "core": "esp32",
+ "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DESP32_4M -DESP32S2",
+ "f_cpu": "240000000L",
+ "f_flash": "80000000L",
+ "flash_mode": "dout",
+ "mcu": "esp32s2",
+ "variant": "esp32s2",
+ "partitions": "esp32_partition_app2880k_spiffs320k.csv"
+ },
+ "connectivity": [
+ "wifi"
+ ],
+ "debug": {
+ "openocd_target": "esp32s2.cfg"
+ },
+ "frameworks": [
+ "espidf",
+ "arduino"
+ ],
+ "name": "Espressif Generic ESP32-S2 4M Flash, Tasmota 2880k Code/OTA, 320k FS",
+ "upload": {
+ "arduino": {
+ "flash_extra_images": [
+ [
+ "0x10000",
+ "variants/tasmota/tasmota32s2-safemode.bin"
+ ]
+ ]
+ },
+ "flash_size": "4MB",
+ "maximum_ram_size": 327680,
+ "maximum_size": 4194304,
+ "require_upload_port": true,
+ "speed": 460800
+ },
+ "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html",
+ "vendor": "Espressif"
+}
diff --git a/boards/esp32s3_2APP.json b/boards/esp32s3_2APP.json
new file mode 100644
index 000000000..1a37483e4
--- /dev/null
+++ b/boards/esp32s3_2APP.json
@@ -0,0 +1,46 @@
+{
+ "build": {
+ "arduino":{
+ "ldscript": "esp32s3_out.ld",
+ "memory_type": "qspi_qspi"
+ },
+ "core": "esp32",
+ "extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DESP32_4M -DESP32S3",
+ "f_cpu": "240000000L",
+ "f_flash": "80000000L",
+ "flash_mode": "dio",
+ "mcu": "esp32s3",
+ "variant": "esp32s3",
+ "partitions": "esp32_partition_app2880k_spiffs320k.csv"
+ },
+ "connectivity": [
+ "wifi",
+ "bluetooth",
+ "ethernet"
+ ],
+ "debug": {
+ "openocd_target": "esp32s3.cfg"
+ },
+ "frameworks": [
+ "espidf",
+ "arduino"
+ ],
+ "name": "Espressif Generic ESP32-S3 4M Flash, Tasmota 2880k Code/OTA, 320k FS",
+ "upload": {
+ "arduino": {
+ "flash_extra_images": [
+ [
+ "0x10000",
+ "variants/tasmota/tasmota32s3-safemode.bin"
+ ]
+ ]
+ },
+ "flash_size": "4MB",
+ "maximum_ram_size": 327680,
+ "maximum_size": 4194304,
+ "require_upload_port": true,
+ "speed": 460800
+ },
+ "url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/",
+ "vendor": "Espressif"
+}
diff --git a/esp32_partition_app2880k_spiffs320k.csv b/esp32_partition_app2880k_spiffs320k.csv
index 511ce01a1..ee2ce899c 100644
--- a/esp32_partition_app2880k_spiffs320k.csv
+++ b/esp32_partition_app2880k_spiffs320k.csv
@@ -1,6 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
-app0, app, ota_0, 0x10000, 0x2D0000,
-factory, app, factory, 0x2E0000,0xD0000,
+factory, app, factory, 0x10000, 0xD0000,
+app0, app, ota_0, 0xE0000, 0x2D0000,
spiffs, data, spiffs, 0x3B0000,0x50000,
diff --git a/lib/libesp32/berry/default/be_modtab.c b/lib/libesp32/berry/default/be_modtab.c
index 000e36881..5ed4a99e6 100644
--- a/lib/libesp32/berry/default/be_modtab.c
+++ b/lib/libesp32/berry/default/be_modtab.c
@@ -46,6 +46,8 @@ be_extern_native_module(hue_ntv);
be_extern_native_module(hue_bridge);
be_extern_native_module(uuid);
be_extern_native_module(animate);
+be_extern_native_module(partition_core);
+be_extern_native_module(crc);
#ifdef USE_LVGL
be_extern_native_module(lv);
be_extern_native_module(lv_extra);
@@ -146,6 +148,8 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
&be_native_module(webserver),
#endif // USE_WEBSERVER
&be_native_module(flash),
+ &be_native_module(partition_core),
+ &be_native_module(crc),
/* user-defined modules register end */
NULL /* do not remove */
diff --git a/lib/libesp32/berry/generate/be_const_strtab.h b/lib/libesp32/berry/generate/be_const_strtab.h
index 26d4948b0..daf7ff25c 100644
--- a/lib/libesp32/berry/generate/be_const_strtab.h
+++ b/lib/libesp32/berry/generate/be_const_strtab.h
@@ -1,4 +1,6 @@
extern const bcstring be_const_str_;
+extern const bcstring be_const_str_00;
+extern const bcstring be_const_str_AA50;
extern const bcstring be_const_str_AES_GCM;
extern const bcstring be_const_str_ALIGN_BOTTOM_MID;
extern const bcstring be_const_str_ALIGN_LEFT_MID;
@@ -16,12 +18,13 @@ extern const bcstring be_const_str_Auto_X2Dconfiguration;
extern const bcstring be_const_str_BECDFE;
extern const bcstring be_const_str_BLE;
extern const bcstring be_const_str_BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20;
+extern const bcstring be_const_str_BRY_X3A_X20Exception_X3E_X20_X27;
extern const bcstring be_const_str_BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s;
extern const bcstring be_const_str_BRY_X3A_X20argument_X20must_X20be_X20a_X20function;
extern const bcstring be_const_str_BRY_X3A_X20bytecode_X20has_X20wrong_X20version_X20_X27_X25s_X27_X20_X28_X25i_X29;
extern const bcstring be_const_str_BRY_X3A_X20corrupt_X20bytecode_X20_X27_X25s_X27;
extern const bcstring be_const_str_BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29;
-extern const bcstring be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_X27_X25s_X27_X20_X28_X25s_X29;
+extern const bcstring be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_X27_X25s_X27_X20_X28_X25s_X20_X2D_X20_X25s_X29;
extern const bcstring be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson;
extern const bcstring be_const_str_BRY_X3A_X20failed_X20to_X20load_X20compiled_X20_X27_X25s_X27_X20_X28_X25s_X29;
extern const bcstring be_const_str_BRY_X3A_X20failed_X20to_X20run_X20compiled_X20code_X20_X27_X25s_X27_X20_X2D_X20_X25s;
@@ -50,12 +53,14 @@ extern const bcstring be_const_str_COLOR_BLACK;
extern const bcstring be_const_str_COLOR_WHITE;
extern const bcstring be_const_str_CT;
extern const bcstring be_const_str_DIMMER;
+extern const bcstring be_const_str_EBEBFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
extern const bcstring be_const_str_EC_C25519;
extern const bcstring be_const_str_EVENT_DELETE;
extern const bcstring be_const_str_EVENT_DRAW_MAIN;
extern const bcstring be_const_str_EVENT_DRAW_PART_BEGIN;
extern const bcstring be_const_str_EVENT_DRAW_PART_END;
extern const bcstring be_const_str_EXTERNAL_I2S;
+extern const bcstring be_const_str_FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
extern const bcstring be_const_str_False;
extern const bcstring be_const_str_GET;
extern const bcstring be_const_str_HTTP_GET;
@@ -64,17 +69,22 @@ extern const bcstring be_const_str_I2C_Driver;
extern const bcstring be_const_str_I2C_X3A;
extern const bcstring be_const_str_INTERNAL_DAC;
extern const bcstring be_const_str_INTERNAL_PDM;
+extern const bcstring be_const_str_Invalid_X20ota_X20partition_X20number;
extern const bcstring be_const_str_LVG_X3A_X20call_X20to_X20unsupported_X20callback;
extern const bcstring be_const_str_Leds;
extern const bcstring be_const_str_MAX_RMT;
extern const bcstring be_const_str_MD5;
extern const bcstring be_const_str_MI32;
+extern const bcstring be_const_str_No_X20SPIFFS_X20partition_X20found;
extern const bcstring be_const_str_None;
extern const bcstring be_const_str_OPTION_A;
extern const bcstring be_const_str_OneWire;
extern const bcstring be_const_str_PART_MAIN;
extern const bcstring be_const_str_POST;
extern const bcstring be_const_str_Parameter_X20error;
+extern const bcstring be_const_str_Partition;
+extern const bcstring be_const_str_Partition_info;
+extern const bcstring be_const_str_Partition_otadata;
extern const bcstring be_const_str_RELAY;
extern const bcstring be_const_str_RES_OK;
extern const bcstring be_const_str_RGB;
@@ -111,6 +121,7 @@ extern const bcstring be_const_str_TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X
extern const bcstring be_const_str_TASMOTA;
extern const bcstring be_const_str_Tasmota;
extern const bcstring be_const_str_Tele;
+extern const bcstring be_const_str_Too_X20many_X20partiition_X20slots;
extern const bcstring be_const_str_Trigger;
extern const bcstring be_const_str_True;
extern const bcstring be_const_str_Unknown;
@@ -120,7 +131,10 @@ extern const bcstring be_const_str_WS2812_GRB;
extern const bcstring be_const_str_Wire;
extern const bcstring be_const_str__;
extern const bcstring be_const_str__X0A;
+extern const bcstring be_const_str__X0A_X29_X3E;
extern const bcstring be_const_str__X20;
+extern const bcstring be_const_str__X20_X20;
+extern const bcstring be_const_str__X20_X28;
extern const bcstring be_const_str__X21_X3D;
extern const bcstring be_const_str__X21_X3D_X3D;
extern const bcstring be_const_str__X22;
@@ -138,7 +152,9 @@ extern const bcstring be_const_str__X2508x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2D_
extern const bcstring be_const_str__X25s_X2Eautoconf;
extern const bcstring be_const_str__X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B;
extern const bcstring be_const_str__X26lt_X3BNone_X26gt_X3B;
+extern const bcstring be_const_str__X27_X20_X2D_X20;
extern const bcstring be_const_str__X28_X29;
+extern const bcstring be_const_str__X29;
extern const bcstring be_const_str__X2A;
extern const bcstring be_const_str__X2B;
extern const bcstring be_const_str__X2C;
@@ -172,6 +188,9 @@ extern const bcstring be_const_str__X3C_X3D;
extern const bcstring be_const_str__X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E;
extern const bcstring be_const_str__X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E;
extern const bcstring be_const_str__X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E;
+extern const bcstring be_const_str__X3Cinstance_X3A_X20Partition_X28_X5B_X0A;
+extern const bcstring be_const_str__X3Cinstance_X3A_X20Partition_info_X28_X25d_X25s_X2C_X25d_X25s_X2C0x_X2508X_X2C0x_X2508X_X2C_X27_X25s_X27_X2C0x_X25X_X29_X3E;
+extern const bcstring be_const_str__X3Cinstance_X3A_X20Partition_otadata_X28ota_active_X3A_X25d_X2C_X20ota_seq_X3D_X5B_X25d_X2C_X25d_X5D_X2C_X20ota_max_X3D_X25d_X29_X3E;
extern const bcstring be_const_str__X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29;
extern const bcstring be_const_str__X3Clabel_X3EChoose_X20a_X20device_X20configuration_X3A_X3C_X2Flabel_X3E_X3Cbr_X3E;
extern const bcstring be_const_str__X3Clambda_X3E;
@@ -195,6 +214,7 @@ extern const bcstring be_const_str__X3E_X3D;
extern const bcstring be_const_str__X3F;
extern const bcstring be_const_str__X5B;
extern const bcstring be_const_str__X5D;
+extern const bcstring be_const_str__X5D_X2C_X0A_X20_X20;
extern const bcstring be_const_str__X7B;
extern const bcstring be_const_str__X7B_X7D;
extern const bcstring be_const_str__X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D;
@@ -238,12 +258,15 @@ extern const bcstring be_const_str__rules;
extern const bcstring be_const_str__settings_def;
extern const bcstring be_const_str__settings_ptr;
extern const bcstring be_const_str__splash;
+extern const bcstring be_const_str__subscribe;
extern const bcstring be_const_str__t;
extern const bcstring be_const_str__timers;
+extern const bcstring be_const_str__validate;
extern const bcstring be_const_str__write;
extern const bcstring be_const_str_a;
extern const bcstring be_const_str_abs;
extern const bcstring be_const_str_acos;
+extern const bcstring be_const_str_active_otadata;
extern const bcstring be_const_str_add;
extern const bcstring be_const_str_add_anim;
extern const bcstring be_const_str_add_cb_event_closure;
@@ -264,6 +287,7 @@ extern const bcstring be_const_str_allocated;
extern const bcstring be_const_str_alternate;
extern const bcstring be_const_str_animate;
extern const bcstring be_const_str_animators;
+extern const bcstring be_const_str_app;
extern const bcstring be_const_str_arc_dsc;
extern const bcstring be_const_str_arch;
extern const bcstring be_const_str_area;
@@ -353,11 +377,17 @@ extern const bcstring be_const_str_content_stop;
extern const bcstring be_const_str_continue;
extern const bcstring be_const_str_coord_arr;
extern const bcstring be_const_str_copy;
+extern const bcstring be_const_str_coredump;
extern const bcstring be_const_str_cos;
extern const bcstring be_const_str_cosh;
extern const bcstring be_const_str_couldn_X27t_X20not_X20initialize_X20noepixelbus;
extern const bcstring be_const_str_count;
extern const bcstring be_const_str_counters;
+extern const bcstring be_const_str_crc;
+extern const bcstring be_const_str_crc16;
+extern const bcstring be_const_str_crc32;
+extern const bcstring be_const_str_crc32_ota_seq;
+extern const bcstring be_const_str_crc8;
extern const bcstring be_const_str_create_custom_widget;
extern const bcstring be_const_str_create_matrix;
extern const bcstring be_const_str_create_segment;
@@ -366,6 +396,7 @@ extern const bcstring be_const_str_ctor;
extern const bcstring be_const_str_ctypes_bytes;
extern const bcstring be_const_str_ctypes_bytes_dyn;
extern const bcstring be_const_str_dac_voltage;
+extern const bcstring be_const_str_data;
extern const bcstring be_const_str_day;
extern const bcstring be_const_str_debug;
extern const bcstring be_const_str_decode;
@@ -403,6 +434,7 @@ extern const bcstring be_const_str_driver_name;
extern const bcstring be_const_str_dump;
extern const bcstring be_const_str_duration;
extern const bcstring be_const_str_editable;
+extern const bcstring be_const_str_efuse_em;
extern const bcstring be_const_str_elements_X20must_X20be_X20a_X20lv_point;
extern const bcstring be_const_str_elif;
extern const bcstring be_const_str_else;
@@ -413,6 +445,7 @@ extern const bcstring be_const_str_energy_struct;
extern const bcstring be_const_str_engine;
extern const bcstring be_const_str_erase;
extern const bcstring be_const_str_escape;
+extern const bcstring be_const_str_esphttpd;
extern const bcstring be_const_str_eth;
extern const bcstring be_const_str_event;
extern const bcstring be_const_str_event_cb;
@@ -428,9 +461,11 @@ extern const bcstring be_const_str_exec_tele;
extern const bcstring be_const_str_exists;
extern const bcstring be_const_str_exp;
extern const bcstring be_const_str_f;
+extern const bcstring be_const_str_factory;
extern const bcstring be_const_str_false;
extern const bcstring be_const_str_fast_loop;
extern const bcstring be_const_str_fast_loop_enabled;
+extern const bcstring be_const_str_fat;
extern const bcstring be_const_str_file;
extern const bcstring be_const_str_file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27;
extern const bcstring be_const_str_files;
@@ -438,6 +473,8 @@ extern const bcstring be_const_str_find;
extern const bcstring be_const_str_find_key_i;
extern const bcstring be_const_str_find_op;
extern const bcstring be_const_str_finish;
+extern const bcstring be_const_str_flags;
+extern const bcstring be_const_str_flash;
extern const bcstring be_const_str_floor;
extern const bcstring be_const_str_flush;
extern const bcstring be_const_str_font_embedded;
@@ -460,6 +497,7 @@ extern const bcstring be_const_str_gc;
extern const bcstring be_const_str_gen_cb;
extern const bcstring be_const_str_get;
extern const bcstring be_const_str_get_MAC;
+extern const bcstring be_const_str_get_active;
extern const bcstring be_const_str_get_alternate;
extern const bcstring be_const_str_get_aps_voltage;
extern const bcstring be_const_str_get_bat_charge_current;
@@ -476,12 +514,14 @@ extern const bcstring be_const_str_get_event_cb;
extern const bcstring be_const_str_get_free_heap;
extern const bcstring be_const_str_get_height;
extern const bcstring be_const_str_get_hor_res;
+extern const bcstring be_const_str_get_image_size;
extern const bcstring be_const_str_get_input_power_status;
extern const bcstring be_const_str_get_light;
extern const bcstring be_const_str_get_log;
extern const bcstring be_const_str_get_name;
extern const bcstring be_const_str_get_object_from_ptr;
extern const bcstring be_const_str_get_option;
+extern const bcstring be_const_str_get_ota_slot;
extern const bcstring be_const_str_get_percentage;
extern const bcstring be_const_str_get_pixel_color;
extern const bcstring be_const_str_get_power;
@@ -540,12 +580,17 @@ extern const bcstring be_const_str_int64;
extern const bcstring be_const_str_internal_error;
extern const bcstring be_const_str_introspect;
extern const bcstring be_const_str_invalid_X20GPIO_X20number;
+extern const bcstring be_const_str_invalid_X20magic_X20number_X20_X2502X;
extern const bcstring be_const_str_invalidate;
+extern const bcstring be_const_str_invalidate_spiffs;
extern const bcstring be_const_str_io_error;
extern const bcstring be_const_str_ip;
extern const bcstring be_const_str_is_dirty;
+extern const bcstring be_const_str_is_factory;
extern const bcstring be_const_str_is_first_time;
+extern const bcstring be_const_str_is_ota;
extern const bcstring be_const_str_is_running;
+extern const bcstring be_const_str_is_spiffs;
extern const bcstring be_const_str_isinstance;
extern const bcstring be_const_str_ismethod;
extern const bcstring be_const_str_isnan;
@@ -575,6 +620,7 @@ extern const bcstring be_const_str_list_handlers;
extern const bcstring be_const_str_listdir;
extern const bcstring be_const_str_load;
extern const bcstring be_const_str_load_freetype_font;
+extern const bcstring be_const_str_load_otadata;
extern const bcstring be_const_str_load_templates;
extern const bcstring be_const_str_local;
extern const bcstring be_const_str_log;
@@ -610,6 +656,8 @@ extern const bcstring be_const_str_manuf;
extern const bcstring be_const_str_map;
extern const bcstring be_const_str_math;
extern const bcstring be_const_str_matrix;
+extern const bcstring be_const_str_maxota;
+extern const bcstring be_const_str_md5;
extern const bcstring be_const_str_member;
extern const bcstring be_const_str_members;
extern const bcstring be_const_str_memory;
@@ -621,6 +669,9 @@ extern const bcstring be_const_str_model;
extern const bcstring be_const_str_module;
extern const bcstring be_const_str_month;
extern const bcstring be_const_str_montserrat_font;
+extern const bcstring be_const_str_mqtt;
+extern const bcstring be_const_str_mqtt_data;
+extern const bcstring be_const_str_mqtt_listener;
extern const bcstring be_const_str_name;
extern const bcstring be_const_str_nan;
extern const bcstring be_const_str_next;
@@ -631,6 +682,8 @@ extern const bcstring be_const_str_no_X20more_X20RMT_X20channel_X20available;
extern const bcstring be_const_str_now;
extern const bcstring be_const_str_null_cb;
extern const bcstring be_const_str_number;
+extern const bcstring be_const_str_nvs;
+extern const bcstring be_const_str_nvskeys;
extern const bcstring be_const_str_o;
extern const bcstring be_const_str_obj;
extern const bcstring be_const_str_obj_class_create_obj;
@@ -641,12 +694,17 @@ extern const bcstring be_const_str_on;
extern const bcstring be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E;
extern const bcstring be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20change_X20the_X20current_X20configuration_X20and_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E;
extern const bcstring be_const_str_open;
+extern const bcstring be_const_str_ota;
+extern const bcstring be_const_str_ota_max;
+extern const bcstring be_const_str_otadata;
extern const bcstring be_const_str_out_X20of_X20range;
extern const bcstring be_const_str_p1;
extern const bcstring be_const_str_p2;
extern const bcstring be_const_str_page_autoconf_ctl;
extern const bcstring be_const_str_page_autoconf_mgr;
extern const bcstring be_const_str_param;
+extern const bcstring be_const_str_parse;
+extern const bcstring be_const_str_partition_core;
extern const bcstring be_const_str_path;
extern const bcstring be_const_str_pc;
extern const bcstring be_const_str_pc_abs;
@@ -655,6 +713,7 @@ extern const bcstring be_const_str_pct;
extern const bcstring be_const_str_percentage;
extern const bcstring be_const_str_persist;
extern const bcstring be_const_str_persist_X2E_p_X20is_X20not_X20a_X20map;
+extern const bcstring be_const_str_phy;
extern const bcstring be_const_str_pi;
extern const bcstring be_const_str_pin;
extern const bcstring be_const_str_pin_mode;
@@ -683,6 +742,7 @@ extern const bcstring be_const_str_rad;
extern const bcstring be_const_str_raise;
extern const bcstring be_const_str_rand;
extern const bcstring be_const_str_range;
+extern const bcstring be_const_str_raw;
extern const bcstring be_const_str_read;
extern const bcstring be_const_str_read12;
extern const bcstring be_const_str_read13;
@@ -710,6 +770,7 @@ extern const bcstring be_const_str_remove_driver;
extern const bcstring be_const_str_remove_light;
extern const bcstring be_const_str_remove_rule;
extern const bcstring be_const_str_remove_timer;
+extern const bcstring be_const_str_remove_trailing_zeroes;
extern const bcstring be_const_str_reset;
extern const bcstring be_const_str_reset_search;
extern const bcstring be_const_str_resize;
@@ -724,6 +785,7 @@ extern const bcstring be_const_str_return;
extern const bcstring be_const_str_return_X20code_X3D_X25i;
extern const bcstring be_const_str_reverse;
extern const bcstring be_const_str_reverse_gamma10;
+extern const bcstring be_const_str_rollback;
extern const bcstring be_const_str_rotate;
extern const bcstring be_const_str_round_end;
extern const bcstring be_const_str_round_start;
@@ -748,9 +810,12 @@ extern const bcstring be_const_str_seg7_font;
extern const bcstring be_const_str_select;
extern const bcstring be_const_str_send;
extern const bcstring be_const_str_send_multicast;
+extern const bcstring be_const_str_seq0;
+extern const bcstring be_const_str_seq1;
extern const bcstring be_const_str_serial;
extern const bcstring be_const_str_set;
extern const bcstring be_const_str_set_MAC;
+extern const bcstring be_const_str_set_active;
extern const bcstring be_const_str_set_align;
extern const bcstring be_const_str_set_alternate;
extern const bcstring be_const_str_set_auth;
@@ -776,6 +841,7 @@ extern const bcstring be_const_str_set_light;
extern const bcstring be_const_str_set_matrix_pixel_color;
extern const bcstring be_const_str_set_mode_ct;
extern const bcstring be_const_str_set_mode_rgb;
+extern const bcstring be_const_str_set_ota_max;
extern const bcstring be_const_str_set_percentage;
extern const bcstring be_const_str_set_pixel_color;
extern const bcstring be_const_str_set_power;
@@ -824,7 +890,9 @@ extern const bcstring be_const_str_sin;
extern const bcstring be_const_str_sinh;
extern const bcstring be_const_str_size;
extern const bcstring be_const_str_skip;
+extern const bcstring be_const_str_slots;
extern const bcstring be_const_str_solidified;
+extern const bcstring be_const_str_spiffs;
extern const bcstring be_const_str_splash;
extern const bcstring be_const_str_splash_init;
extern const bcstring be_const_str_splash_remove;
@@ -844,8 +912,10 @@ extern const bcstring be_const_str_strip;
extern const bcstring be_const_str_strptime;
extern const bcstring be_const_str_style_prop_arr;
extern const bcstring be_const_str_subscribe;
+extern const bcstring be_const_str_subtype;
extern const bcstring be_const_str_success;
extern const bcstring be_const_str_super;
+extern const bcstring be_const_str_switch_factory;
extern const bcstring be_const_str_sys;
extern const bcstring be_const_str_tag;
extern const bcstring be_const_str_tan;
@@ -858,6 +928,7 @@ extern const bcstring be_const_str_tasmota_X2Eset_light_X28_X29_X20is_X20depreca
extern const bcstring be_const_str_tasmota_log_reader;
extern const bcstring be_const_str_tcpclient;
extern const bcstring be_const_str_tele;
+extern const bcstring be_const_str_test;
extern const bcstring be_const_str_the_X20second_X20argument_X20is_X20not_X20a_X20function;
extern const bcstring be_const_str_time_dump;
extern const bcstring be_const_str_time_reached;
@@ -870,6 +941,7 @@ extern const bcstring be_const_str_toint;
extern const bcstring be_const_str_tolower;
extern const bcstring be_const_str_tomap;
extern const bcstring be_const_str_top;
+extern const bcstring be_const_str_topic;
extern const bcstring be_const_str_toptr;
extern const bcstring be_const_str_tostring;
extern const bcstring be_const_str_touch_update;
diff --git a/lib/libesp32/berry/generate/be_const_strtab_def.h b/lib/libesp32/berry/generate/be_const_strtab_def.h
index d2c51ccaf..49a12d477 100644
--- a/lib/libesp32/berry/generate/be_const_strtab_def.h
+++ b/lib/libesp32/berry/generate/be_const_strtab_def.h
@@ -1,900 +1,972 @@
-be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_driver_name);
-be_define_const_str(_X0A, "\n", 252472541u, 0, 1, &be_const_str_autoexec);
-be_define_const_str(_X20, " ", 621580159u, 0, 1, &be_const_str_stop);
-be_define_const_str(_X21_X3D, "!=", 2428715011u, 0, 2, &be_const_str_editable);
-be_define_const_str(_X21_X3D_X3D, "!==", 559817114u, 0, 3, &be_const_str_cb_obj);
-be_define_const_str(_X22, "\"", 655135397u, 0, 1, &be_const_str_RGBW);
-be_define_const_str(_X22_X3A, "\":", 399167565u, 0, 2, &be_const_str__X2F_X2Eautoconf);
-be_define_const_str(_X23, "#", 638357778u, 0, 1, &be_const_str_write);
-be_define_const_str(_X23autoexec_X2Ebat, "#autoexec.bat", 3382890497u, 0, 13, &be_const_str_SERIAL_5O1);
-be_define_const_str(_X23autoexec_X2Ebe, "#autoexec.be", 1181757091u, 0, 12, &be_const_str_font_embedded);
-be_define_const_str(_X23display_X2Eini, "#display.ini", 182218220u, 0, 12, &be_const_str_INTERNAL_PDM);
-be_define_const_str(_X23init_X2Ebat, "#init.bat", 3297595077u, 0, 9, &be_const_str_MD5);
-be_define_const_str(_X23preinit_X2Ebe, "#preinit.be", 687035716u, 0, 11, &be_const_str_False);
-be_define_const_str(_X25, "%", 537692064u, 0, 1, &be_const_str_classname);
-be_define_const_str(_X2502d_X25s_X2502d, "%02d%s%02d", 1587999717u, 0, 10, &be_const_str_EXTERNAL_I2S);
-be_define_const_str(_X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d, "%04d-%02d-%02dT%02d:%02d:%02d", 3425528601u, 0, 29, &be_const_str__X2A);
-be_define_const_str(_X2508x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2508x, "%08x-%04x-%04x-%04x-%04x%08x", 1670063141u, 0, 28, &be_const_str_Auto_X2Dconfiguration);
-be_define_const_str(_X25s_X2Eautoconf, "%s.autoconf", 3560383524u, 0, 11, &be_const_str_pc);
-be_define_const_str(_X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B, "<Error: apply new or remove>", 2855507949u, 0, 34, &be_const_str_h);
-be_define_const_str(_X26lt_X3BNone_X26gt_X3B, "<None>", 2602165498u, 0, 12, &be_const_str_send_multicast);
-be_define_const_str(_X28_X29, "()", 685372826u, 0, 2, &be_const_str_available);
-be_define_const_str(_X2A, "*", 789356349u, 0, 1, &be_const_str__settings_def);
-be_define_const_str(_X2B, "+", 772578730u, 0, 1, &be_const_str_id_X20must_X20be_X20of_X20type_X20_X27int_X27);
-be_define_const_str(_X2C, ",", 688690635u, 0, 1, NULL);
-be_define_const_str(_X2C_X22AXP192_X22_X3A_X7B_X22VBusVoltage_X22_X3A_X25_X2E3f_X2C_X22VBusCurrent_X22_X3A_X25_X2E1f_X2C_X22BattVoltage_X22_X3A_X25_X2E3f_X2C_X22BattCurrent_X22_X3A_X25_X2E1f_X2C_X22Temperature_X22_X3A_X25_X2E1f_X7D, ",\"AXP192\":{\"VBusVoltage\":%.3f,\"VBusCurrent\":%.1f,\"BattVoltage\":%.3f,\"BattCurrent\":%.1f,\"Temperature\":%.1f}", 2598755376u, 0, 106, &be_const_str_isnan);
-be_define_const_str(_X2D, "-", 671913016u, 0, 1, NULL);
-be_define_const_str(_X2D_X2A, "-*", 499980374u, 0, 2, &be_const_str_BECDFE);
-be_define_const_str(_X2D_X2D_X3A_X2D_X2D, "--:--", 1370615441u, 0, 5, &be_const_str_add_driver);
-be_define_const_str(_X2E, ".", 722245873u, 0, 1, &be_const_str_load_templates);
-be_define_const_str(_X2E_X2E, "..", 2748622605u, 0, 2, NULL);
-be_define_const_str(_X2Eautoconf, ".autoconf", 2524679088u, 0, 9, &be_const_str_animate);
-be_define_const_str(_X2Ebe, ".be", 1325797348u, 0, 3, &be_const_str_RGB);
-be_define_const_str(_X2Ebec, ".bec", 3985273221u, 0, 4, &be_const_str_get_input_power_status);
-be_define_const_str(_X2Elen, ".len", 850842136u, 0, 4, &be_const_str_begin);
-be_define_const_str(_X2Ep, ".p", 1171526419u, 0, 2, &be_const_str_file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27);
-be_define_const_str(_X2Ep1, ".p1", 249175686u, 0, 3, &be_const_str_AES_GCM);
-be_define_const_str(_X2Ep2, ".p2", 232398067u, 0, 3, &be_const_str_get_bri);
-be_define_const_str(_X2Esize, ".size", 1965188224u, 0, 5, &be_const_str__X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E);
-be_define_const_str(_X2Etapp, ".tapp", 1363391594u, 0, 5, &be_const_str_assign_rmt);
-be_define_const_str(_X2Ew, ".w", 1255414514u, 0, 2, &be_const_str_load_freetype_font);
-be_define_const_str(_X2F, "/", 705468254u, 0, 1, &be_const_str_class_init_obj);
+be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_get_bat_power);
+be_define_const_str(_X0A, "\n", 252472541u, 0, 1, &be_const_str_as);
+be_define_const_str(_X0A_X29_X3E, "\n)>", 804061574u, 0, 3, &be_const_str_SERIAL_7N1);
+be_define_const_str(_X20, " ", 621580159u, 0, 1, &be_const_str_SERIAL_8E2);
+be_define_const_str(_X20_X20, " ", 2982523533u, 0, 2, &be_const_str_Leds);
+be_define_const_str(_X20_X28, " (", 2848302581u, 0, 2, &be_const_str__X3C);
+be_define_const_str(_X21_X3D, "!=", 2428715011u, 0, 2, &be_const_str_json);
+be_define_const_str(_X21_X3D_X3D, "!==", 559817114u, 0, 3, &be_const_str_attrdump);
+be_define_const_str(_X22, "\"", 655135397u, 0, 1, &be_const_str_EVENT_DELETE);
+be_define_const_str(_X22_X3A, "\":", 399167565u, 0, 2, &be_const_str_screenshot);
+be_define_const_str(_X23, "#", 638357778u, 0, 1, &be_const_str_get_style_pad_right);
+be_define_const_str(_X23autoexec_X2Ebat, "#autoexec.bat", 3382890497u, 0, 13, &be_const_str_content_start);
+be_define_const_str(_X23autoexec_X2Ebe, "#autoexec.be", 1181757091u, 0, 12, &be_const_str_consume_silence);
+be_define_const_str(_X23display_X2Eini, "#display.ini", 182218220u, 0, 12, &be_const_str_cb_obj);
+be_define_const_str(_X23init_X2Ebat, "#init.bat", 3297595077u, 0, 9, NULL);
+be_define_const_str(_X23preinit_X2Ebe, "#preinit.be", 687035716u, 0, 11, &be_const_str_atleast1);
+be_define_const_str(_X25, "%", 537692064u, 0, 1, &be_const_str_add_header);
+be_define_const_str(_X2502d_X25s_X2502d, "%02d%s%02d", 1587999717u, 0, 10, &be_const_str_maxota);
+be_define_const_str(_X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d, "%04d-%02d-%02dT%02d:%02d:%02d", 3425528601u, 0, 29, NULL);
+be_define_const_str(_X2508x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2508x, "%08x-%04x-%04x-%04x-%04x%08x", 1670063141u, 0, 28, &be_const_str__X2A);
+be_define_const_str(_X25s_X2Eautoconf, "%s.autoconf", 3560383524u, 0, 11, &be_const_str_crc32);
+be_define_const_str(_X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B, "<Error: apply new or remove>", 2855507949u, 0, 34, &be_const_str_None);
+be_define_const_str(_X26lt_X3BNone_X26gt_X3B, "<None>", 2602165498u, 0, 12, &be_const_str_SERIAL_7O2);
+be_define_const_str(_X27_X20_X2D_X20, "' - ", 3420378487u, 0, 4, &be_const_str__X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29);
+be_define_const_str(_X28_X29, "()", 685372826u, 0, 2, &be_const_str__X3Cp_X3E_X3C_X2Fp_X3E_X3C_X2Ffieldset_X3E_X3Cp_X3E_X3C_X2Fp_X3E);
+be_define_const_str(_X29, ")", 739023492u, 0, 1, &be_const_str_adv_cb);
+be_define_const_str(_X2A, "*", 789356349u, 0, 1, &be_const_str_RGBW);
+be_define_const_str(_X2B, "+", 772578730u, 0, 1, &be_const_str_decrypt);
+be_define_const_str(_X2C, ",", 688690635u, 0, 1, &be_const_str__X2F_X2Eautoconf);
+be_define_const_str(_X2C_X22AXP192_X22_X3A_X7B_X22VBusVoltage_X22_X3A_X25_X2E3f_X2C_X22VBusCurrent_X22_X3A_X25_X2E1f_X2C_X22BattVoltage_X22_X3A_X25_X2E3f_X2C_X22BattCurrent_X22_X3A_X25_X2E1f_X2C_X22Temperature_X22_X3A_X25_X2E1f_X7D, ",\"AXP192\":{\"VBusVoltage\":%.3f,\"VBusCurrent\":%.1f,\"BattVoltage\":%.3f,\"BattCurrent\":%.1f,\"Temperature\":%.1f}", 2598755376u, 0, 106, &be_const_str_bri);
+be_define_const_str(_X2D, "-", 671913016u, 0, 1, &be_const_str_CFG_X3A_X20loaded_X20_X20);
+be_define_const_str(_X2D_X2A, "-*", 499980374u, 0, 2, &be_const_str_set_style_img_recolor);
+be_define_const_str(_X2D_X2D_X3A_X2D_X2D, "--:--", 1370615441u, 0, 5, &be_const_str_groups);
+be_define_const_str(_X2E, ".", 722245873u, 0, 1, &be_const_str_set_align);
+be_define_const_str(_X2E_X2E, "..", 2748622605u, 0, 2, &be_const_str__X3A);
+be_define_const_str(_X2Eautoconf, ".autoconf", 2524679088u, 0, 9, &be_const_str_available);
+be_define_const_str(_X2Ebe, ".be", 1325797348u, 0, 3, &be_const_str_AA50);
+be_define_const_str(_X2Ebec, ".bec", 3985273221u, 0, 4, &be_const_str_CFG_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s);
+be_define_const_str(_X2Elen, ".len", 850842136u, 0, 4, NULL);
+be_define_const_str(_X2Ep, ".p", 1171526419u, 0, 2, &be_const_str_base_class);
+be_define_const_str(_X2Ep1, ".p1", 249175686u, 0, 3, &be_const_str_add_anim);
+be_define_const_str(_X2Ep2, ".p2", 232398067u, 0, 3, &be_const_str_SERIAL_5N2);
+be_define_const_str(_X2Esize, ".size", 1965188224u, 0, 5, &be_const_str_CFG_X3A_X20loaded_X20_X27_X25s_X27);
+be_define_const_str(_X2Etapp, ".tapp", 1363391594u, 0, 5, &be_const_str__X3Cp_X3E_X3Csmall_X3E_X26nbsp_X3B_X28This_X20feature_X20requires_X20an_X20internet_X20connection_X29_X3C_X2Fsmall_X3E_X3C_X2Fp_X3E);
+be_define_const_str(_X2Ew, ".w", 1255414514u, 0, 2, &be_const_str__X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E);
+be_define_const_str(_X2F, "/", 705468254u, 0, 1, &be_const_str_BLE);
be_define_const_str(_X2F_X2Eautoconf, "/.autoconf", 2212074393u, 0, 10, NULL);
-be_define_const_str(_X2F_X3Frst_X3D, "/?rst=", 580074707u, 0, 6, &be_const_str_every_second);
-be_define_const_str(_X2Fac, "/ac", 3904651978u, 0, 3, &be_const_str_get_alternate);
-be_define_const_str(_X2Flights_X2F, "/lights/", 2370247908u, 0, 8, &be_const_str_arc_dsc);
-be_define_const_str(_X2Fstate_X2F, "/state/", 4226179876u, 0, 7, &be_const_str___lower__);
-be_define_const_str(_X3A, ":", 1057798253u, 0, 1, &be_const_str_EVENT_DELETE);
-be_define_const_str(_X3C, "<", 957132539u, 0, 1, &be_const_str_POST);
-be_define_const_str(_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "
", 3546571739u, 0, 11, &be_const_str_json_fdump_any);
-be_define_const_str(_X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "", 1863865923u, 0, 16, &be_const_str_loop);
-be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str_import);
-be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str_chars_in_string);
-be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str_content_send_style);
-be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "", 2052843416u, 0, 25, &be_const_str_CFG_X3A_X20loaded_X20_X20);
-be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "", 2058443583u, 0, 110, &be_const_str_arch);
-be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, "", 3546571739u, 0, 11, &be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson);
+be_define_const_str(_X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "", 1863865923u, 0, 16, &be_const_str_response_append);
+be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str_setrange);
+be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str_register_button_encoder);
+be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str_remove);
+be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "", 2052843416u, 0, 25, NULL);
+be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "", 2058443583u, 0, 110, &be_const_str_call);
+be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, "")
end
webserver.content_send("")
@@ -591,7 +241,9 @@ class Partition_manager_UI
var ota_num = slot.is_ota()
if ota_num != nil
# we have an OTA partition
- self.page_show_partition(slot, ota_num == p.otadata.active_otadata, ota_num)
+ self.page_show_partition(slot, ota_num == p.otadata.active_otadata, ota_num, p.otadata.maxota)
+ elif slot.is_factory()
+ self.page_show_partition(slot, false, nil, nil)
elif slot.is_spiffs()
var flash_size = tasmota.memory()['flash'] * 1024
var used_size = (slot.start + slot.size)
@@ -647,8 +299,9 @@ class Partition_manager_UI
def page_part_mgr()
import webserver
import string
+ import partition_core
if !webserver.check_privileged_access() return nil end
- var p = partition.Partition()
+ var p = partition_core.Partition()
webserver.content_start("Partition Manager") #- title of the web page -#
webserver.content_send_style() #- send standard Tasmota styles -#
@@ -659,9 +312,11 @@ class Partition_manager_UI
self.page_show_partitions(p)
webserver.content_send("")
- webserver.content_send("")
+ if p.otadata.maxota > 0
+ webserver.content_send("")
+ end
webserver.content_button(webserver.BUTTON_MANAGEMENT) #- button back to management page -#
webserver.content_stop() #- end of web page -#
@@ -673,10 +328,11 @@ class Partition_manager_UI
def page_part_ctl()
import webserver
import string
+ import partition_core
if !webserver.check_privileged_access() return nil end
#- check that the partition is valid -#
- var p = partition.Partition()
+ var p = partition_core.Partition()
try
#---------------------------------------------------------------------#
@@ -847,6 +503,7 @@ partition.Partition_manager_UI = Partition_manager_UI
#- create and register driver in Tasmota -#
if tasmota
+ import partition_core
var partition_manager_ui = partition.Partition_manager_UI()
tasmota.add_driver(partition_manager_ui)
## can be removed if put in 'autoexec.bat'
diff --git a/tasmota/html_compressed/HTTP_HEAD_LAST_SCRIPT.h b/tasmota/html_compressed/HTTP_HEAD_LAST_SCRIPT.h
index 41ed93443..32b31c318 100644
--- a/tasmota/html_compressed/HTTP_HEAD_LAST_SCRIPT.h
+++ b/tasmota/html_compressed/HTTP_HEAD_LAST_SCRIPT.h
@@ -2,7 +2,7 @@
// compressed by tools/unishox/compress-html-uncompressed.py
/////////////////////////////////////////////////////////////////////
-const size_t HTTP_HEAD_LAST_SCRIPT_SIZE = 355;
+const size_t HTTP_HEAD_LAST_SCRIPT_SIZE = 346;
const char HTTP_HEAD_LAST_SCRIPT_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x46\xB1\x0E\xE9\xDE\x3D\xA6\x77\xF5\x47\xC3\x8C\xEA\x2D\x3E"
"\x09\x81\x8B\x1A\xFA\x8E\x86\xA1\x6F\xE6\x45\xE6\x13\x0E\xB3\xE5\x61\x04\x77\x4F"
"\xBD\xE1\x82\xE8\xEA\x1C\x2E\xAB\x38\xEA\xA6\x6C\xAB\xFB\xB3\xAB\xCC\x26\x1D\x1F"
@@ -13,7 +13,6 @@ const char HTTP_HEAD_LAST_SCRIPT_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x4
"\x04\x1C\x87\x44\x3E\xCF\x7C\xF3\x04\x7C\xB0\xF0\x7B\xA8\xED\x9D\xB3\xC1\xEE\x3D"
"\xC0\x89\xC1\x77\x8C\x1D\xDF\x03\x02\xE0\xBC\xE8\x28\xC0\x2F\x70\x2C\x74\xF5\x19"
"\x04\xCE\x82\x6F\x86\x05\x66\x47\xCF\x1D\xA3\xEC\x70\x58\x19\xA1\xF6\x79\x9F\x7D"
- "\x9C\xCF\xB0\x43\xD7\x47\xC2\x3B\xA6\xB1\x0E\xF1\xE0\xF4\x3B\x3C\x1F\xF4\x65\x1F"
- "\x86";
+ "\x9C\xCF\xB0\x43\xD7\x47\xC2\x3B\xA6\xB1\x0E\xF1\xE0";
#define HTTP_HEAD_LAST_SCRIPT Decompress(HTTP_HEAD_LAST_SCRIPT_COMPRESSED,HTTP_HEAD_LAST_SCRIPT_SIZE).c_str()
\ No newline at end of file
diff --git a/tasmota/html_compressed/HTTP_HEAD_LAST_SCRIPT32.h b/tasmota/html_compressed/HTTP_HEAD_LAST_SCRIPT32.h
new file mode 100644
index 000000000..fcf228aad
--- /dev/null
+++ b/tasmota/html_compressed/HTTP_HEAD_LAST_SCRIPT32.h
@@ -0,0 +1,40 @@
+/////////////////////////////////////////////////////////////////////
+// compressed by tools/unishox/compress-html-uncompressed.py
+/////////////////////////////////////////////////////////////////////
+
+const size_t HTTP_HEAD_LAST_SCRIPT32_SIZE = 989;
+const char HTTP_HEAD_LAST_SCRIPT32_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x46\xB1\x0E\xE9\xDE\x3D\xA6\x77\xF5\x47\xC3\x8C\xEA\x2D\x3E"
+ "\x09\x81\x8B\x1A\xFA\x8E\x86\xA1\x6F\xE6\x45\xE6\x13\x0E\xB3\xE5\x61\x04\x77\x4F"
+ "\xBD\xE1\x82\xE8\xEA\x1C\x2E\xAB\x38\xEA\xA6\x6C\xAB\xFB\xB3\xAB\xCC\x26\x1D\x1F"
+ "\x67\x78\xF0\x3E\x2B\x42\x67\x77\x4E\x81\x3E\x1E\xA1\x47\xE1\xF2\x8E\xF1\xED\xD3"
+ "\x07\x77\x4F\x7A\x8F\x7C\xEF\x1E\xDD\x3D\xEA\x3D\xF3\xDE\x3E\xFA\xC6\xB3\xEC\xF7"
+ "\xCF\x87\x77\x4F\x7A\x8F\x7C\xE8\x2A\x2B\xFC\x57\x55\xFD\x1C\x2E\x99\xDD\x3E\xF4"
+ "\x43\xEC\xEF\x1F\xA3\xF4\x77\x4F\xE0\x27\x57\xEB\x1A\xCF\xB3\xBC\x77\x8E\xF1\xDA"
+ "\x04\x1C\x87\x44\x3E\xCF\x7C\xF3\x04\x7C\xB0\xF0\x7B\xA8\xED\x9D\xB3\xC1\xEE\x3D"
+ "\xC0\x89\xC1\x77\x8C\x1D\xDF\x03\x02\xE0\xBC\xE8\x28\xC0\x2F\x70\x2C\x74\xF5\x19"
+ "\x04\xCE\x82\x6F\x86\x05\x66\x47\xCF\x1D\xA3\xEC\x70\x58\x19\xA1\xF6\x79\x9F\x7D"
+ "\x9C\xCF\xB0\x43\xD7\x47\xC2\x3B\xA6\xB1\x0E\xF1\xE0\x11\x76\x41\x67\x76\x8E\xF1"
+ "\xED\x63\x8E\xE9\xF6\x60\xE5\x9F\x67\x78\x81\x2B\x21\x04\x2C\x5D\x8E\x3B\xA7\xD9"
+ "\x83\x94\x40\x9B\x68\x10\x73\xD3\xC5\x1D\x0C\x67\xC6\x9D\x3C\x2C\x70\xDD\xA3\xBA"
+ "\x77\x8F\x2A\x01\x8B\xC2\x08\xB1\x81\x1D\xDA\x04\x1E\x10\xBC\x11\xF0\x10\x70\x43"
+ "\xDE\x3E\xC5\x9C\xA3\xEC\xF7\xCE\x84\x63\x42\x7E\x3D\xE3\x8C\xF7\xCE\x85\xE0\xB4"
+ "\x36\x77\x4E\x33\xAA\x1D\xE3\xC1\x19\xDF\xD7\xC4\x3E\x73\x1F\x44\x63\x42\x65\xF7"
+ "\x62\x3F\x9D\xD3\xBC\x78\xF8\x87\x4C\xE0\xB2\xC4\x3E\x1D\xD3\xBC\x7C\x3F\x0F\x69"
+ "\x9D\xFD\x0E\x1C\x7C\xE6\x3E\x88\x5E\xF5\x1C\xF9\x15\xFF\xF6\x64\x77\x7E\x21\xD3"
+ "\xEF\xC2\xC2\xA3\xBC\x78\xD3\x07\x74\x70\xE0\x42\xE2\x14\xF8\x7C\x39\x0F\xD1\xFA"
+ "\x21\xC3\x8F\x78\xE3\x3D\xF3\xE1\xF1\x91\xB0\x99\xC4\x77\x8F\x69\x18\x0E\x8E\xED"
+ "\x1D\xE3\xC1\xEE\x61\x79\x9E\xD0\x4C\xE0\x60\xF0\x7B\x8F\x1F\x10\xE9\xF7\x62\x15"
+ "\xF8\xAF\xFF\xB3\x22\x1C\x2C\xC1\x87\xF3\xBB\xE0\x8E\xF1\xE3\xEE\x85\xFF\x91\x8B"
+ "\x0B\xCC\xF0\x7B\x81\x17\x8A\x2A\x01\x41\xCB\x8F\x69\x9D\xFD\x1B\x0F\x9C\xC7\xD1"
+ "\x1B\x08\x69\x04\x42\xAA\x86\x17\xD9\xA8\x5B\xF5\x1D\xD3\xBC\x78\x36\x1D\x30\x63"
+ "\xE3\xBA\x7D\x90\xF1\x32\xA3\xEC\xEA\x3E\xCE\xC1\x67\x30\xED\x10\xB3\x98\x7C\x23"
+ "\x01\xD1\xFA\xB1\x9A\x7C\x3E\xCE\xAA\xF8\xB6\x77\x8F\x06\xC3\xA6\x77\xDD\x88\x65"
+ "\xEA\xBA\x61\x8A\xBE\x1E\x60\x83\xC2\x76\x98\x3B\xA6\xC3\xA7\xDD\x88\x64\x5E\xAB"
+ "\xA6\x7C\x3E\x1C\xC3\xF4\x7E\x88\xD8\x74\xF5\x5D\x0B\xF1\xF0\xF8\x72\x9B\x20\x42"
+ "\xE3\x2A\x01\xF8\x6C\x3A\x7D\xF8\x66\x77\x99\x53\x36\x51\xE3\x4C\x1D\xDF\x1F\x0F"
+ "\x87\xD9\x8B\x0B\xCC\xFB\x3B\xDE\x74\x55\xA3\x5E\x0B\xA3\xBA\x77\x4E\xF1\xF0\xFC"
+ "\x04\x4E\x19\x4E\xA3\x9C\xDB\x3B\xC4\x08\x78\x4D\x7C\x5B\x3E\xCE\xF7\x85\x82\x27"
+ "\x10\x08\x16\x75\xA3\x8C\xEF\x1E\xD2\x05\x4C\xD4\xE5\x36\xC8\x10\x78\xB0\x36\x1D"
+ "\x3C\xF8\x43\xBA\x77\x8F\x07\xB8\xF4\x3B\x3C\x1F\xF4\x65\x1F\x86";
+
+#define HTTP_HEAD_LAST_SCRIPT32 Decompress(HTTP_HEAD_LAST_SCRIPT32_COMPRESSED,HTTP_HEAD_LAST_SCRIPT32_SIZE).c_str()
\ No newline at end of file
diff --git a/tasmota/html_uncompressed/HTTP_HEAD_LAST_SCRIPT.h b/tasmota/html_uncompressed/HTTP_HEAD_LAST_SCRIPT.h
index 6a3a01c49..5818df491 100644
--- a/tasmota/html_uncompressed/HTTP_HEAD_LAST_SCRIPT.h
+++ b/tasmota/html_uncompressed/HTTP_HEAD_LAST_SCRIPT.h
@@ -18,4 +18,4 @@ const char HTTP_HEAD_LAST_SCRIPT[] PROGMEM =
"}"
"}"
"wl(jd);" // Add name='' to any id='' in input,button,textarea,select
- "";
+ ;
diff --git a/tasmota/html_uncompressed/HTTP_HEAD_LAST_SCRIPT32.h b/tasmota/html_uncompressed/HTTP_HEAD_LAST_SCRIPT32.h
new file mode 100644
index 000000000..3b8a1ebff
--- /dev/null
+++ b/tasmota/html_uncompressed/HTTP_HEAD_LAST_SCRIPT32.h
@@ -0,0 +1,65 @@
+const char HTTP_HEAD_LAST_SCRIPT32[] PROGMEM =
+ "function jd(){" // Add label name='' based on provided id=''
+ "var t=0,i=document.querySelectorAll('input,button,textarea,select');"
+ "while(i.length>=t){"
+ "if(i[t]){"
+ "i[t]['name']=(i[t].hasAttribute('id')&&(!i[t].hasAttribute('name')))?i[t]['id']:i[t]['name'];"
+ "}"
+ "t++;"
+ "}"
+ "}"
+ "function sf(s){"
+ "var t=0,i=document.querySelectorAll('.hf');"
+ "while(i.length>=t){"
+ "if(i[t]){"
+ "i[t].style.display=s?'block':'none';"
+ "}"
+ "t++;"
+ "}"
+ "}"
+ "wl(jd);" // Add name='' to any id='' in input,button,textarea,select
+ // experimental
+ "function su(t){"
+ // "console.log('su()');"
+ "eb('f3').style.display='none';"
+ "eb('f2').style.display='block';"
+ "t.form.submit();"
+ "}"
+ "function upl(t){" // check file's first byte to decide next step
+ "var sl=t.form['u2'].files[0].slice(0,1);" // load only first byte of file
+ // "console.log(sl);"
+ // "console.log(sl.length);"
+ "var rd=new FileReader();"
+ "rd.onload=()=>{"
+ // "console.log(\"rd.onload\");"
+ "var bb=new Uint8Array(rd.result);"
+ // "console.log(bb[0]);"
+ // "console.log(bb.length);"
+ "if(bb.length==1&&bb[0]==0xE9){"
+ "fct(t);" // upload via factory
+ "}else{"
+ "t.form.submit();" // normal upload
+ "};"
+ "};"
+ "rd.readAsArrayBuffer(sl);"
+ "return false;"
+ "};"
+
+ "function fct(t){"
+ "var x=new XMLHttpRequest();"
+ "x.open('GET','/u4?u4=fct&api=',true);"
+ "x.onreadystatechange=()=>{"
+ // "console.log('x.readyState=%%i x.status=%%i',x.readyState,x.status);"
+ "if(x.readyState==4&&x.status==200){"
+ "var s=x.responseText;"
+ // "console.log('responseText:'+s);"
+ "if(s=='false')setTimeout(()=>{fct(t);},6000);"
+ "if(s=='true')su(t);"
+ "}else if(x.readyState==4&&x.status==0){"
+ "setTimeout(()=>{fct(t);},2000);" // retry in 2 seconds
+ "};"
+ "};"
+ "x.send();"
+ // "console.log('after send');"
+ "}"
+ "";
diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h
index 6c7934f76..8d96dd5d8 100644
--- a/tasmota/language/af_AF.h
+++ b/tasmota/language/af_AF.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA Url"
#define D_START_UPGRADE "Begin opgradering"
#define D_UPGRADE_BY_FILE_UPLOAD "Gradeer op volgens lêeroplaai"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Oplaai begin"
#define D_UPGRADE_STARTED "Opgradering is begin"
#define D_UPLOAD_DONE "Oplaai gedoen"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Wagwoord geverifieer" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Fout" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowmeter"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h
index 1e6270266..d38d30f81 100644
--- a/tasmota/language/bg_BG.h
+++ b/tasmota/language/bg_BG.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "Адрес на сървър за OTA"
#define D_START_UPGRADE "Начало на обновяване"
#define D_UPGRADE_BY_FILE_UPLOAD "Обновяване от файл"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Качване"
#define D_UPGRADE_STARTED "Обновяване"
#define D_UPLOAD_DONE "Качването завърши"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Грешка" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h
index 941dd24a2..628a87aca 100644
--- a/tasmota/language/cs_CZ.h
+++ b/tasmota/language/cs_CZ.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "URL OTA"
#define D_START_UPGRADE "Start aktualizace"
#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizace nahráním souboru"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Nahrávání zahájeno"
#define D_UPGRADE_STARTED "Zahájení aktualizace"
#define D_UPLOAD_DONE "Nahrávání ukončeno"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h
index 9218e9537..b4365df39 100644
--- a/tasmota/language/de_DE.h
+++ b/tasmota/language/de_DE.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA-URL"
#define D_START_UPGRADE "Update starten"
#define D_UPGRADE_BY_FILE_UPLOAD "Update Datei hochladen"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Upload gestartet"
#define D_UPGRADE_STARTED "Update gestartet"
#define D_UPLOAD_DONE "Upload abgeschlossen"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Neue Adresse"
#define D_OUT_OF_RANGE "Außerhalb Bereich"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Übereinstimmung" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Fehler" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Durchflussmesser"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h
index 67481f5a2..4ce0c2b43 100644
--- a/tasmota/language/el_GR.h
+++ b/tasmota/language/el_GR.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA URL"
#define D_START_UPGRADE "Εκκίνηση αναβάθμισης"
#define D_UPGRADE_BY_FILE_UPLOAD "Αναβάθμιση με μεταφόρτωση αρχείου"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Η μεταφόρτωση ξεκίνησε"
#define D_UPGRADE_STARTED "Η αναβάθμιση ξεκίνησε"
#define D_UPLOAD_DONE "Η μεταφόρτωση ολοκληρώθηκε"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h
index afa9b3a8f..cdb40a7a7 100644
--- a/tasmota/language/en_GB.h
+++ b/tasmota/language/en_GB.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA Url"
#define D_START_UPGRADE "Start upgrade"
#define D_UPGRADE_BY_FILE_UPLOAD "Upgrade by file upload"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Upload started"
#define D_UPGRADE_STARTED "Upgrade started"
#define D_UPLOAD_DONE "Upload done"
@@ -866,6 +867,7 @@
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h
index b93135578..2479a92d9 100644
--- a/tasmota/language/es_ES.h
+++ b/tasmota/language/es_ES.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA Url"
#define D_START_UPGRADE "Comenzar actualización"
#define D_UPGRADE_BY_FILE_UPLOAD "Actualizar cargando archivo bin"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Cargando archivo"
#define D_UPGRADE_STARTED "Actualización iniciada"
#define D_UPLOAD_DONE "Carga finalizada"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Cambiando dirección a"
#define D_OUT_OF_RANGE "Fuera de Rango"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Clave Correcta" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h
index 5638233b1..37d99584c 100644
--- a/tasmota/language/fr_FR.h
+++ b/tasmota/language/fr_FR.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "URL OTA"
#define D_START_UPGRADE "Lancer la mise à jour"
#define D_UPGRADE_BY_FILE_UPLOAD "Mise à jour par téléchargement fichier"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Téléchargement lancé"
#define D_UPGRADE_STARTED "Mise à jour lancée"
#define D_UPLOAD_DONE "Téléchargement terminé"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Positionner l'adresse à"
#define D_OUT_OF_RANGE "Hors limites"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Mot-de-passe vérifié" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Erreur" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h
index fc97068d3..15b92f7c3 100644
--- a/tasmota/language/fy_NL.h
+++ b/tasmota/language/fy_NL.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA Url"
#define D_START_UPGRADE "Begjin upgrade"
#define D_UPGRADE_BY_FILE_UPLOAD "Upgrade op bestân upload"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Upload begon"
#define D_UPGRADE_STARTED "Upgrade begon"
#define D_UPLOAD_DONE "Upload dien"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h
index dc7be8aa0..e157192cb 100644
--- a/tasmota/language/he_HE.h
+++ b/tasmota/language/he_HE.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA כתובת"
#define D_START_UPGRADE "התחל בשדרוג"
#define D_UPGRADE_BY_FILE_UPLOAD "שדרוג דרך קובץ נכשל"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "העלאה מתחילה"
#define D_UPGRADE_STARTED "שדרוג מתחיל"
#define D_UPLOAD_DONE "העלאה הסתיימה"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h
index 04b069358..e83341bca 100644
--- a/tasmota/language/hu_HU.h
+++ b/tasmota/language/hu_HU.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA URL"
#define D_START_UPGRADE "Frissítés"
#define D_UPGRADE_BY_FILE_UPLOAD "Frissítés helyi fájllal"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Feltöltés elindítva"
#define D_UPGRADE_STARTED "Frissítés elindítva"
#define D_UPLOAD_DONE "Feltöltés kész"
@@ -866,6 +867,7 @@
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Jelszó ellenőrizve" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Hiba" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h
index 769f43241..1bc0ea809 100644
--- a/tasmota/language/it_IT.h
+++ b/tasmota/language/it_IT.h
@@ -28,7 +28,7 @@
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
* Use online command Prefix to translate cmnd, stat and tele.
*
- * Updated until v11.0.0.7 - Last update 19.04.2022
+ * Updated until v9.4.0.1 - Last update 03.05.2022
\*********************************************************************/
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
@@ -372,6 +372,7 @@
#define D_OTA_URL "URL OTA"
#define D_START_UPGRADE "Esegui aggiornamento"
#define D_UPGRADE_BY_FILE_UPLOAD "Aggiornamento tramite file locale"
+#define D_UPLOAD_FACTORY "Passaggio a partizione avvio sicuro"
#define D_UPLOAD_STARTED "Caricamento..."
#define D_UPGRADE_STARTED "Aggiornamento..."
#define D_UPLOAD_DONE "Caricamento completato"
@@ -710,7 +711,7 @@
#define D_SENSOR_MAX31855_CLK "MX31855 - CLK"
#define D_SENSOR_MAX31855_DO "MX31855 - DO"
#define D_SENSOR_MAX31865_CS "MX31865 - CS"
-#define D_SENSOR_NRG_SEL "HLWBL - SEL" // Suffix "i"
+#define D_SENSOR_NRG_SEL "HLWBL - SEL" // Suffix "i"
#define D_SENSOR_NRG_CF1 "HLWBL - CF1"
#define D_SENSOR_HLW_CF "HLW8012 - CF"
#define D_SENSOR_HJL_CF "BL0937 - CF"
@@ -735,7 +736,7 @@
#define D_SENSOR_ARIRFSEL "IR ALux - SEL"
#define D_SENSOR_TXD "Seriale - TX"
#define D_SENSOR_RXD "Seriale - RX"
-#define D_SENSOR_ROTARY "Rotativo" // Suffix "1A"
+#define D_SENSOR_ROTARY "Rotativo" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE - Clock"
#define D_SENSOR_HRE_DATA "HRE - Dati"
#define D_SENSOR_ADE7880_IRQ "ADE7880 - IRQ"
@@ -866,6 +867,7 @@
#define D_GPIO_SHIFT595_SER "74x595 - SER"
#define D_SENSOR_CM11_TX "CM110x - TX"
#define D_SENSOR_CM11_RX "CM110x - RX"
+#define D_SENSOR_FLOWRATEMETER "Portata"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,24 +915,26 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/ora"
#define D_NEW_ADDRESS "Imposta indirizzo a"
#define D_OUT_OF_RANGE "Fuori intervallo"
#define D_SENSOR_DETECTED "rilevato"
//SDM220, SDM120, SDM72, LE01MR, SDM230
-#define D_EXPORT_POWER "Potenza esportata"
-#define D_IMPORT_POWER "Potenza importata"
-#define D_PHASE_ANGLE "Angolo fase"
-#define D_IMPORT_ACTIVE "Potenza attiva importata"
-#define D_EXPORT_ACTIVE "Potenza attiva esportata"
-#define D_IMPORT_REACTIVE "Potenza reattiva importata"
-#define D_EXPORT_REACTIVE "Potenza reattiva esportata"
-#define D_TOTAL_REACTIVE "Potenza reattiva totale"
-#define D_UNIT_KWARH "kVArh"
-#define D_UNIT_ANGLE "°"
-#define D_TOTAL_ACTIVE "Potenza attiva totale"
-#define D_RESETTABLE_TOTAL_ACTIVE "Potenza attiva totale (RST)"
+#define D_EXPORT_POWER "Potenza esportata"
+#define D_IMPORT_POWER "Potenza importata"
+#define D_PHASE_ANGLE "Angolo fase"
+#define D_IMPORT_ACTIVE "Potenza attiva importata"
+#define D_EXPORT_ACTIVE "Potenza attiva esportata"
+#define D_IMPORT_REACTIVE "Potenza reattiva importata"
+#define D_EXPORT_REACTIVE "Potenza reattiva esportata"
+#define D_TOTAL_REACTIVE "Potenza reattiva totale"
+#define D_UNIT_KWARH "kVArh"
+#define D_UNIT_ANGLE "°"
+#define D_TOTAL_ACTIVE "Potenza attiva totale"
+#define D_RESETTABLE_TOTAL_ACTIVE "Potenza attiva totale (RST)"
//SOLAXX1
#define D_PV1_VOLTAGE "PV1 - Voltaggio"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verificata" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Errore" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Portata"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h
index 2716feea4..261345b88 100644
--- a/tasmota/language/ko_KO.h
+++ b/tasmota/language/ko_KO.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA Url"
#define D_START_UPGRADE "업그레이드 시작"
#define D_UPGRADE_BY_FILE_UPLOAD "파일에서 업로드해 업그레이드"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "업로드 시작됨"
#define D_UPGRADE_STARTED "업그레이드 시작됨"
#define D_UPLOAD_DONE "업그레이드 완료"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h
index a7a1e383a..db0de2f7e 100644
--- a/tasmota/language/nl_NL.h
+++ b/tasmota/language/nl_NL.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA Url"
#define D_START_UPGRADE "Start opwaarderen"
#define D_UPGRADE_BY_FILE_UPLOAD "Opwaarderen dmv verzenden bestand"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Verzending gestart"
#define D_UPGRADE_STARTED "Opwaarderen gestart"
#define D_UPLOAD_DONE "Opwaarderen klaar"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Nieuw adres"
#define D_OUT_OF_RANGE "Buiten beriek"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Wachtwoord herkend" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Fout" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h
index 6bec6b159..88eb1f797 100644
--- a/tasmota/language/pl_PL.h
+++ b/tasmota/language/pl_PL.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "Adres serwera"
#define D_START_UPGRADE "Aktualizuj"
#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizacja z pliku"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Wgrywanie rozpoczęte"
#define D_UPGRADE_STARTED "Aktualizacja rozpoczęta"
#define D_UPLOAD_DONE "Wgrywanie zakończone"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Ustawiam adres na"
#define D_OUT_OF_RANGE "Poza zakresem"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Zweryfikowano poprawnie" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Błąd" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h
index 15b574f64..ae3234214 100644
--- a/tasmota/language/pt_BR.h
+++ b/tasmota/language/pt_BR.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA URL"
#define D_START_UPGRADE "Iniciar atualização"
#define D_UPGRADE_BY_FILE_UPLOAD "Atualização por arquivo local"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Início do envio"
#define D_UPGRADE_STARTED "Atualização iniciada"
#define D_UPLOAD_DONE "Atualização finalizada"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "W/h"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Mudança de endereço para"
#define D_OUT_OF_RANGE "Fora de Alcance"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Senha verificada" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Erro" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h
index b664cf3cf..10b0252bc 100644
--- a/tasmota/language/pt_PT.h
+++ b/tasmota/language/pt_PT.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "Url OTA"
#define D_START_UPGRADE "Iniciar atualização"
#define D_UPGRADE_BY_FILE_UPLOAD "Atualizar por envio de ficheiro"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Envio Iniciado"
#define D_UPGRADE_STARTED "Atualização Iniciada"
#define D_UPLOAD_DONE "Atualização Finalizada"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Mudança de endereço para"
#define D_OUT_OF_RANGE "Fora de Alcance"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h
index cb709f185..bdb183bf9 100644
--- a/tasmota/language/ro_RO.h
+++ b/tasmota/language/ro_RO.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA Url"
#define D_START_UPGRADE "Porneste actualizare"
#define D_UPGRADE_BY_FILE_UPLOAD "Actualizare prin încărcare fișier"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Încărcare începută"
#define D_UPGRADE_STARTED "Actualizare începută"
#define D_UPLOAD_DONE "Încărcare terminată"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h
index e45388a22..e37f5142d 100644
--- a/tasmota/language/ru_RU.h
+++ b/tasmota/language/ru_RU.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA Url"
#define D_START_UPGRADE "Начать обновление"
#define D_UPGRADE_BY_FILE_UPLOAD "Обновление путем загрузки файлов"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Загрузка началась"
#define D_UPGRADE_STARTED "Обновление началось"
#define D_UPLOAD_DONE "Загрузка завершена"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "А"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "Вт"
#define D_UNIT_WATTHOUR "ВтЧ"
#define D_UNIT_WATT_METER_QUADRAT "Вт/м²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h
index d376dc26c..564783ee3 100644
--- a/tasmota/language/sk_SK.h
+++ b/tasmota/language/sk_SK.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "URL OTA"
#define D_START_UPGRADE "Spustiť aktualizáciu"
#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizácia nahraním súboru"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Nahrávanie spustené"
#define D_UPGRADE_STARTED "Aktualizácia spustená"
#define D_UPLOAD_DONE "Nahrávanie ukončené"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h
index dbd138ff5..1021c512b 100644
--- a/tasmota/language/sv_SE.h
+++ b/tasmota/language/sv_SE.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA Url"
#define D_START_UPGRADE "Starta uppdatering"
#define D_UPGRADE_BY_FILE_UPLOAD "Uppgradering via filuppladdning"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Uppladdning startad"
#define D_UPGRADE_STARTED "Uppgradeing startad"
#define D_UPLOAD_DONE "Uppladdning klar"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h
index bcb341725..78a0924e5 100644
--- a/tasmota/language/tr_TR.h
+++ b/tasmota/language/tr_TR.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA Url"
#define D_START_UPGRADE "Yükseltmeyi başlat"
#define D_UPGRADE_BY_FILE_UPLOAD "Dosya kullanrak yükset"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Yükleme başlatıldı"
#define D_UPGRADE_STARTED "YÜkestlme başlatıldı"
#define D_UPLOAD_DONE "Yükleme Tamamlandı"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h
index b13930560..e5b948ec7 100644
--- a/tasmota/language/uk_UA.h
+++ b/tasmota/language/uk_UA.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA URL"
#define D_START_UPGRADE "Почати оновлення"
#define D_UPGRADE_BY_FILE_UPLOAD "Оновлення шляхом завантаження файлів"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Завантаження почалось"
#define D_UPGRADE_STARTED "Оновлення почалось"
#define D_UPLOAD_DONE "Завантаження завершено"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "А"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "Вт"
#define D_UNIT_WATTHOUR "Вт/г"
#define D_UNIT_WATT_METER_QUADRAT "Вт/м²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h
index 0f4e5f563..bb9d23a57 100644
--- a/tasmota/language/vi_VN.h
+++ b/tasmota/language/vi_VN.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "Đường dẫn OTA"
#define D_START_UPGRADE "Bắt đầu nâng cấp"
#define D_UPGRADE_BY_FILE_UPLOAD "Nâng cấp thông qua tải lên tệp"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "Bắt đầu tải lên"
#define D_UPGRADE_STARTED "Bắt đầu nâng cấp"
#define D_UPLOAD_DONE "Hoàn thành tải tệp"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h
index 89ad958ca..a5c6381a6 100644
--- a/tasmota/language/zh_CN.h
+++ b/tasmota/language/zh_CN.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA 地址"
#define D_START_UPGRADE "开始升级"
#define D_UPGRADE_BY_FILE_UPLOAD "通过文件升级"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "开始上传"
#define D_UPGRADE_STARTED "开始升级"
#define D_UPLOAD_DONE "上传完成"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "A"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h
index 767df5857..5aab42a00 100644
--- a/tasmota/language/zh_TW.h
+++ b/tasmota/language/zh_TW.h
@@ -372,6 +372,7 @@
#define D_OTA_URL "OTA網址"
#define D_START_UPGRADE "開始升級"
#define D_UPGRADE_BY_FILE_UPLOAD "透過檔案升級"
+#define D_UPLOAD_FACTORY "Switching to safeboot partition"
#define D_UPLOAD_STARTED "已開始上傳"
#define D_UPGRADE_STARTED "已開始升級"
#define D_UPLOAD_DONE "已上傳完成"
@@ -865,7 +866,8 @@
#define D_GPIO_SHIFT595_OE "74x595 OE"
#define D_GPIO_SHIFT595_SER "74x595 SER"
#define D_SENSOR_CM11_TX "CM110x TX"
-#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_CM11_RX "CM110x RX"
+#define D_SENSOR_FLOWRATEMETER "Flowrate"
// Units
#define D_UNIT_AMPERE "安培"
@@ -913,6 +915,8 @@
#define D_UNIT_WATT "瓦特"
#define D_UNIT_WATTHOUR "瓦小時"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
+#define D_UNIT_LITER_PER_MINUTE "l/min"
+#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
#define D_NEW_ADDRESS "Setting address to"
#define D_OUT_OF_RANGE "Out of Range"
@@ -1054,6 +1058,9 @@
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
#define D_FP_UNKNOWNERROR "Error" // Any other error
+// xsns_96_flowratemeter.ino
+#define D_FLOWRATEMETER_NAME "Flowrate"
+
// xsns_83_neopool.ino
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h
index 6a197c5d5..a3344e41f 100644
--- a/tasmota/my_user_config.h
+++ b/tasmota/my_user_config.h
@@ -948,6 +948,8 @@
//#define USE_NEOPOOL // Add support for Sugar Valley NeoPool Controller - also known under brands Hidrolife, Aquascenic, Oxilife, Bionet, Hidroniser, UVScenic, Station, Brilix, Bayrol and Hay (+6k flash, +60 mem)
// #define NEOPOOL_MODBUS_ADDRESS 1 // Any modbus address
+//#define FLOWRATEMETER // Add support for water flow meter YF-DN50 and similary (+1k7 code)
+
// -- Thermostat control ----------------------------
//#define USE_THERMOSTAT // Add support for Thermostat
#define THERMOSTAT_CONTROLLER_OUTPUTS 1 // Number of outputs to be controlled independently
diff --git a/tasmota/settings.h b/tasmota/settings.h
index 4442fd60f..c6d37fe15 100644
--- a/tasmota/settings.h
+++ b/tasmota/settings.h
@@ -366,7 +366,7 @@ typedef union {
uint8_t data;
struct {
uint8_t spare0 : 1;
- uint8_t spare1 : 1;
+ uint8_t flowratemeter_unit : 1; // Sensor96 9,x - unit l/min (0) or m³/h (1)
uint8_t bh1750_2_resolution : 2;
uint8_t bh1750_1_resolution : 2; // Sensor10 1,2,3
uint8_t hx711_json_weight_change : 1; // Sensor34 8,x - Enable JSON message on weight change
@@ -794,10 +794,10 @@ typedef struct {
uint8_t tcp_config; // F5F
uint8_t light_step_pixels; // F60
- uint8_t free_f61[27]; // F61 - Decrement if adding new Setting variables just above and below
+ uint8_t free_f61[23]; // F61 - Decrement if adding new Setting variables just above and below
// Only 32 bit boundary variables below
-
+ uint16_t flowratemeter_calibration[2];// F78
int32_t energy_kWhexport_ph[3]; // F7C
uint32_t eth_ipv4_address[5]; // F88
uint32_t energy_kWhtotal; // F9C
diff --git a/tasmota/support_esp.ino b/tasmota/support_esp.ino
index b671be30e..11f00911c 100644
--- a/tasmota/support_esp.ino
+++ b/tasmota/support_esp.ino
@@ -295,14 +295,37 @@ extern "C" {
#include "rom/spi_flash.h"
#endif
+bool EspSingleOtaPartition(void) {
+ return (1 == esp_ota_get_app_partition_count());
+}
+
+bool EspRunningFactoryPartition(void) {
+ const esp_partition_t *cur_part = esp_ota_get_running_partition();
+ return (cur_part->type == 0 && cur_part->subtype == 0);
+}
+
+void EspPrepRestartToSafeMode(void) {
+// esp_ota_mark_app_invalid_rollback_and_reboot(); // Doesn't work 20220501
+ const esp_partition_t *otadata_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
+ if (otadata_partition) {
+ esp_partition_erase_range(otadata_partition, 0, SPI_FLASH_SEC_SIZE * 2);
+ }
+}
+
uint32_t EspFlashBaseAddress(void) {
- const esp_partition_t* partition = esp_ota_get_next_update_partition(nullptr);
- if (!partition) { return 0; }
- return partition->address; // For tasmota 0x00010000 or 0x00200000
+ if (EspSingleOtaPartition()) { // Only one partition so start at end of sketch
+ const esp_partition_t *running = esp_ota_get_running_partition();
+ if (!running) { return 0; }
+ return running->address + ESP_getSketchSize();
+ } else { // Select other partition
+ const esp_partition_t* partition = esp_ota_get_next_update_partition(nullptr);
+ if (!partition) { return 0; }
+ return partition->address; // For tasmota 0x00010000 or 0x00200000
+ }
}
uint32_t EspFlashBaseEndAddress(void) {
- const esp_partition_t* partition = esp_ota_get_next_update_partition(nullptr);
+ const esp_partition_t* partition = (EspSingleOtaPartition()) ? esp_ota_get_running_partition() : esp_ota_get_next_update_partition(nullptr);
if (!partition) { return 0; }
return partition->address + partition->size; // For tasmota 0x00200000 or 0x003F0000
}
@@ -664,7 +687,7 @@ typedef struct {
if (rev3) { return F("ESP32-PICO-V3"); } // Max 240MHz, Dual core, LGA 7*7, ESP32-PICO-V3-ZERO, ESP32-PICO-V3-ZERO-DevKit
else { return F("ESP32-PICO-D4"); } // Max 240MHz, Dual core, LGA 7*7, 4MB embedded flash, ESP32-PICO-KIT
case 6: return F("ESP32-PICO-V3-02"); // Max 240MHz, Dual core, LGA 7*7, 8MB embedded flash, 2MB embedded PSRAM, ESP32-PICO-MINI-02, ESP32-PICO-DevKitM-2
- case 7: return F("ESP32-D0WDR2-V3"); // Max 240MHz, Dual core, QFN 5*5, ESP32-WROOM-32E, ESP32_WROVER-E, ESP32-DevKitC?
+ case 7: return F("ESP32-D0WDR2-V3"); // Max 240MHz, Dual core, QFN 5*5, ESP32-WROOM-32E, ESP32_WROVER-E, ESP32-DevKitC
}
#endif // CONFIG_IDF_TARGET_ESP32
return F("ESP32");
@@ -672,16 +695,23 @@ typedef struct {
else if (2 == chip_model) { // ESP32-S2
#ifdef CONFIG_IDF_TARGET_ESP32S2
/* esptool:
- def get_pkg_version(self):
+ def get_flash_version(self):
num_word = 3
block1_addr = self.EFUSE_BASE + 0x044
word3 = self.read_reg(block1_addr + (4 * num_word))
pkg_version = (word3 >> 21) & 0x0F
return pkg_version
+
+ def get_psram_version(self):
+ num_word = 3
+ block1_addr = self.EFUSE_BASE + 0x044
+ word3 = self.read_reg(block1_addr + (4 * num_word))
+ pkg_version = (word3 >> 28) & 0x0F
+ return pkg_version
*/
- uint32_t chip_ver = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_PKG_VERSION);
- uint32_t pkg_version = chip_ver & 0x7;
-// uint32_t pkg_version = esp_efuse_get_pkg_ver();
+ uint32_t chip_ver = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_FLASH_VERSION);
+ uint32_t psram_ver = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_PSRAM_VERSION);
+ uint32_t pkg_version = (chip_ver & 0xF) + ((psram_ver & 0xF) * 100);
// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("HDW: ESP32 Model %d, Revision %d, Core %d, Package %d"), chip_info.model, chip_revision, chip_info.cores, chip_ver);
@@ -690,6 +720,8 @@ typedef struct {
case 1: return F("ESP32-S2FH2"); // Max 240MHz, Single core, QFN 7*7, 2MB embedded flash, ESP32-S2-MINI-1, ESP32-S2-DevKitM-1
case 2: return F("ESP32-S2FH4"); // Max 240MHz, Single core, QFN 7*7, 4MB embedded flash
case 3: return F("ESP32-S2FN4R2"); // Max 240MHz, Single core, QFN 7*7, 4MB embedded flash, 2MB embedded PSRAM, , ESP32-S2-MINI-1U, ESP32-S2-DevKitM-1U
+ case 100: return F("ESP32-S2R2");
+ case 102: return F("ESP32-S2FNR2"); // Max 240MHz, Single core, QFN 7*7, 4MB embedded flash, 2MB embedded PSRAM, , Lolin S2 mini
}
#endif // CONFIG_IDF_TARGET_ESP32S2
return F("ESP32-S2");
diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino
index c2e6535c7..bf3b17011 100644
--- a/tasmota/support_features.ino
+++ b/tasmota/support_features.ino
@@ -806,7 +806,9 @@ void ResponseAppendFeatures(void)
#ifdef USE_IMPROV
feature8 |= 0x04000000; // xdrv_62_improv.ino
#endif
-// feature8 |= 0x08000000;
+#ifdef USE_FLOWRATEMETER
+ feature8 |= 0x08000000; // xsns_96_flowratemeter.ino
+#endif
// feature8 |= 0x10000000;
// feature8 |= 0x20000000;
diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino
index a0295d501..2753b33c9 100644
--- a/tasmota/support_tasmota.ino
+++ b/tasmota/support_tasmota.ino
@@ -1242,6 +1242,19 @@ void Every250mSeconds(void)
}
}
#endif // ESP8266
+
+#ifdef ESP32
+#ifndef FIRMWARE_MINIMAL
+ if (EspSingleOtaPartition()) {
+ RtcSettings.ota_loader = 1; // Try safemode image next
+ SettingsSaveAll();
+ AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING));
+ EspPrepRestartToSafeMode();
+ EspRestart();
+ }
+#endif // FIRMWARE_MINIMAL
+#endif // ESP32
+
char version[50];
snprintf_P(version, sizeof(version), PSTR("%s%s"), TasmotaGlobal.version, TasmotaGlobal.image_name);
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s %s"), full_ota_url, version);
diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino
index 04d44e78b..0d3fd0717 100644
--- a/tasmota/support_wifi.ino
+++ b/tasmota/support_wifi.ino
@@ -617,8 +617,7 @@ void WifiConnect(void)
#endif // WIFI_RF_PRE_INIT
}
-void WifiShutdown(bool option = false)
-{
+void WifiShutdown(bool option) {
// option = false - Legacy disconnect also used by DeepSleep
// option = true - Disconnect with SDK wifi calibrate sector erase when WIFI_FORCE_RF_CAL_ERASE enabled
delay(100); // Allow time for message xfer - disabled v6.1.0b
diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h
index 5bae64353..5b4913690 100644
--- a/tasmota/tasmota.h
+++ b/tasmota/tasmota.h
@@ -418,7 +418,7 @@ enum SettingsTextIndex { SET_OTAURL,
#endif // ESP32
SET_SHD_PARAM,
SET_RGX_SSID, SET_RGX_PASSWORD,
- SET_INFLUXDB_HOST, SET_INFLUXDB_PORT, SET_INFLUXDB_ORG, SET_INFLUXDB_TOKEN, SET_INFLUXDB_BUCKET,
+ SET_INFLUXDB_HOST, SET_INFLUXDB_PORT, SET_INFLUXDB_ORG, SET_INFLUXDB_TOKEN, SET_INFLUXDB_BUCKET, SET_INFLUXDB_RP,
SET_MAX };
enum SpiInterfaces { SPI_NONE, SPI_MOSI, SPI_MISO, SPI_MOSI_MISO };
diff --git a/tasmota/tasmota_configurations_ESP32.h b/tasmota/tasmota_configurations_ESP32.h
index c79d7f287..d85b93e09 100644
--- a/tasmota/tasmota_configurations_ESP32.h
+++ b/tasmota/tasmota_configurations_ESP32.h
@@ -22,6 +22,150 @@
#ifdef ESP32
+/*********************************************************************************************\
+ * [tasmota32x-safemode.bin]
+ * Provide an image with useful supported sensors enabled
+\*********************************************************************************************/
+
+#ifdef FIRMWARE_SAFEMODE
+#define FIRMWARE_MINIMAL
+
+#undef CODE_IMAGE_STR
+#define CODE_IMAGE_STR "safemode"
+
+#define USE_TLS
+#define USE_WEBSERVER
+#define USE_WEBCLIENT
+#define USE_WEBCLIENT_HTTPS
+
+#undef USE_UFILESYS
+#undef GUI_TRASH_FILE
+#undef GUI_EDIT_FILE
+#undef USE_PING
+#undef USE_AUTOCONF
+#undef USE_BERRY
+
+#undef FIRMWARE_LITE // Disable tasmota-lite with no sensors
+#undef FIRMWARE_SENSORS // Disable tasmota-sensors with useful sensors enabled
+#undef FIRMWARE_KNX_NO_EMULATION // Disable tasmota-knx with KNX but without Emulation
+#undef FIRMWARE_DISPLAYS // Disable tasmota-display with display drivers enabled
+#undef FIRMWARE_IR // Disable tasmota-ir with IR full protocols activated
+#undef FIRMWARE_WEBCAM
+#undef FIRMWARE_BLUETOOTH
+#undef FIRMWARE_LVGL
+#undef FIRMWARE_TASMOTA32
+
+#undef USE_IMPROV // Disable support for IMPROV serial protocol as used by esp-web-tools (+2k code)
+#undef USE_TASMESH // Disable Tasmota Mesh using ESP-NOW (+11k code)
+#undef USE_ARDUINO_OTA // Disable support for Arduino OTA
+#undef USE_INFLUXDB // Disable influxdb support (+5k code)
+#undef USE_DOMOTICZ // Disable Domoticz
+#undef USE_HOME_ASSISTANT // Disable Home Assistant
+#undef USE_TASMOTA_DISCOVERY // Disable Tasmota Discovery support (+2k code)
+#undef USE_TELEGRAM // Disable support for Telegram protocol (+49k code, +7.0k mem and +4.8k additional during connection handshake)
+//#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set
+#undef USE_KNX // Disable KNX IP Protocol Support
+//#undef USE_WEBSERVER // Disable Webserver
+#undef USE_ENHANCED_GUI_WIFI_SCAN // Disable wifi scan output with BSSID (+0k5 code)
+#undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code)
+#undef USE_EMULATION // Disable Wemo or Hue emulation
+#undef USE_EMULATION_HUE // Disable Hue Bridge emulation for Alexa (+14k code, +2k mem common)
+#undef USE_EMULATION_WEMO // Disable Belkin WeMo emulation for Alexa (+6k code, +2k mem common)
+#undef USE_CUSTOM // Disable Custom features
+#undef USE_DISCOVERY // Disable Discovery services for both MQTT and web server
+#undef USE_TIMERS // Disable support for up to 16 timers
+#undef USE_TIMERS_WEB // Disable support for timer webpage
+#undef USE_SUNRISE // Disable support for Sunrise and sunset tools
+#undef USE_PING // Disable Ping command (+2k code)
+#undef USE_UNISHOX_COMPRESSION // Disable support for string compression in Rules or Scripts
+#undef USE_RULES // Disable support for rules
+#undef USE_SCRIPT // Disable support for script
+
+// -- Optional modules ----------------------------
+#undef ROTARY_V1 // Disable support for MI Desk Lamp
+#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code)
+ #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB
+#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code)
+#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU
+#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
+#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
+#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code)
+#undef USE_BUZZER // Disable support for a buzzer (+0k6 code)
+#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller
+#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code)
+#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code)
+#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer
+#undef USE_HOTPLUG // Disable support for HotPlug
+#undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code)
+#undef USE_PWM_DIMMER // Disable support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code)
+#undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer
+#undef USE_KEELOQ // Disable support for Jarolift rollers by Keeloq algorithm (+4k5 code)
+#undef USE_SONOFF_D1 // Disable support for Sonoff D1 Dimmer (+0k7 code)
+#undef USE_SHELLY_DIMMER // Disable support for Shelly Dimmer (+3k code)
+
+// -- Optional light modules ----------------------
+#undef USE_LIGHT // Disable support for lights
+
+#undef USE_COUNTER // Disable counters
+#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices
+#undef USE_DS18x20 // Disable DS18x20 sensor
+
+#undef USE_I2C // Disable all I2C sensors and devices
+#undef USE_SPI // Disable all SPI devices
+#undef USE_DISPLAY // Disable Display support
+
+#undef USE_MHZ19 // Disable support for MH-Z19 CO2 sensor
+#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor
+#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor
+#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor
+#undef USE_HPMA // Disable support for Honeywell HPMA115S0 particle concentration sensor
+#undef USE_SR04 // Disable support for HC-SR04 ultrasonic devices (+1k code)
+#undef USE_DYP // Disable support for DYP ME-007 ultrasonic distance sensor, serial port version (+0k5 code)
+#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge
+#undef USE_TCP_BRIDGE // DIsable support for Serial to TCP bridge (+1.3k code)
+#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop
+#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger
+#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem)
+#undef USE_ZIGBEE // Disable serial communication with Zigbee CC2530 flashed with ZNP
+#undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8)
+#undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module)
+#undef USE_GPS // Disable support for GPS and NTP Server for becoming Stratus 1 Time Source (+ 3.1kb flash, +132 bytes RAM)
+#undef USE_HM10 // (ESP8266 only) Disable support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code)
+#undef USE_BLE_ESP32 // (ESP32 only) Disable support for native BLE on ESP32 - use new driver
+#undef USE_MI_ESP32 // (ESP32 only) Disable support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash)
+#undef USE_HRXL // Disable support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7)
+#undef USE_TASMOTA_CLIENT // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem)
+#undef USE_OPENTHERM // Disable support for OpenTherm (+15k code)
+#undef USE_MIEL_HVAC // Disable support for Mitsubishi Electric HVAC serial interface (+5k code)
+#undef USE_PROJECTOR_CTRL // Disable support for LCD/DLP Projector serial control interface
+#undef USE_AS608 // Disable support for AS608 optical and R503 capacitive fingerprint sensor (+3k4 code)
+#undef USE_TFMINIPLUS // Disable support for TFmini Plus (TFmini, TFmini-S) LiDAR modules via UART interface (+0k8)
+#undef USE_HRG15 // Disable support for Hydreon RG-15 Solid State Rain sensor (+1k5 code)
+#undef USE_VINDRIKTNING // Disable support for IKEA VINDRIKTNING particle concentration sensor (+0k6 code)
+
+#undef USE_ENERGY_SENSOR // Disable energy sensors
+
+#undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor
+#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI
+#undef USE_MAX31865 // Disable support for MAX31865 RTD sensors using softSPI
+#undef USE_LMT01 // Disable support for TI LMT01 temperature sensor, count pulses on single GPIO (+0k5 code)
+#undef USE_IR_REMOTE // Disable IR driver
+#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8
+#undef USE_HX711 // Disable support for HX711 load cell
+#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer
+#undef USE_TX23_WIND_SENSOR // Disable support for La Crosse TX23 anemometer
+#undef USE_WINDMETER // Disable support for analog anemometer (+2k2 code)
+#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch
+#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
+#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code)
+#undef USE_A4988_STEPPER // Disable support for A4988_Stepper
+#undef USE_THERMOSTAT // Disable support for Thermostat
+#undef USE_PROMETHEUS // Disable support for https://prometheus.io/ metrics exporting over HTTP /metrics endpoint
+#undef DEBUG_THEO // Disable debug code
+#undef USE_DEBUG_DRIVER // Disable debug code
+#undef USE_AC_ZERO_CROSS_DIMMER // Disable support for AC_ZERO_CROSS_DIMMER
+#endif // FIRMWARE_SAFEMODE
+
/*********************************************************************************************\
* [tasmota32-webcam.bin]
* Provide an image with useful supported sensors enabled
diff --git a/tasmota/tasmota_globals.h b/tasmota/tasmota_globals.h
index e30bfe22f..ddeab70a3 100644
--- a/tasmota/tasmota_globals.h
+++ b/tasmota/tasmota_globals.h
@@ -38,6 +38,7 @@ extern "C" {
void KNX_CB_Action(message_t const &msg, void *arg);
#endif // USE_KNX
+void WifiShutdown(bool option = false);
void DomoticzTempHumPressureSensor(float temp, float hum, float baro = -1);
char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween = '\0');
extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end);
diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h
index b576027b3..5c6fa8237 100644
--- a/tasmota/tasmota_template.h
+++ b/tasmota/tasmota_template.h
@@ -187,6 +187,7 @@ enum UserSelectablePins {
GPIO_RESET, // Generic reset
GPIO_MS01, // Sonoff MS01 Moisture Sensor 1wire interface
GPIO_SDIO_CMD, GPIO_SDIO_CLK, GPIO_SDIO_D0, GPIO_SDIO_D1, GPIO_SDIO_D2, GPIO_SDIO_D3, // SD Card SDIO interface, including 1-bit and 4-bit modes
+ GPIO_FLOWRATEMETER_IN, // Flowrate Meter
GPIO_SENSOR_END };
enum ProgramSelectablePins {
@@ -418,12 +419,14 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_SDIO_D1 "|"
D_SENSOR_SDIO_D2 "|"
D_SENSOR_SDIO_D3 "|"
+ D_SENSOR_FLOWRATEMETER "|"
;
const char kSensorNamesFixed[] PROGMEM =
D_SENSOR_USER;
#define MAX_MAX31865S 6
+#define MAX_FLOWRATEMETER 2
#define MAX_A4988_MSS 3
#define MAX_WEBCAM_DATA 8
#define MAX_WEBCAM_HSD 3
@@ -973,6 +976,11 @@ const uint16_t kGpioNiceList[] PROGMEM = {
AGPIO(GPIO_CM11_TXD), // CM110x Serial interface
AGPIO(GPIO_CM11_RXD), // CM110x Serial interface
#endif
+
+#if defined(USE_FLOWRATEMETER)
+ AGPIO(GPIO_FLOWRATEMETER_IN) + MAX_FLOWRATEMETER, // Flow meter Pin
+#endif
+
/*-------------------------------------------------------------------------------------------*\
* ESP32 specifics
\*-------------------------------------------------------------------------------------------*/
diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino
index a977b5479..2c1646ab9 100644
--- a/tasmota/xdrv_01_webserver.ino
+++ b/tasmota/xdrv_01_webserver.ino
@@ -209,10 +209,12 @@ const char HTTP_SCRIPT_INFO_END[] PROGMEM =
#ifdef USE_UNISHOX_COMPRESSION
#include "./html_compressed/HTTP_HEAD_LAST_SCRIPT.h"
+ #include "./html_compressed/HTTP_HEAD_LAST_SCRIPT32.h"
#include "./html_compressed/HTTP_HEAD_STYLE1.h"
#include "./html_compressed/HTTP_HEAD_STYLE2.h"
#else
#include "./html_uncompressed/HTTP_HEAD_LAST_SCRIPT.h"
+ #include "./html_uncompressed/HTTP_HEAD_LAST_SCRIPT32.h"
#include "./html_uncompressed/HTTP_HEAD_STYLE1.h"
#include "./html_uncompressed/HTTP_HEAD_STYLE2.h"
#endif
@@ -241,7 +243,11 @@ const char HTTP_HEAD_STYLE3[] PROGMEM =
""
"" // COLOR_TEXT
#ifdef FIRMWARE_MINIMAL
+#ifdef FIRMWARE_SAFEMODE
+ "
SafeMode
" // COLOR_TEXT_SUCCESS
+#else
"
" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "
" // COLOR_TEXT_WARNING
+#endif
#endif
"
" // COLOR_TITLE
/*
@@ -352,7 +358,17 @@ const char HTTP_FORM_RST_UPG[] PROGMEM =
"
"
""
"
"
- "
" D_UPLOAD_STARTED " ...
";
+ "
" D_UPLOAD_STARTED "...
";
+
+// upload via factory partition
+const char HTTP_FORM_RST_UPG_FCT[] PROGMEM =
+ "
"
+ ""
+ "
"
+ "" D_UPLOAD_FACTORY "...
"
+ "" D_UPLOAD_STARTED "...
";
const char HTTP_FORM_CMND[] PROGMEM =
"
"
@@ -523,6 +539,9 @@ const WebServerDispatch_t WebServerDispatch[] PROGMEM = {
{ "u1", HTTP_ANY, HandleUpgradeFirmwareStart }, // OTA
{ "u2", HTTP_OPTIONS, HandlePreflightRequest },
{ "u3", HTTP_ANY, HandleUploadDone },
+#ifdef ESP32
+ { "u4", HTTP_GET, HandleSwitchFactory },
+#endif // ESP32
{ "mn", HTTP_GET, HandleManagement },
{ "cs", HTTP_GET, HandleConsole },
{ "cs", HTTP_OPTIONS, HandlePreflightRequest },
@@ -841,7 +860,11 @@ void WSContentSendStyle_P(const char* formatP, ...) {
WSContentSend_P(HTTP_SCRIPT_COUNTER);
}
}
+#ifdef ESP32
+ WSContentSend_P(HTTP_HEAD_LAST_SCRIPT32);
+#else
WSContentSend_P(HTTP_HEAD_LAST_SCRIPT);
+#endif
WSContentSend_P(HTTP_HEAD_STYLE1, WebColor(COL_FORM), WebColor(COL_INPUT), WebColor(COL_INPUT_TEXT), WebColor(COL_INPUT),
WebColor(COL_INPUT_TEXT), WebColor(COL_CONSOLE), WebColor(COL_CONSOLE_TEXT), WebColor(COL_BACKGROUND));
@@ -860,7 +883,11 @@ void WSContentSendStyle_P(const char* formatP, ...) {
}
WSContentSend_P(HTTP_HEAD_STYLE3, WebColor(COL_TEXT),
#ifdef FIRMWARE_MINIMAL
+#ifdef FIRMWARE_SAFEMODE
+ WebColor(COL_TEXT_SUCCESS),
+#else
WebColor(COL_TEXT_WARNING),
+#endif
#endif
WebColor(COL_TITLE),
(Web.initial_config) ? "" : ModuleName().c_str(), SettingsText(SET_DEVICENAME));
@@ -2283,7 +2310,15 @@ void HandleRestoreConfiguration(void)
WSContentStart_P(PSTR(D_RESTORE_CONFIGURATION));
WSContentSendStyle();
WSContentSend_P(HTTP_FORM_RST);
+#ifdef ESP32
+ if (EspSingleOtaPartition() && !EspRunningFactoryPartition()) {
+ WSContentSend_P(HTTP_FORM_RST_UPG_FCT, PSTR(D_RESTORE));
+ } else {
+ WSContentSend_P(HTTP_FORM_RST_UPG, PSTR(D_RESTORE));
+ }
+#else
WSContentSend_P(HTTP_FORM_RST_UPG, PSTR(D_RESTORE));
+#endif
if (WifiIsInManagerMode()) {
WSContentSpaceButton(BUTTON_MAIN);
} else {
@@ -2508,7 +2543,15 @@ void HandleUpgradeFirmware(void) {
WSContentStart_P(PSTR(D_FIRMWARE_UPGRADE));
WSContentSendStyle();
WSContentSend_P(HTTP_FORM_UPG, SettingsText(SET_OTAURL));
+#ifdef ESP32
+ if (EspSingleOtaPartition() && !EspRunningFactoryPartition()) {
+ WSContentSend_P(HTTP_FORM_RST_UPG_FCT, PSTR(D_UPGRADE));
+ } else {
+ WSContentSend_P(HTTP_FORM_RST_UPG, PSTR(D_UPGRADE));
+ }
+#else
WSContentSend_P(HTTP_FORM_RST_UPG, PSTR(D_UPGRADE));
+#endif
WSContentSpaceButton(BUTTON_MAIN);
WSContentStop();
@@ -2884,6 +2927,80 @@ void HandlePreflightRequest(void)
/*-------------------------------------------------------------------------------------------*/
+#ifdef ESP32
+// Check if we are in single-mode OTA, if so restart to factory mode
+//
+// Parameter `u4` is either `fct` or `ota` to switch to factory or ota
+//
+// The page can return the followinf (code 200)
+// `false`: the current partition is not the target, but a restart to factory is triggered (polling required)
+// `true`: the current partition is the one required
+// `none`: there is no factory partition
+
+// return a simple status page as text/plain code 200
+static void WSReturnSimpleString(const char *msg) {
+ if (nullptr == msg) { msg = ""; }
+ Webserver->client().flush();
+ WSHeaderSend();
+ Webserver->send(200, "text/plain", msg);
+}
+
+void HandleSwitchFactory(void)
+{
+ if (!HttpCheckPriviledgedAccess()) { return; }
+
+ char tmp1[8];
+ WebGetArg(PSTR("u4"), tmp1, sizeof(tmp1));
+
+ bool switch_factory = false; // trigger a restart to factory partition?
+ bool switch_ota = false; // switch back to OTA partition
+ bool single_ota = false;
+ bool api_mode = Webserver->hasArg("api"); // api-mode, returns `true`, `false` or `none`
+
+ // switch to factory ?
+ if (EspSingleOtaPartition()) {
+ single_ota = true;
+ if (strcmp("fct", tmp1) == 0 && !EspRunningFactoryPartition()) {
+ switch_factory = true;
+ }
+ // switch to OTA
+ else if (strcmp("ota", tmp1) == 0 && EspRunningFactoryPartition()) {
+ switch_ota = true;
+ }
+ }
+
+ // apply the change in flash and return result
+ if (switch_factory || switch_ota) {
+ SettingsSaveAll();
+ if (switch_factory) {
+ EspPrepRestartToSafeMode();
+ } else {
+ const esp_partition_t* partition = esp_ota_get_next_update_partition(nullptr);
+ esp_ota_set_boot_partition(partition);
+ }
+
+ if (api_mode) {
+ WSReturnSimpleString("false");
+ AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_RESTART));
+ EspRestart();
+ } else {
+ WebRestart(0);
+ }
+ } else {
+ if (api_mode) {
+ // return `none` or `true`
+ WSReturnSimpleString(EspSingleOtaPartition() ? "true" : "none");
+ } else {
+ Webserver->sendHeader("Location", "/", true);
+ Webserver->send(302, "text/plain", "");
+ }
+ }
+ Web.upload_file_type = UPL_TASMOTA;
+}
+#endif // ESP32
+
+/*-------------------------------------------------------------------------------------------*/
+
void HandleHttpCommand(void)
{
if (!HttpCheckPriviledgedAccess(false)) { return; }
diff --git a/tasmota/xdrv_52_3_berry_mqtt.ino b/tasmota/xdrv_52_3_berry_mqtt.ino
index e02b45f28..77525039c 100644
--- a/tasmota/xdrv_52_3_berry_mqtt.ino
+++ b/tasmota/xdrv_52_3_berry_mqtt.ino
@@ -70,20 +70,20 @@ extern "C" {
int32_t l_publish(struct bvm *vm) {
return be_mqtt_publish(vm, true);
}
-}
-int32_t be_mqtt_publish(struct bvm *vm) {
- return be_mqtt_publish(vm, false);
-}
+ int32_t be_mqtt_publish(struct bvm *vm) {
+ return be_mqtt_publish(vm, false);
+ }
-void be_mqtt_subscribe(const char* topic) {
- if (!topic) { return; }
- MqttSubscribe(topic);
-}
+ void be_mqtt_subscribe(const char* topic) {
+ if (!topic) { return; }
+ MqttSubscribe(topic);
+ }
-void be_mqtt_unsubscribe(const char* topic) {
- if (!topic) { return; }
- MqttUnsubscribe(topic);
+ void be_mqtt_unsubscribe(const char* topic) {
+ if (!topic) { return; }
+ MqttUnsubscribe(topic);
+ }
}
#endif // USE_BERRY
diff --git a/tasmota/xdrv_52_3_berry_tasmota.ino b/tasmota/xdrv_52_3_berry_tasmota.ino
index 6b9fd8842..3e2c85f13 100644
--- a/tasmota/xdrv_52_3_berry_tasmota.ino
+++ b/tasmota/xdrv_52_3_berry_tasmota.ino
@@ -381,7 +381,7 @@ extern "C" {
if (top == 2 && be_isstring(vm, 2)) {
const char *msg = be_tostring(vm, 2);
strlcpy(XdrvMailbox.command, msg, CMDSZ);
- be_return_nil(vm); // Return nil when something goes wrong
+ be_return_nil(vm);
}
be_raise(vm, kTypeError, nullptr);
}
@@ -394,7 +394,7 @@ extern "C" {
const char *msg = be_tostring(vm, 2);
be_pop(vm, top); // avoid Error be_top is non zero message
ResponseAppend_P(PSTR("%s"), msg);
- be_return_nil(vm); // Return nil when something goes wrong
+ be_return_nil(vm);
}
be_raise(vm, kTypeError, nullptr);
}
diff --git a/tasmota/xdrv_52_7_berry_embedded.ino b/tasmota/xdrv_52_7_berry_embedded.ino
index 5e5b4f165..4ad02b900 100644
--- a/tasmota/xdrv_52_7_berry_embedded.ino
+++ b/tasmota/xdrv_52_7_berry_embedded.ino
@@ -75,6 +75,10 @@ const char berry_prog[] =
"import tapp "
+#ifdef USE_BERRY_DEBUG
+ "import debug "
+ "import solidify "
+#endif
;
#endif // USE_BERRY
diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino
index 47085ada8..5e5c3e0e5 100644
--- a/tasmota/xdrv_52_9_berry.ino
+++ b/tasmota/xdrv_52_9_berry.ino
@@ -108,12 +108,14 @@ extern "C" {
// If event == nullptr, then take XdrvMailbox.data
bool callBerryRule(const char *event, bool teleperiod) {
- if (berry.rules_busy) { return false; }
+ bool save_rules_busy = berry.rules_busy;
+ bool exec_rule = !save_rules_busy; // true if the rule is executed, false if we only record the value
+ // if (berry.rules_busy) { return false; }
berry.rules_busy = true;
char * json_event = XdrvMailbox.data;
bool serviced = false;
- serviced = callBerryEventDispatcher(teleperiod ? "tele" : "rule", nullptr, 0, event ? event : XdrvMailbox.data);
- berry.rules_busy = false;
+ serviced = callBerryEventDispatcher(teleperiod ? "tele" : "rule", nullptr, exec_rule, event ? event : XdrvMailbox.data);
+ berry.rules_busy = save_rules_busy;
return serviced; // TODO event not handled
}
diff --git a/tasmota/xdrv_59_influxdb.ino b/tasmota/xdrv_59_influxdb.ino
index 70f9b2803..48adb935c 100644
--- a/tasmota/xdrv_59_influxdb.ino
+++ b/tasmota/xdrv_59_influxdb.ino
@@ -39,8 +39,7 @@
* IfxToken - Set Influxdb v2 and token
* IfxPeriod - Set Influxdb period. If not set (or 0), use Teleperiod
* IfxSensor - Set Influxdb sensor logging off (0) or on (1)
- *
- * Set influxdb update interval with command teleperiod
+ * IfxRP - Set Influxdb retention policy
*
* The following triggers result in automatic influxdb numeric feeds without appended time:
* - this driver initiated state message
@@ -73,6 +72,9 @@
#ifndef INFLUXDB_BUCKET
#define INFLUXDB_BUCKET "db" // [IfxDatabase, IfxBucket] Influxdb v1 database or v2 bucket
#endif
+#ifndef INFLUXDB_RP
+#define INFLUXDB_RP "" // [IfxRP] Influxdb v1 retention policy (blank is default, usually autogen infinite)
+#endif
static const char UninitializedMessage[] PROGMEM = "Unconfigured instance";
// This cannot be put to PROGMEM due to the way how it is used
@@ -132,6 +134,10 @@ bool InfluxDbParameterInit(void) {
IFDB._writeUrl += "/write?db=";
IFDB._writeUrl += UrlEncode(SettingsText(SET_INFLUXDB_BUCKET));
IFDB._writeUrl += InfluxDbAuth();
+ if (strlen(SettingsText(SET_INFLUXDB_RP)) != 0) {
+ IFDB._writeUrl += "&rp=";
+ IFDB._writeUrl += UrlEncode(SettingsText(SET_INFLUXDB_RP));
+ }
}
AddLog(LOG_LEVEL_DEBUG, PSTR("IFX: Url %s"), IFDB._writeUrl.c_str());
@@ -427,6 +433,7 @@ void InfluxDbLoop(void) {
#define D_CMND_INFLUXDBBUCKET "Bucket"
#define D_CMND_INFLUXDBPERIOD "Period"
#define D_CMND_INFLUXDBSENSOR "Sensor"
+#define D_CMND_INFLUXDBRP "RP"
const char kInfluxDbCommands[] PROGMEM = D_PRFX_INFLUXDB "|" // Prefix
"|" D_CMND_INFLUXDBLOG "|"
@@ -434,7 +441,7 @@ const char kInfluxDbCommands[] PROGMEM = D_PRFX_INFLUXDB "|" // Prefix
D_CMND_INFLUXDBUSER "|" D_CMND_INFLUXDBORG "|"
D_CMND_INFLUXDBPASSWORD "|" D_CMND_INFLUXDBTOKEN "|"
D_CMND_INFLUXDBDATABASE "|" D_CMND_INFLUXDBBUCKET "|"
- D_CMND_INFLUXDBPERIOD "|" D_CMND_INFLUXDBSENSOR;
+ D_CMND_INFLUXDBPERIOD "|" D_CMND_INFLUXDBSENSOR "|" D_CMND_INFLUXDBRP;
void (* const InfluxCommand[])(void) PROGMEM = {
&CmndInfluxDbState, &CmndInfluxDbLog,
@@ -442,7 +449,7 @@ void (* const InfluxCommand[])(void) PROGMEM = {
&CmndInfluxDbUser, &CmndInfluxDbUser,
&CmndInfluxDbPassword, &CmndInfluxDbPassword,
&CmndInfluxDbDatabase, &CmndInfluxDbDatabase,
- &CmndInfluxDbPeriod, &CmndInfluxDbSensor };
+ &CmndInfluxDbPeriod, &CmndInfluxDbSensor, &CmndInfluxDbRP };
void InfluxDbReinit(void) {
IFDB.init = false;
@@ -532,6 +539,14 @@ void CmndInfluxDbDatabase(void) {
ResponseCmndChar(SettingsText(SET_INFLUXDB_BUCKET));
}
+void CmndInfluxDbRP(void) {
+ if (XdrvMailbox.data_len > 0) {
+ SettingsUpdateText(SET_INFLUXDB_RP, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? PSTR(INFLUXDB_RP) : XdrvMailbox.data);
+ InfluxDbReinit();
+ }
+ ResponseCmndChar(SettingsText(SET_INFLUXDB_RP));
+}
+
void CmndInfluxDbPeriod(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings->influxdb_period = XdrvMailbox.payload;
@@ -559,6 +574,7 @@ bool Xdrv59(uint8_t function) {
SettingsUpdateText(SET_INFLUXDB_ORG, PSTR(INFLUXDB_ORG));
SettingsUpdateText(SET_INFLUXDB_TOKEN, PSTR(INFLUXDB_TOKEN));
SettingsUpdateText(SET_INFLUXDB_BUCKET, PSTR(INFLUXDB_BUCKET));
+ SettingsUpdateText(SET_INFLUXDB_RP, PSTR(INFLUXDB_RP));
Settings->sbflag1.influxdb_default = 1;
}
} else if (FUNC_COMMAND == function) {
diff --git a/tasmota/xnrg_12_solaxX1.ino b/tasmota/xnrg_12_solaxX1.ino
index 9be2e7194..6bad53255 100644
--- a/tasmota/xnrg_12_solaxX1.ino
+++ b/tasmota/xnrg_12_solaxX1.ino
@@ -30,6 +30,8 @@
#define SOLAXX1_SPEED 9600 // default solax rs485 speed
#endif
+#define SOLAXX1_READCONFIG // enable to read inverters config; disable to save codespace (3k1)
+
#define INVERTER_ADDRESS 0x0A
#define D_SOLAX_X1 "SolaxX1"
@@ -44,10 +46,12 @@ const char kSolaxError[] PROGMEM =
D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|"
D_SOLAX_ERROR_6 "|" D_SOLAX_ERROR_7 "|" D_SOLAX_ERROR_8;
+#ifdef SOLAXX1_READCONFIG
const char kSolaxSafetyType[] PROGMEM =
"VDE0126|ARN4105|AS4777_AU|G98/1|C10/11|OVE/ONORME8001|EN50438_NL|EN50438_DK|CEB|CEI021|NRS097_2_1|"
"VDE0126_Gr_Is|UTE_C15_712|IEC61727|G99/1|VDE0126_Gr_Co|France_VFR2014|C15_712_is_50|C15_712_is_60|"
"AS4777_NZ|RD1699|Chile|EN50438_Ireland|Philippines|Czech_PPDS|Czech_50438";
+#endif // SOLAXX1_READCONFIG
union {
uint32_t ErrMessage;
@@ -333,11 +337,12 @@ void solaxX1_250MSecond(void) // Every 250 milliseconds
return;
} // end received "Response for query (ID data)"
+#ifdef SOLAXX1_READCONFIG
if (DataRead[6] == 0x11 && DataRead[7] == 0x84) { // received "Response for query (config data)"
if (solaxX1_global.Command_QueryConfig) {
// This values are displayed as they were received from the inverter. They are not interpreted in any way.
TempFloat = ((DataRead[9] << 8) | DataRead[10]) * 0.1f;
- AddLog(LOG_LEVEL_INFO, PSTR("SX1: new wVpvStart: %1_f V (Inverter launch voltage threshold)"), &TempFloat);
+ AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVpvStart: %1_f V (Inverter launch voltage threshold)"), &TempFloat);
AddLog(LOG_LEVEL_INFO, PSTR("SX1: wTimeStart: %d sec (launch wait time)"), (DataRead[11] << 8) | DataRead[12]);
TempFloat = ((DataRead[13] << 8) | DataRead[14]) * 0.1f;
AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVacMinProtect: %1_f V (allowed minimum grid voltage)"), &TempFloat);
@@ -400,6 +405,7 @@ void solaxX1_250MSecond(void) // Every 250 milliseconds
DEBUG_SENSOR_LOG(PSTR("SX1: received config data"));
return;
} // end received "Response for query (config data)"
+#endif // SOLAXX1_READCONFIG
if (DataRead[6] == 0x10 && DataRead[7] == 0x80) { // received "register request"
solaxX1_global.QueryData_count = 5; // give time for next query
@@ -489,9 +495,14 @@ bool SolaxX1_cmd(void)
AddLog(LOG_LEVEL_INFO, PSTR("SX1: ReadIDinfo sent..."));
return true;
} else if (!strcasecmp(XdrvMailbox.data, "ReadConfig")) {
+#ifdef SOLAXX1_READCONFIG
solaxX1_global.Command_QueryConfig = true;
AddLog(LOG_LEVEL_INFO, PSTR("SX1: ReadConfig sent..."));
return true;
+#else
+ AddLog(LOG_LEVEL_INFO, PSTR("SX1: Command not available. Please set compiler directive '#define SOLAXX1_READCONFIG'."));
+ return false;
+#endif // SOLAXX1_READCONFIG
}
AddLog(LOG_LEVEL_INFO, PSTR("SX1: Unknown command: \"%s\""),XdrvMailbox.data);
return false;
@@ -510,7 +521,7 @@ const char HTTP_SNS_solaxX1_DATA2[] PROGMEM =
"{s}" D_SOLAX_X1 " " D_PV2_POWER "{m}%s " D_UNIT_WATT "{e}";
#endif
const char HTTP_SNS_solaxX1_DATA3[] PROGMEM =
- "{s}" D_SOLAX_X1 " " D_UPTIME "{m}%s " D_UNIT_HOUR "{e}"
+ "{s}" D_SOLAX_X1 " " D_UPTIME "{m}%d " D_UNIT_HOUR "{e}"
"{s}" D_SOLAX_X1 " " D_STATUS "{m}%s"
"{s}" D_SOLAX_X1 " " D_ERROR "{m}%s"
"{s}" D_SOLAX_X1 " Inverter SN{m}%s";
@@ -534,8 +545,6 @@ void solaxX1_Show(bool json)
char pv2_power[33];
dtostrfd(solaxX1.dc2_power, Settings->flag2.wattage_resolution, pv2_power);
#endif
- char runtime[33];
- dtostrfd(solaxX1.runtime_total, 0, runtime);
char status[33];
GetTextIndexed(status, sizeof(status), solaxX1.runMode + 1, kSolaxMode);
@@ -546,8 +555,8 @@ void solaxX1_Show(bool json)
ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"),
pv2_voltage, pv2_current, pv2_power);
#endif
- ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%d,\"" D_JSON_RUNTIME "\":%s,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"),
- solaxX1.temperature, runtime, status, solaxX1.errorCode);
+ ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%d,\"" D_JSON_RUNTIME "\":%d,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"),
+ solaxX1.temperature, solaxX1.runtime_total, status, solaxX1.errorCode);
#ifdef USE_DOMOTICZ
// Avoid bad temperature report at beginning of the day (spikes of 1200 celsius degrees)
@@ -562,7 +571,7 @@ void solaxX1_Show(bool json)
#endif
WSContentSend_Temp(D_SOLAX_X1, solaxX1.temperature);
char errorCodeString[33];
- WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, runtime, status,
+ WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, solaxX1.runtime_total, status,
GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError),
solaxX1.SerialNumber);
#endif // USE_WEBSERVER
diff --git a/tasmota/xsns_96_flowratemeter.ino b/tasmota/xsns_96_flowratemeter.ino
new file mode 100644
index 000000000..1b727dba0
--- /dev/null
+++ b/tasmota/xsns_96_flowratemeter.ino
@@ -0,0 +1,268 @@
+/*
+ xsns_96_flowratemeter.ino - flowratemeter support for Tasmota
+ - up to two flowratemeter YF-DN50 and similary
+ - flow rate frequencies f = 1 Hz up to 5 kHz
+ - uses the FreqRes resolution
+
+ Copyright (C) 2022 Norbert Richter
+
+ 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifdef USE_FLOWRATEMETER
+
+#define XSNS_96 96
+
+
+
+#define FLOWRATEMETER_WEIGHT_AVG_SAMPLE 20 // number of samples for smooth weigted average
+#define FLOWRATEMETER_MIN_FREQ 1 // Hz
+
+#define D_JSON_FLOWRATEMETER_RATE "Rate"
+#define D_JSON_FLOWRATEMETER_VALUE "Value"
+#define D_JSON_FLOWRATEMETER_UNIT "Unit"
+#define D_JSON_FLOWRATEMETER_VALUE_AVG "average"
+#define D_JSON_FLOWRATEMETER_VALUE_RAW "raw"
+
+
+
+#ifdef USE_WEBSERVER
+const char HTTP_SNS_FLOWRATEMETER[] PROGMEM =
+ "{s}" D_FLOWRATEMETER_NAME "-%d{m}%*_f %s{e}"
+ ;
+#endif // USE_WEBSERVER
+
+
+int32_t flowratemeter_period[MAX_FLOWRATEMETER] = {0};
+float flowratemeter_period_avg[MAX_FLOWRATEMETER] = {0};
+uint32_t flowratemeter_count[MAX_FLOWRATEMETER] = {0};
+volatile uint32_t flowratemeter_last_irq[MAX_FLOWRATEMETER] = {0};
+
+bool flowratemeter_valuesread = false;
+bool flowratemeter_raw_value = false;
+
+
+
+void IRAM_ATTR FlowRateMeterIR(uint16_t irq)
+{
+ uint32_t time = micros();
+#if defined(ESP8266)
+ uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
+ GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status);
+#endif
+ if (irq < MAX_FLOWRATEMETER) {
+ if ((time - flowratemeter_last_irq[irq]) < (1000000 / FLOWRATEMETER_MIN_FREQ)) {
+ flowratemeter_period[irq] = time - flowratemeter_last_irq[irq];
+ } else {
+ flowratemeter_period[irq] = 0;
+ }
+ flowratemeter_valuesread = true;
+ flowratemeter_last_irq[irq] = time;
+ }
+}
+// GPIO_STATUS is always 0 (?), so can only determine the IR source using this way
+void IRAM_ATTR FlowRateMeter1IR(void)
+{
+ FlowRateMeterIR(0);
+}
+void IRAM_ATTR FlowRateMeter2IR(void)
+{
+ FlowRateMeterIR(1);
+}
+
+void FlowRateMeterRead(void)
+{
+ for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) {
+ if ((micros() - flowratemeter_last_irq[i]) >= (1000000 / FLOWRATEMETER_MIN_FREQ)) {
+ flowratemeter_period[i] = 0;
+ flowratemeter_period_avg[i] = 0;
+ }
+
+ // exponentially weighted average
+ if (flowratemeter_count[i] <= FLOWRATEMETER_WEIGHT_AVG_SAMPLE) {
+ flowratemeter_count[i]++;
+ }
+ flowratemeter_period_avg[i] -= flowratemeter_period_avg[i] / flowratemeter_count[i];
+ flowratemeter_period_avg[i] += float(flowratemeter_period[i]) / flowratemeter_count[i];
+ }
+}
+
+void FlowRateMeterInit(void)
+{
+ void (* irq_service[MAX_FLOWRATEMETER])(void)= {FlowRateMeter1IR, FlowRateMeter2IR};
+
+ flowratemeter_valuesread = false;
+ for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) {
+ pinMode(Pin(GPIO_FLOWRATEMETER_IN, i), INPUT);
+ attachInterrupt(Pin(GPIO_FLOWRATEMETER_IN, i), irq_service[i], RISING);
+ }
+}
+
+void FlowRateMeterShow(bool json)
+{
+ if (json) {
+ ResponseAppend_P(PSTR(",\"" D_FLOWRATEMETER_NAME "\":{\"" D_JSON_FLOWRATEMETER_RATE "\":["));
+ }
+
+ for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) {
+ float flowratemeter_rate_avg_float = 0;
+
+ if (flowratemeter_period[i]) {
+ flowratemeter_rate_avg_float =
+ ((Settings->SensorBits1.flowratemeter_unit ? (1000000.0 / 1000.0) : (1000000 / 60.0)) / 2.0)
+ / (flowratemeter_raw_value ? flowratemeter_period[i] : flowratemeter_period_avg[i])
+ * (Settings->flowratemeter_calibration[i] ? (float)Settings->flowratemeter_calibration[i] : 1000.0);
+ }
+
+ if (PinUsed(GPIO_FLOWRATEMETER_IN, i)) {
+ if (json) {
+ ResponseAppend_P(PSTR("%s%*_f"),
+ i ? PSTR(",") : PSTR(""),
+ Settings->flag2.frequency_resolution, &flowratemeter_rate_avg_float
+ );
+
+#ifdef USE_WEBSERVER
+ } else {
+ WSContentSend_PD(HTTP_SNS_FLOWRATEMETER,
+ i+1,
+ Settings->flag2.frequency_resolution, &flowratemeter_rate_avg_float,
+ Settings->SensorBits1.flowratemeter_unit ? D_UNIT_CUBICMETER_PER_HOUR : D_UNIT_LITER_PER_MINUTE
+ );
+#endif // USE_WEBSERVER
+ }
+ }
+ }
+ if (json) {
+ ResponseAppend_P(PSTR("],\"" D_JSON_FLOWRATEMETER_VALUE "\":\"%s\""),
+ flowratemeter_raw_value ? PSTR(D_JSON_FLOWRATEMETER_VALUE_RAW) : PSTR(D_JSON_FLOWRATEMETER_VALUE_AVG)
+ );
+ ResponseAppend_P(PSTR(",\"" D_JSON_FLOWRATEMETER_UNIT "\":\"%s\"}"),
+ Settings->SensorBits1.flowratemeter_unit ? PSTR(D_UNIT_CUBICMETER_PER_HOUR) : PSTR(D_UNIT_LITER_PER_MINUTE)
+ );
+ }
+}
+
+/*********************************************************************************************\
+ * Supported commands for Sensor96:
+ *
+ * Sensor96 - Show current settings
+ * Sensor96 0 0|1 - Show flow value in l/min (0) or m³/h (1)
+ * Sensor96 1 - Set sensor 1 factor (x 1000) - to set to 0.2 enter 'Sensor96 1 200'
+ * Sensor96 2 - Set sensor 2 factor (x 1000)
+ * Sensor96 9 0|1 - Value mode: Switch between displaying avg(0) / raw(1) readings (not permanently)
+ *
+ * Flowmeter calibration:
+ * - get the current displayed flow rate (D)
+ * - get the current (c)
+ * - measure the real flow rate (M)
+ * - new = M / (c * D)
+ *
+ * Example:
+ * - displayed flow rate = 254.39 l/min (D)
+ * - current = 1.0 (c)
+ * - real flow rate = 83.42 l/min (M)
+ *
+ * new = M / (c * D) = 83.42 / (1 * 254.39) = 0.328
+ * Cmd: Sensor96 x 328
+\*********************************************************************************************/
+bool FlowRateMeterCommand(void) {
+ bool show_parms = true;
+ char argument[XdrvMailbox.data_len];
+
+ long value = 0;
+ for (uint32_t ca = 0; ca < XdrvMailbox.data_len; ca++) {
+ if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; }
+ }
+ bool any_value = (strchr(XdrvMailbox.data, ',') != nullptr);
+ if (any_value) {
+ value = strtol(ArgV(argument, 2), nullptr, 10);
+ }
+
+ switch (XdrvMailbox.payload) {
+ case 0: // Unit
+ if (any_value) {
+ Settings->SensorBits1.flowratemeter_unit = value & 1;
+ ResponseCmndNumber(value & 1);
+ show_parms = false;
+ }
+ break;
+ case 1: // Sensor calibration value
+ case 2:
+ if (any_value) {
+ Settings->flowratemeter_calibration[XdrvMailbox.payload - 1] = value;
+ ResponseCmndNumber(value);
+ show_parms = false;
+ }
+ break;
+ case 9: // avg/raw values
+ if (any_value) {
+ flowratemeter_raw_value = value & 1;
+ ResponseCmndNumber(value & 1);
+ show_parms = false;
+ }
+ break;
+ }
+
+ if (show_parms) {
+ Response_P(PSTR("{\"Sensor%d\":{\"" D_JSON_POWERFACTOR "\":["), XSNS_96);
+ for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) {
+ float flowratemeter_factor = Settings->flowratemeter_calibration[i] ? (float)Settings->flowratemeter_calibration[i] / 1000 : 1;
+ ResponseAppend_P(PSTR("%s%3_f"), i ? PSTR(",") : PSTR(""), &flowratemeter_factor);
+ }
+ ResponseAppend_P(PSTR("],\"" D_JSON_FLOWRATEMETER_VALUE "\":\"%s\""),
+ flowratemeter_raw_value ? PSTR(D_JSON_FLOWRATEMETER_VALUE_RAW) : PSTR(D_JSON_FLOWRATEMETER_VALUE_AVG)
+ );
+ ResponseAppend_P(PSTR(",\"" D_JSON_FLOWRATEMETER_UNIT "\":\"%s\"}}"),
+ Settings->SensorBits1.flowratemeter_unit ? PSTR(D_UNIT_CUBICMETER_PER_HOUR) : PSTR(D_UNIT_LITER_PER_MINUTE)
+ );
+ }
+
+ return true;
+}
+
+/*********************************************************************************************\
+ * Interface
+\*********************************************************************************************/
+
+bool Xsns96(uint8_t function)
+{
+ bool result = false;
+
+ if (PinUsed(GPIO_FLOWRATEMETER_IN, GPIO_ANY)) {
+ switch (function) {
+ case FUNC_INIT:
+ FlowRateMeterInit();
+ break;
+ case FUNC_EVERY_250_MSECOND:
+ FlowRateMeterRead();
+ break;
+ case FUNC_COMMAND_SENSOR:
+ if (XSNS_96 == XdrvMailbox.index) {
+ result = FlowRateMeterCommand();
+ }
+ break;
+ case FUNC_JSON_APPEND:
+ FlowRateMeterShow(true);
+ break;
+#ifdef USE_WEBSERVER
+ case FUNC_WEB_SENSOR:
+ FlowRateMeterShow(false);
+ break;
+#endif // USE_WEBSERVER
+ }
+ }
+ return result;
+}
+
+#endif // USE_FLOWRATEMETER
diff --git a/tools/lv_gpio/lv_gpio_enum.h b/tools/lv_gpio/lv_gpio_enum.h
index 19e517add..0d2132307 100644
--- a/tools/lv_gpio/lv_gpio_enum.h
+++ b/tools/lv_gpio/lv_gpio_enum.h
@@ -298,5 +298,14 @@ BL6523_TX = GPIO_BL6523_TX
BL6523_RX = GPIO_BL6523_RX
ADE7880_IRQ = GPIO_ADE7880_IRQ
RESET = GPIO_RESET
+MS01 = GPIO_MS01
+SDIO_CMD = GPIO_SDIO_CMD
+SDIO_CLK = GPIO_SDIO_CLK
+SDIO_D0 = GPIO_SDIO_D0
+SDIO_D1 = GPIO_SDIO_D1
+SDIO_D2 = GPIO_SDIO_D2
+SDIO_D3 = GPIO_SDIO_D3
+
+FLOWRATEMETER_SIGNAL = GPIO_FLOWRATEMETER_IN
SENSOR_END = GPIO_SENSOR_END