Merge branch 'development' of https://github.com/arendst/Tasmota into development

This commit is contained in:
renzhe 2022-09-01 14:05:47 +08:00
commit 4765e95d91
39 changed files with 340 additions and 93 deletions

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -18,7 +18,6 @@
#include <ctype.h>
#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;

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
if (flowmeter_count > 1) {
// head
WSContentSend_PD(PSTR("{s}&nbsp;</th>&nbsp;<th></th>"));
for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) {
if (PinUsed(GPIO_FLOWRATEMETER_IN, i)) {
WSContentSend_PD(PSTR("<th style=\"text-align:%s\">%d</th><th>&nbsp;</th>"),
Settings->flag5.gui_table_align ? PSTR("right") : PSTR("center"),
i+1
);
}
}
WSContentSend_PD(PSTR("<th> </th></tr>"));
}
// Flowrate
WSContentSend_PD(PSTR("{s}" D_FLOWRATEMETER_NAME "{m}&nbsp;</td>"));
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("<td style=\"text-align:%s\">%*_f</td><td>&nbsp;</td>"),
Settings->flag5.gui_table_align ? PSTR("right") : PSTR("center"),
Settings->flag2.frequency_resolution, &rate
);
}
}
WSContentSend_PD(PSTR("<td>%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}&nbsp;</td>"));
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("<td style=\"text-align:%s\">%*_f</td><td>&nbsp;</td>"),
Settings->flag5.gui_table_align ? PSTR("right") : PSTR("center"),
Settings->flag2.frequency_resolution, &amount_today
);
}
}
WSContentSend_PD(PSTR("<td>%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}&nbsp;</td>"));
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("<td style=\"text-align:%s\">%s</td><td>&nbsp;</td>"),
(Settings->flag5.gui_table_align)?PSTR("right"):PSTR("center"),
GetDuration(flowratemeter_period_duration[i] / 10000).c_str()
);
}
}
WSContentSend_PD(PSTR("<td>{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;