diff --git a/CHANGELOG.md b/CHANGELOG.md index c2ce50ee4..8b2c6a528 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,14 @@ All notable changes to this project will be documented in this file. ### Added - Support for SGP40 gas and air quality sensor (#16341) - Support for Modbus writing using ModbusBridge by JeroenSt (#16351) +- Support for Ethernet in ESP32 safeboot firmware (#16388) +- Flowrate meter flow amount/duration, show values in table format (#16385) ### Changed - TasmotaModbus library from v3.5.0 to v3.6.0 (#16351) - Button debouncing V3 by adopting switch debounce code (#16339) - Thermostat max allowed temperature from 100 to 200C (#16363) +- Using command ``SerialBuffer`` raise max allowed buffer size to 2048 characters (#16374) ### Fixed - Removed whitespace from JSON values with no decimals (#16365) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ff53be16d..f4912f2dc 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -14,7 +14,7 @@ Pay attention to the following version breaks due to dynamic settings updates: 1. Migrate to **Sonoff-Tasmota 3.9.x** 2. Migrate to **Sonoff-Tasmota 4.x** -3. Migrate to **Sonoff-Tasmota 5.14** +3. Migrate to **Sonoff-Tasmota 5.14** (http://ota.tasmota.com/tasmota/release_5.14.0/sonoff.bin) - NOTICE underscore as a dash is not supported in older versions 4. Migrate to **Sonoff-Tasmota 6.7.1** (http://ota.tasmota.com/tasmota/release_6.7.1/sonoff.bin) - NOTICE underscore as a dash is not supported in older versions 5. Migrate to **Tasmota 7.2.0** (http://ota.tasmota.com/tasmota/release-7.2.0/tasmota.bin) @@ -113,6 +113,8 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - Support for SGP40 gas and air quality sensor [#16341](https://github.com/arendst/Tasmota/issues/16341) - Support for Modbus writing using ModbusBridge by JeroenSt [#16351](https://github.com/arendst/Tasmota/issues/16351) - Zigbee device plugin mechanism with commands ``ZbLoad``, ``ZbUnload`` and ``ZbLoadDump`` [#16252](https://github.com/arendst/Tasmota/issues/16252) +- Flowrate meter flow amount/duration, show values in table format [#16385](https://github.com/arendst/Tasmota/issues/16385) +- Support for Ethernet in ESP32 safeboot firmware [#16388](https://github.com/arendst/Tasmota/issues/16388) - ESP32-S3 support for internal temperature sensor ### Breaking Changed @@ -122,6 +124,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - TasmotaModbus library from v3.5.0 to v3.6.0 [#16351](https://github.com/arendst/Tasmota/issues/16351) - Button debouncing V3 by adopting switch debounce code [#16339](https://github.com/arendst/Tasmota/issues/16339) - Thermostat max allowed temperature from 100 to 200C [#16363](https://github.com/arendst/Tasmota/issues/16363) +- Using command ``SerialBuffer`` raise max allowed buffer size to 2048 characters [#16374](https://github.com/arendst/Tasmota/issues/16374) ### Fixed - RTC not detected when lights are present [#16242](https://github.com/arendst/Tasmota/issues/16242) @@ -130,5 +133,4 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - Lost module name in GUI regression from v12.0.2.4 - 20220803 [#16324](https://github.com/arendst/Tasmota/issues/16324) - Removed whitespace from JSON values with no decimals [#16365](https://github.com/arendst/Tasmota/issues/16365) - ### Removed diff --git a/lib/libesp32/berry/default/berry_conf.h b/lib/libesp32/berry/default/berry_conf.h index c70af7945..4d46eb3df 100644 --- a/lib/libesp32/berry/default/berry_conf.h +++ b/lib/libesp32/berry/default/berry_conf.h @@ -41,6 +41,14 @@ **/ #define BE_USE_SINGLE_FLOAT 1 // use `float` not `double` +/* Macro: BE_BYTES_MAX_SIZE + * Maximum size in bytes of a `bytes()` object. + * Putting too much pressure on the memory allocator can do + * harm, so we limit the maximum size. + * Default: 32kb + **/ +#define BE_BYTES_MAX_SIZE (32*1024) /* 32 kb default value */ + /* Macro: BE_USE_PRECOMPILED_OBJECT * Use precompiled objects to avoid creating these objects at * runtime. Enable this macro can greatly optimize RAM usage. diff --git a/lib/libesp32/berry/src/be_byteslib.c b/lib/libesp32/berry/src/be_byteslib.c index 11857963a..299cc2fcd 100644 --- a/lib/libesp32/berry/src/be_byteslib.c +++ b/lib/libesp32/berry/src/be_byteslib.c @@ -18,7 +18,6 @@ #include #define BYTES_DEFAULT_SIZE 28 // default pre-reserved size for buffer (keep 4 bytes for len/size) -#define BYTES_MAX_SIZE (32*1024) // max 32Kb #define BYTES_OVERHEAD 4 // bytes overhead to be added when allocating (used to store len and size) #define BYTES_HEADROOM 8 // keep a natural headroom of 8 bytes when resizing @@ -506,7 +505,7 @@ void m_write_attributes(bvm *vm, int rel_idx, const buf_impl * attr) void bytes_realloc(bvm *vm, buf_impl * attr, int32_t size) { if (!attr->fixed && size < 4) { size = 4; } - if (size > BYTES_MAX_SIZE) { size = BYTES_MAX_SIZE; } + if (size > vm->bytesmaxsize) { size = vm->bytesmaxsize; } size_t oldsize = attr->bufptr ? attr->size : 0; attr->bufptr = (uint8_t*) be_realloc(vm, attr->bufptr, oldsize, size); /* malloc */ attr->size = size; diff --git a/lib/libesp32/berry/src/be_strlib.c b/lib/libesp32/berry/src/be_strlib.c index 23fdf978f..2c5424634 100644 --- a/lib/libesp32/berry/src/be_strlib.c +++ b/lib/libesp32/berry/src/be_strlib.c @@ -263,6 +263,9 @@ BERRY_API bint be_str2int(const char *str, const char **endstr) while ((c = be_char2hex(*str++)) >= 0) { sum = sum * 16 + c; } + if (endstr) { + *endstr = str - 1; + } return sum; } else { /* decimal literal */ diff --git a/lib/libesp32/berry/src/be_vm.c b/lib/libesp32/berry/src/be_vm.c index de738fb4d..ffc55977a 100644 --- a/lib/libesp32/berry/src/be_vm.c +++ b/lib/libesp32/berry/src/be_vm.c @@ -477,6 +477,7 @@ BERRY_API bvm* be_vm_new(void) be_gc_setpause(vm, 1); be_loadlibs(vm); vm->compopt = 0; + vm->bytesmaxsize = BE_BYTES_MAX_SIZE; vm->obshook = NULL; vm->ctypefunc = NULL; #if BE_USE_PERF_COUNTERS diff --git a/lib/libesp32/berry/src/be_vm.h b/lib/libesp32/berry/src/be_vm.h index 816d10cd1..474e74a7d 100644 --- a/lib/libesp32/berry/src/be_vm.h +++ b/lib/libesp32/berry/src/be_vm.h @@ -105,6 +105,7 @@ struct bvm { struct bgc gc; bctypefunc ctypefunc; /* handler to ctype_func */ bbyte compopt; /* compilation options */ + uint32_t bytesmaxsize; /* max allowed size for bytes() object, default 32kb but can be increased */ bobshook obshook; bmicrosfnct microsfnct; /* fucntion to get time as a microsecond resolution */ #if BE_USE_PERF_COUNTERS diff --git a/tasmota/include/tasmota_configurations_ESP32.h b/tasmota/include/tasmota_configurations_ESP32.h index 9f33d3544..4544f7da6 100644 --- a/tasmota/include/tasmota_configurations_ESP32.h +++ b/tasmota/include/tasmota_configurations_ESP32.h @@ -182,6 +182,7 @@ #define USE_WEBCLIENT #define USE_WEBCLIENT_HTTPS #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge console Tee (+0k8 code) +#define USE_ETHERNET #endif // FIRMWARE_SAFEBOOT diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h index a02170f37..72fe31896 100644 --- a/tasmota/language/af_AF.h +++ b/tasmota/language/af_AF.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1076,7 +1077,9 @@ #define D_FP_UNKNOWNERROR "Fout" // Any other error // xsns_96_flowratemeter.ino -#define D_FLOWRATEMETER_NAME "Flowmeter" +#define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index 581d0b6fc..949dbdb16 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/ca_AD.h b/tasmota/language/ca_AD.h index 6dfeec7e9..bbdb4eee1 100644 --- a/tasmota/language/ca_AD.h +++ b/tasmota/language/ca_AD.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Posant l'adreça a" #define D_OUT_OF_RANGE "Fora de rang" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Cabal" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index 8cc9a3255..71d42ddfc 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index 44c63ba50..e9a9f6609 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Neue Adresse" #define D_OUT_OF_RANGE "Außerhalb Bereich" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Durchflussmesser" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Menge heute" +#define D_FLOWRATEMETER_DURATION_TODAY "Dauer heute" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index ab3479641..028c9a49d 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index 25d605ab3..60b9e8942 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index c0209fe37..e9a5c46fe 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Cambiando dirección a" #define D_OUT_OF_RANGE "Fuera de Rango" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index 21dcf9060..b94af9891 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Positionner l'adresse à" #define D_OUT_OF_RANGE "Hors limites" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h index 0212d2f2c..fbe031e89 100644 --- a/tasmota/language/fy_NL.h +++ b/tasmota/language/fy_NL.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index 9f0a2df84..6c5cbb225 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index b748b0dbc..d31d0957d 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 560cb299f..ba49afae4 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 v9.4.0.1 - Last update 19.07.2022 + * Updated until v9.4.0.1 - Last update 31.08.2022 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Imposta indirizzo a" #define D_OUT_OF_RANGE "Fuori intervallo" @@ -1076,7 +1077,9 @@ #define D_FP_UNKNOWNERROR "Errore" // Any other error // xsns_96_flowratemeter.ino -#define D_FLOWRATEMETER_NAME "Portata" +#define D_FLOWRATEMETER_NAME "Portata" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Valore odierno" +#define D_FLOWRATEMETER_DURATION_TODAY "Durata odierna" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index 40ebaec62..92400dfe5 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index 2b69901e2..729aa5e0e 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Nieuw adres" #define D_OUT_OF_RANGE "Buiten beriek" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index 992419ee1..fa9c391c2 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Ustawiam adres na" #define D_OUT_OF_RANGE "Poza zakresem" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index 763efdea3..b845055a4 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Mudança de endereço para" #define D_OUT_OF_RANGE "Fora de Alcance" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index 2d216a4a6..4b03eb70b 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Mudança de endereço para" #define D_OUT_OF_RANGE "Fora de Alcance" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index 8d2d409e2..93f2381b1 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index e5f0a0e81..81e66fa2c 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -934,6 +934,7 @@ #define D_UNIT_WATT_METER_QUADRAT "Вт/м²" #define D_UNIT_LITER_PER_MINUTE "l/min" #define D_UNIT_CUBICMETER_PER_HOUR "m³/h" +#define D_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index c24ab53cb..f1a60f325 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index c36612aed..fa52fe7fe 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index 319791d99..90337d4cb 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index ea736ffea..8258e3a0a 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -934,6 +934,7 @@ #define D_UNIT_WATT_METER_QUADRAT "Вт/м²" #define D_UNIT_LITER_PER_MINUTE "l/min" #define D_UNIT_CUBICMETER_PER_HOUR "m³/h" +#define D_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index 26de9f0a7..3422ab65d 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index 7e6e2da7e..c06627648 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index 2fe003a1c..00b247f74 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -934,6 +934,7 @@ #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_UNIT_CUBIC_METER "m³" #define D_NEW_ADDRESS "Setting address to" #define D_OUT_OF_RANGE "Out of Range" @@ -1077,6 +1078,8 @@ // xsns_96_flowratemeter.ino #define D_FLOWRATEMETER_NAME "Flowrate" +#define D_FLOWRATEMETER_AMOUNT_TODAY "Amount Today" +#define D_FLOWRATEMETER_DURATION_TODAY "Duration Today" // xsns_83_neopool.ino #define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names diff --git a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_1z_libs.ino b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_1z_libs.ino index 34dfd2e57..335431b53 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_1z_libs.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_23_zigbee_1z_libs.ino @@ -317,6 +317,7 @@ public: // if suffix == 0, we don't care and find the first match Z_attribute & findOrCreateAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix = 0); Z_attribute & findOrCreateAttribute(const char * name, uint8_t suffix = 0); + Z_attribute & findOrCreateCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix = 0); // always care about suffix Z_attribute & findOrCreateAttribute(const Z_attribute &attr); // replace attribute with new value, suffix does care @@ -558,27 +559,25 @@ bool Z_attribute::equalsKey(const Z_attribute & attr2, bool ignore_key_suffix) c } bool Z_attribute::equalsId(uint16_t _cluster, uint16_t _attr_id, uint8_t suffix) const { - if (!key_is_str) { - if ((this->cluster == _cluster) && (this->attr_id == _attr_id) && (!this->key_is_cmd)) { - if (suffix) { - if (key_suffix == suffix) { return true; } - } else { - return true; - } + if (key_is_cmd || key_is_str) { return false; } + if ((this->cluster == _cluster) && (this->attr_id == _attr_id) && (!this->key_is_cmd)) { + if (suffix) { + if (key_suffix == suffix) { return true; } + } else { + return true; } } return false; } bool Z_attribute::equalsCmd(uint16_t _cluster, uint8_t _cmd_id, bool _direction, uint8_t suffix) const { - if (!key_is_str) { - uint16_t _attr_id = _cmd_id | (_direction ? 0x100 : 0x000); - if ((this->cluster == _cluster) && (this->attr_id == _attr_id) && (!this->key_is_cmd)) { - if (suffix) { - if (key_suffix == suffix) { return true; } - } else { - return true; - } + if (!key_is_cmd ||key_is_str) { return false; } + uint16_t _attr_id = _cmd_id | (_direction ? 0x100 : 0x000); + if ((this->cluster == _cluster) && (this->attr_id == _attr_id) && (!this->key_is_cmd)) { + if (suffix) { + if (key_suffix == suffix) { return true; } + } else { + return true; } } return false; @@ -813,7 +812,7 @@ Z_attribute & Z_attribute_list::addAttributeCmd(uint16_t cluster, uint8_t cmd_id Z_attribute & attr = addToLast(); attr.cluster = cluster; attr.attr_id = cmd_id | (direction ? 0x100 : 0); - attr.key_is_str = true; + attr.key_is_cmd = true; if (!suffix) { attr.key_suffix = countAttribute(attr.cluster, attr.attr_id); } else { attr.key_suffix = suffix; } return attr; @@ -891,7 +890,7 @@ const Z_attribute * Z_attribute_list::findAttribute(const Z_attribute &attr) con const Z_attribute * Z_attribute_list::findAttribute(uint16_t cluster, uint16_t attr_id, uint8_t suffix) const { for (const auto & attr : *this) { - if (attr.equalsId(cluster, attr_id, suffix)) { return &attr; } + if (attr.equalsId(cluster, attr_id, suffix) && !attr.key_is_cmd) { return &attr; } } return nullptr; } @@ -916,6 +915,11 @@ Z_attribute & Z_attribute_list::findOrCreateAttribute(uint16_t cluster, uint16_t return found ? *found : addAttribute(cluster, attr_id, suffix); } +Z_attribute & Z_attribute_list::findOrCreateCmd(uint16_t cluster, uint8_t cmd_id, bool direction, uint8_t suffix) { + Z_attribute * found = findAttributeCmd(cluster, cmd_id, direction, suffix); + return found ? *found : addAttributeCmd(cluster, cmd_id, direction, suffix); +} + const Z_attribute * Z_attribute_list::findAttribute(const char * name, uint8_t suffix) const { for (const auto & attr : *this) { if (attr.equalsKey(name, suffix)) { return &attr; } @@ -938,7 +942,9 @@ Z_attribute & Z_attribute_list::findOrCreateAttribute(const char * name, uint8_t // same but passing a Z_attribute as key Z_attribute & Z_attribute_list::findOrCreateAttribute(const Z_attribute &attr) { Z_attribute & ret = attr.key_is_str ? findOrCreateAttribute(attr.key, attr.key_suffix) - : findOrCreateAttribute(attr.cluster, attr.attr_id, attr.key_suffix); + : attr.key_is_cmd ? + findOrCreateCmd(attr.cluster, attr.attr_id & 0xFF, attr.attr_id & 0x100 ? true : false, attr.key_suffix) + : findOrCreateAttribute(attr.cluster, attr.attr_id, attr.key_suffix); ret.key_suffix = attr.key_suffix; return ret; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino index 51d18abad..36ac8b4e0 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_9_berry.ino @@ -316,6 +316,10 @@ void BerryInit(void) { comp_set_strict(berry.vm); /* Enable strict mode in Berry compiler, equivalent of `import strict` */ be_set_ctype_func_hanlder(berry.vm, be_call_ctype_func); + if (UsePSRAM()) { // if PSRAM is available, raise the max size to 512kb + berry.vm->bytesmaxsize = 512 * 1024; + } + be_load_custom_libs(berry.vm); // load classes and modules // Set the GC threshold to 3584 bytes to avoid the first useless GC diff --git a/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino b/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino index b7cfada24..525e878cc 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_82_esp32_ethernet.ino @@ -154,6 +154,31 @@ void EthernetInit(void) { int eth_power = Pin(GPIO_ETH_PHY_POWER); int eth_mdc = Pin(GPIO_ETH_PHY_MDC); int eth_mdio = Pin(GPIO_ETH_PHY_MDIO); +#if CONFIG_IDF_TARGET_ESP32 + // fix an disconnection issue after rebooting Olimex POE - this forces a clean state for all GPIO involved in RMII + gpio_reset_pin((gpio_num_t)GPIO_ETH_PHY_POWER); + gpio_reset_pin((gpio_num_t)GPIO_ETH_PHY_MDC); + gpio_reset_pin((gpio_num_t)GPIO_ETH_PHY_MDIO); + gpio_reset_pin(GPIO_NUM_19); // EMAC_TXD0 - hardcoded + gpio_reset_pin(GPIO_NUM_21); // EMAC_TX_EN - hardcoded + gpio_reset_pin(GPIO_NUM_22); // EMAC_TXD1 - hardcoded + gpio_reset_pin(GPIO_NUM_25); // EMAC_RXD0 - hardcoded + gpio_reset_pin(GPIO_NUM_26); // EMAC_RXD1 - hardcoded + gpio_reset_pin(GPIO_NUM_27); // EMAC_RX_CRS_DV - hardcoded + switch (Settings->eth_clk_mode) { + case 0: // ETH_CLOCK_GPIO0_IN + case 1: // ETH_CLOCK_GPIO0_OUT + gpio_reset_pin(GPIO_NUM_0); + break; + case 2: // ETH_CLOCK_GPIO16_OUT + gpio_reset_pin(GPIO_NUM_16); + break; + case 3: // ETH_CLOCK_GPIO17_OUT + gpio_reset_pin(GPIO_NUM_17); + break; + } + delay(1); +#endif // CONFIG_IDF_TARGET_ESP32 if (!ETH.begin(Settings->eth_address, eth_power, eth_mdc, eth_mdio, (eth_phy_type_t)Settings->eth_type, (eth_clock_mode_t)Settings->eth_clk_mode)) { AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: Bad PHY type or init error")); return; diff --git a/tasmota/tasmota_xsns_sensor/xsns_96_flowratemeter.ino b/tasmota/tasmota_xsns_sensor/xsns_96_flowratemeter.ino index 4e43bd6b8..16a635e9e 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_96_flowratemeter.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_96_flowratemeter.ino @@ -25,34 +25,35 @@ #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" +#define D_JSON_FLOWRATEMETER_RATE "Rate" +#define D_JSON_FLOWRATEMETER_VALUE "Source" +#define D_JSON_FLOWRATEMETER_UNIT "Unit" +#define D_JSON_FLOWRATEMETER_AMOUNT_TODAY "AmountToday" +#define D_JSON_FLOWRATEMETER_AMOUNT_UNIT "AmountUnit" +#define D_JSON_FLOWRATEMETER_DURATION_TODAY "DurationToday" +#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 - +#define FLOWRATEMETER_INVALID (uint32_t)-1 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}; +volatile uint32_t flowratemeter_last_irq[MAX_FLOWRATEMETER] = {FLOWRATEMETER_INVALID}; + +int32_t flowratemeter_period_sum[MAX_FLOWRATEMETER]; +int32_t flowratemeter_period_sum_dT[MAX_FLOWRATEMETER]; +int32_t flowratemeter_period_duration[MAX_FLOWRATEMETER]; + -bool flowratemeter_valuesread = false; bool flowratemeter_raw_value = false; +#define FlowRateMeterIsValid(time, meter) flowratemeter_last_irq[meter] != FLOWRATEMETER_INVALID && flowratemeter_last_irq[meter] < time void IRAM_ATTR FlowRateMeterIR(uint16_t irq) { @@ -62,12 +63,16 @@ void IRAM_ATTR FlowRateMeterIR(uint16_t irq) 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; + if (FlowRateMeterIsValid(time, irq)) { + if ((time - flowratemeter_last_irq[irq]) < (1000000 / FLOWRATEMETER_MIN_FREQ)) { + flowratemeter_period_sum_dT[irq] = millis(); + flowratemeter_period_sum[irq]++; + flowratemeter_period[irq] = time - flowratemeter_last_irq[irq]; + flowratemeter_period_duration[irq] += flowratemeter_period[irq] / 100; + } else { + flowratemeter_period[irq] = 0; + } } - flowratemeter_valuesread = true; flowratemeter_last_irq[irq] = time; } } @@ -81,20 +86,36 @@ void IRAM_ATTR FlowRateMeter2IR(void) FlowRateMeterIR(1); } +void FlowRateMeterMidnightReset(void) +{ + uint32_t t = millis(); + for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) { + flowratemeter_period_sum[i] = 0; + flowratemeter_period_duration[i] = 0; + flowratemeter_period_sum_dT[i] = t; + } +} + 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; - } + uint32_t time = micros(); + if (PinUsed(GPIO_FLOWRATEMETER_IN, i) && FlowRateMeterIsValid(time, i)) { + if ((time - flowratemeter_last_irq[i]) >= (1000000 / FLOWRATEMETER_MIN_FREQ)) { + // invalid in case of pulse outage + flowratemeter_period[i] = 0; + flowratemeter_period_avg[i] = 0; + flowratemeter_count[i] = 0; + flowratemeter_last_irq[i] = FLOWRATEMETER_INVALID; + } - // exponentially weighted average - if (flowratemeter_count[i] <= FLOWRATEMETER_WEIGHT_AVG_SAMPLE) { - flowratemeter_count[i]++; + // 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]; } - flowratemeter_period_avg[i] -= flowratemeter_period_avg[i] / flowratemeter_count[i]; - flowratemeter_period_avg[i] += float(flowratemeter_period[i]) / flowratemeter_count[i]; } } @@ -102,7 +123,7 @@ void FlowRateMeterInit(void) { void (* irq_service[MAX_FLOWRATEMETER])(void)= {FlowRateMeter1IR, FlowRateMeter2IR}; - flowratemeter_valuesread = false; + FlowRateMeterMidnightReset(); for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) { if (PinUsed(GPIO_FLOWRATEMETER_IN, i)) { pinMode(Pin(GPIO_FLOWRATEMETER_IN, i), INPUT); @@ -111,50 +132,139 @@ void FlowRateMeterInit(void) } } -void FlowRateMeterShow(bool json) +void FlowRateMeterGetValue(uint32_t meter, float *rate_float, float *amount_today) { - 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 (nullptr != rate_float) { + *rate_float = 0; + if (meter < MAX_FLOWRATEMETER && flowratemeter_period[meter]) { + *rate_float = + (1000000.0 / 60.0 / 2.0) + / (flowratemeter_raw_value ? flowratemeter_period[meter] : flowratemeter_period_avg[meter]) + * (Settings->flowratemeter_calibration[meter] ? (float)Settings->flowratemeter_calibration[meter] : 1000.0); } } - 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) - ); + + if (nullptr != amount_today) { + *amount_today = 0; + if (meter < MAX_FLOWRATEMETER && flowratemeter_period_sum[meter]) { + uint32_t _flowratemeter_period = (uint32_t)((float)flowratemeter_period_sum_dT[meter] / (float)flowratemeter_period_sum[meter] * 1000.0); + float lmin = (((1000000.0 / 60.0) / 2.0) / _flowratemeter_period * (Settings->flowratemeter_calibration[meter] ? (float)Settings->flowratemeter_calibration[meter] : 1000.0)); + *amount_today = (lmin / 60000) * flowratemeter_period_sum_dT[meter]; + } } } +void FlowRateMeterShow(bool json) +{ + uint16_t flowmeter_count = 0; + const char* open_square_bracket; + const char* close_square_bracket; + float flowratemeter_rate_float[MAX_FLOWRATEMETER]; + float floatrate_amount_today[MAX_FLOWRATEMETER]; + + for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) { + FlowRateMeterGetValue(i, &flowratemeter_rate_float[i], &floatrate_amount_today[i]); + if (PinUsed(GPIO_FLOWRATEMETER_IN, i)) { + flowmeter_count++; + } + } + if (flowmeter_count > 1) { + open_square_bracket = PSTR("["); + close_square_bracket = PSTR("]"); + } else { + open_square_bracket = PSTR(""); + close_square_bracket = PSTR(""); + } + + if (json) { + ResponseAppend_P(PSTR(",\"" D_FLOWRATEMETER_NAME "\":{\"" D_JSON_FLOWRATEMETER_RATE "\":%s"), open_square_bracket); + for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) { + if (PinUsed(GPIO_FLOWRATEMETER_IN, i)) { + float rate = Settings->SensorBits1.flowratemeter_unit ? flowratemeter_rate_float[i] * 60 / 1000 : flowratemeter_rate_float[i]; + ResponseAppend_P(PSTR("%s%*_f"), i ? PSTR(",") : PSTR(""), Settings->flag2.frequency_resolution, &rate); + } + } + ResponseAppend_P(PSTR("%s,\"" D_JSON_FLOWRATEMETER_AMOUNT_TODAY "\":%s"), close_square_bracket, open_square_bracket); + for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) { + if (PinUsed(GPIO_FLOWRATEMETER_IN, i)) { + float amount_today = Settings->SensorBits1.flowratemeter_unit ? floatrate_amount_today[i] / 1000 : floatrate_amount_today[i]; + ResponseAppend_P(PSTR("%s%*_f"), i ? PSTR(",") : PSTR(""), Settings->flag2.frequency_resolution, &amount_today); + } + } + ResponseAppend_P(PSTR("%s,\"" D_JSON_FLOWRATEMETER_DURATION_TODAY "\":%s"), close_square_bracket, open_square_bracket); + for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) { + if (PinUsed(GPIO_FLOWRATEMETER_IN, i)) { + ResponseAppend_P(PSTR("%s%ld"), i ? PSTR(",") : PSTR(""), flowratemeter_period_duration[i] / 10000); + } + } + ResponseAppend_P(PSTR("%s,\"" D_JSON_FLOWRATEMETER_VALUE "\":\"%s\""), + close_square_bracket, + flowratemeter_raw_value ? PSTR(D_JSON_FLOWRATEMETER_VALUE_RAW) : PSTR(D_JSON_FLOWRATEMETER_VALUE_AVG) + ); + ResponseAppend_P(PSTR(",\"" D_JSON_FLOWRATEMETER_AMOUNT_UNIT "\":\"%s\""), + Settings->SensorBits1.flowratemeter_unit ? PSTR(D_UNIT_CUBIC_METER) : PSTR(D_UNIT_LITERS)); + ResponseAppend_P(PSTR(",\"" D_JSON_FLOWRATEMETER_UNIT "\":\"%s\"}"), + Settings->SensorBits1.flowratemeter_unit ? PSTR(D_UNIT_CUBICMETER_PER_HOUR) : PSTR(D_UNIT_LITER_PER_MINUTE)); +#ifdef USE_WEBSERVER + } else { + // {s} = , {m} = , {e} = + if (flowmeter_count > 1) { + // head + WSContentSend_PD(PSTR("{s}  ")); + for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) { + if (PinUsed(GPIO_FLOWRATEMETER_IN, i)) { + WSContentSend_PD(PSTR("%d "), + Settings->flag5.gui_table_align ? PSTR("right") : PSTR("center"), + i+1 + ); + } + } + WSContentSend_PD(PSTR(" ")); + } + + // Flowrate + WSContentSend_PD(PSTR("{s}" D_FLOWRATEMETER_NAME "{m} ")); + for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) { + if (PinUsed(GPIO_FLOWRATEMETER_IN, i)) { + float rate = Settings->SensorBits1.flowratemeter_unit ? flowratemeter_rate_float[i] * 60 / 1000 : flowratemeter_rate_float[i]; + WSContentSend_PD(PSTR("%*_f "), + Settings->flag5.gui_table_align ? PSTR("right") : PSTR("center"), + Settings->flag2.frequency_resolution, &rate + ); + } + } + WSContentSend_PD(PSTR("%s{e}"), Settings->SensorBits1.flowratemeter_unit ? PSTR(D_UNIT_CUBICMETER_PER_HOUR) : PSTR(D_UNIT_LITER_PER_MINUTE)); + + // Amount today + WSContentSend_PD(PSTR("{s}" D_FLOWRATEMETER_NAME " " D_FLOWRATEMETER_AMOUNT_TODAY "{m} ")); + for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) { + if (PinUsed(GPIO_FLOWRATEMETER_IN, i)) { + float amount_today = Settings->SensorBits1.flowratemeter_unit ? floatrate_amount_today[i] / 1000 : floatrate_amount_today[i]; + WSContentSend_PD(PSTR("%*_f "), + Settings->flag5.gui_table_align ? PSTR("right") : PSTR("center"), + Settings->flag2.frequency_resolution, &amount_today + ); + } + } + WSContentSend_PD(PSTR("%s{e}"), Settings->SensorBits1.flowratemeter_unit ? PSTR(D_UNIT_CUBIC_METER) : PSTR(D_UNIT_LITERS)); + + // Duration today + WSContentSend_PD(PSTR("{s}" D_FLOWRATEMETER_NAME " " D_FLOWRATEMETER_DURATION_TODAY "{m} ")); + for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) { + if (PinUsed(GPIO_FLOWRATEMETER_IN, i)) { + float amount_today = Settings->SensorBits1.flowratemeter_unit ? floatrate_amount_today[i] / 1000 : floatrate_amount_today[i]; + WSContentSend_PD(PSTR("%s "), + (Settings->flag5.gui_table_align)?PSTR("right"):PSTR("center"), + GetDuration(flowratemeter_period_duration[i] / 10000).c_str() + ); + } + } + WSContentSend_PD(PSTR("{e}")); +#endif // USE_WEBSERVER + } +} + + /*********************************************************************************************\ * Supported commands for Sensor96: * @@ -246,6 +356,9 @@ bool Xsns96(uint8_t function) case FUNC_INIT: FlowRateMeterInit(); break; + case FUNC_SAVE_AT_MIDNIGHT: + FlowRateMeterMidnightReset(); + break; case FUNC_EVERY_250_MSECOND: FlowRateMeterRead(); break;