From c88b773dd3aa99fea557b70d597517b9c092890b Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Sat, 11 Nov 2023 11:49:40 +0100 Subject: [PATCH] Neopool enhancements (#19973) * Add NeoPool sensor delta trigger * Add NeoPool store settings in unified file system * Add NeoPool command NPBoost --- CHANGELOG.md | 3 + tasmota/include/tasmota_configurations.h | 2 +- tasmota/my_user_config.h | 2 +- .../tasmota_xsns_sensor/xsns_83_neopool.ino | 467 +++++++++++++++--- 4 files changed, 394 insertions(+), 80 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2f678a6f..5e2539fd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ All notable changes to this project will be documented in this file. ### Added - Scripter TCP client (#19914) - Berry ``debug.gcdebug()`` to enable GC debugging (#19936) +- NeoPool sensor delta trigger (command ``NPTelePeriod``) +- NeoPool store settings on unified file system +- NeoPool command ``NPBoost`` ### Breaking Changed diff --git a/tasmota/include/tasmota_configurations.h b/tasmota/include/tasmota_configurations.h index a572440f6..b55626794 100644 --- a/tasmota/include/tasmota_configurations.h +++ b/tasmota/include/tasmota_configurations.h @@ -823,7 +823,7 @@ #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) #undef USE_A4988_STEPPER // Disable support for A4988_Stepper #undef USE_PROMETHEUS // Disable support for https://prometheus.io/ metrics exporting over HTTP /metrics endpoint -#undef USE_NEOPOOL // Disable 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) +#undef USE_NEOPOOL // Disable support for Sugar Valley NeoPool Controller - also known under brands Hidrolife, Aquascenic, Oxilife, Bionet, Hidroniser, UVScenic, Station, Brilix, Bayrol and Hay (+14k flash, +120 mem) #undef USE_THERMOSTAT // Disable support for Thermostat #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index d1f672f68..f8e3fd4a1 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -1029,7 +1029,7 @@ //#define USE_PROMETHEUS // Add support for https://prometheus.io/ metrics exporting over HTTP /metrics endpoint -//#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 USE_NEOPOOL // Add support for Sugar Valley NeoPool Controller - also known under brands Hidrolife, Aquascenic, Oxilife, Bionet, Hidroniser, UVScenic, Station, Brilix, Bayrol and Hay (+14k flash, +120 mem) // #define NEOPOOL_MODBUS_ADDRESS 1 // Any modbus address //#define USE_FLOWRATEMETER // Add support for water flow meter YF-DN50 and similary (+1k7 code) diff --git a/tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino b/tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino index 8c6bbc87a..ac4901c4f 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino @@ -64,7 +64,7 @@ #define NEOPOOL_READ_REGISTER 0x04 // Function code used to read register #define NEOPOOL_WRITE_REGISTER 0x10 // Function code used to write register #define NEOPOOL_READ_TIMEOUT 25 // read data timeout in ms -#define NEOPOOL_DATA_TIMEOUT 30000 // directly read data register data discard timout in ms +#define NEOPOOL_CACHE_INVALID_TIME 30 // data cache invalidation time in s // Pool LED RGB lights with different programs, the individual programs can be selected @@ -361,7 +361,7 @@ enum NeoPoolConstAndBitMask { MBMSK_NOTIF_MISC_CHANGED = 0x0020, // 5 Misc page changed // MBF_CELL_BOOST - MBMSK_CELL_BOOST_REDOX_CTL = 0x8000, // undocumented - Disable redox ctrl + MBMSK_CELL_BOOST_NO_REDOX_CTL = 0x8000, // undocumented - Disable redox ctrl MBMSK_CELL_BOOST_STATE = 0x0500, // undocumented - Boost MBMSK_CELL_BOOST_START = 0x00A0, // undocumented - Start boost @@ -586,13 +586,6 @@ bool neopool_system_gperh = false; // emulation defaults off #define NEOPOOL_RELAY_MAX 7 // Number of relais build-in -enum NeoPoolResult { - NEOPOOL_RESULT_DEC = false, - NEOPOOL_RESULT_HEX, - NEOPOOL_RESULT_MAX -}; -uint8_t neopool_result = NEOPOOL_RESULT_HEX; - bool neopool_active = false; volatile bool neopool_poll = true; @@ -614,21 +607,87 @@ void (* neopoll_cmd)(void) = nullptr; // Modbus register set to read // Defines blocks of register read once with a single read -struct { +typedef struct { const uint16_t addr; const uint16_t cnt; uint16_t *data; -} NeoPoolReg[] = { - // complete poll cycle needs 1750 ms to read complete register set - {MBF_ION_CURRENT, MBF_NOTIFICATION - MBF_ION_CURRENT + 1, nullptr}, - {MBF_CELL_RUNTIME_LOW, MBF_CELL_RUNTIME_POL_CHANGES_HIGH - MBF_CELL_RUNTIME_LOW + 1, nullptr}, - {MBF_PAR_VERSION, MBF_PAR_HIDRO_NOM - MBF_PAR_VERSION + 1, nullptr}, - {MBF_PAR_TIME_LOW, MBF_PAR_HEATING_GPIO - MBF_PAR_TIME_LOW + 1, nullptr}, - {MBF_PAR_ION, MBF_PAR_FILTRATION_CONF - MBF_PAR_ION + 1, nullptr}, - {MBF_PAR_UICFG_MACHINE, MBF_PAR_UICFG_MACH_VISUAL_STYLE - MBF_PAR_UICFG_MACHINE + 1, nullptr}, - {MBF_VOLT_24_36, MBF_VOLT_12 - MBF_VOLT_24_36 + 1, nullptr}, - {MBF_VOLT_5, MBF_AMP_4_20_MICRO - MBF_VOLT_5 + 1, nullptr} +} TNeoPoolReg; + +// complete poll cycle needs 2000 ms to read complete register set +#define NEOPOOL_REG_QUERY {\ + {MBF_ION_CURRENT, MBF_NOTIFICATION - MBF_ION_CURRENT + 1, nullptr},\ + {MBF_CELL_RUNTIME_LOW, MBF_CELL_RUNTIME_POL_CHANGES_HIGH - MBF_CELL_RUNTIME_LOW + 1, nullptr},\ + {MBF_PAR_VERSION, MBF_PAR_HIDRO_NOM - MBF_PAR_VERSION + 1, nullptr},\ + {MBF_PAR_TIME_LOW, MBF_PAR_HEATING_GPIO - MBF_PAR_TIME_LOW + 1, nullptr},\ + {MBF_PAR_ION, MBF_PAR_FILTRATION_CONF - MBF_PAR_ION + 1, nullptr},\ + {MBF_PAR_UICFG_MACHINE, MBF_PAR_UICFG_MACH_VISUAL_STYLE - MBF_PAR_UICFG_MACHINE + 1, nullptr},\ + {MBF_VOLT_24_36, MBF_VOLT_12 - MBF_VOLT_24_36 + 1, nullptr},\ + {MBF_VOLT_5, MBF_AMP_4_20_MICRO - MBF_VOLT_5 + 1, nullptr}\ +} +TNeoPoolReg NeoPoolReg[] = NEOPOOL_REG_QUERY; + +// Register to check for NPTelePeriod changes +const uint16_t NeoPoolRegCheck[] PROGMEM = { + // excl. values that change almost continuously + // MBF_PAR_TIME_LOW, + // MBF_PAR_TIME_HIGH, + // MBF_VOLT_12, + // MBF_VOLT_24_36, + // MBF_VOLT_5, + // MBF_AMP_4_20_MICRO, + // MBF_CELL_RUNTIME_LOW, + // MBF_CELL_RUNTIME_HIGH, + // MBF_CELL_RUNTIME_PART_LOW, + // MBF_CELL_RUNTIME_PART_HIGH, + // MBF_CELL_RUNTIME_POLA_LOW, + // MBF_CELL_RUNTIME_POLA_HIGH, + // MBF_CELL_RUNTIME_POLB_LOW, + // MBF_CELL_RUNTIME_POLB_HIGH, + // MBF_CELL_RUNTIME_POL_CHANGES_LOW, + // MBF_CELL_RUNTIME_POL_CHANGES_HIGH, + + // measured values delayed (set bit 15 to indicate often value changes) + MBF_ION_CURRENT | 0x8000, + MBF_MEASURE_CL | 0x8000, + MBF_MEASURE_CONDUCTIVITY | 0x8000, + MBF_MEASURE_PH | 0x8000, + MBF_MEASURE_RX | 0x8000, + MBF_MEASURE_TEMPERATURE | 0x8000, + MBF_HIDRO_CURRENT | 0x8000, + + // undelayed measured values + MBF_HIDRO_STATUS, + MBF_PH_STATUS, + MBF_RELAY_STATE, + + // undelayed setting values + MBF_CELL_BOOST, + MBF_PAR_CL1, + MBF_PAR_FILT_MODE, + MBF_PAR_HIDRO, + MBF_PAR_HIDRO_NOM, + MBF_PAR_ION, + MBF_PAR_PH1, + MBF_PAR_PH2, + MBF_PAR_RX1, + + MBF_PAR_CD_RELAY_GPIO, + MBF_PAR_CL_RELAY_GPIO, + MBF_PAR_FILT_GPIO, + MBF_PAR_FILTVALVE_GPIO, + MBF_PAR_HEATING_GPIO, + MBF_PAR_LIGHTING_GPIO, + MBF_PAR_PH_ACID_RELAY_GPIO, + MBF_PAR_PH_BASE_RELAY_GPIO, + MBF_PAR_RX_RELAY_GPIO, + MBF_PAR_UV_RELAY_GPIO, + MBF_PAR_ION_NOM, + MBF_PAR_TEMPERATURE_ACTIVE, + MBF_PAR_UICFG_MACHINE }; +uint16_t *NeoPoolRegCheckData; +uint32_t NeoPoolRegCheckDataTimeout = 0; + typedef struct { uint16_t addr; @@ -647,17 +706,38 @@ enum NeoPoolModbusCode { NEOPOOL_MODBUS_ERROR_DEADLOCK }; + + +// NPResult possible values +enum NeoPoolResult { + NEOPOOL_RESULT_DEC = false, + NEOPOOL_RESULT_HEX, + NEOPOOL_RESULT_MAX +}; + +// Sensor saved variables +#define NEOPOOL_SETTING_VERSION 0x0100 +#define NEOPOOL_DEFAULT_PHRES 1 +#define NEOPOOL_DEFAULT_CLRES 1 +#define NEOPOOL_DEFAULT_IONRES 1 +#define NEOPOOL_DEFAULT_RESULT NEOPOOL_RESULT_HEX +#define NEOPOOL_DEFAULT_NPTELEPERIOD 0 + // NeoPool value resolutions typedef struct { uint16_t ph : 2; uint16_t cl : 2; uint16_t ion : 2; } NeoPoolResMBitfield; -NeoPoolResMBitfield neopool_resolution { - .ph = 1, - .cl = 1, - .ion = 1 -}; + +// Global structure containing sensor saved variables +struct { + uint32_t crc32; + uint16_t version; + NeoPoolResMBitfield resolution; + uint8_t result; + uint16_t npteleperiod; +} NeoPoolSettings; #define D_NEOPOOL_NAME "NeoPool" @@ -703,6 +783,8 @@ NeoPoolResMBitfield neopool_resolution { #define D_NEOPOOL_JSON_UNIT "Unit" #define D_NEOPOOL_JSON_COVER "Cover" #define D_NEOPOOL_JSON_SHOCK "Boost" +#define D_NEOPOOL_JSON_OFF "OFF" +#define D_NEOPOOL_JSON_ON "ON" #define D_NEOPOOL_JSON_LOW "Low" #define D_NEOPOOL_JSON_SETPOINT "Setpoint" #define D_NEOPOOL_JSON_MIN "Min" @@ -759,6 +841,17 @@ const char kNeoPoolFiltrationSpeed[] PROGMEM = D_NEOPOOL_FILTRATION_FAST ; +const char kNeoPoolBoostCmnd[] PROGMEM = + D_NEOPOOL_JSON_OFF "|" + D_NEOPOOL_JSON_ON "|" + D_NEOPOOL_JSON_REDOX + ; + +const uint16_t sNeoPoolBoost[] PROGMEM = { + 0x0000, + MBMSK_CELL_BOOST_STATE | MBMSK_CELL_BOOST_START | MBMSK_CELL_BOOST_NO_REDOX_CTL, + MBMSK_CELL_BOOST_STATE | MBMSK_CELL_BOOST_START }; + const char kNeoPoolpHAlarms[] PROGMEM = D_NEOPOOL_SETPOINT_OK "|" D_NEOPOOL_PH_HIGH "|" @@ -824,6 +917,13 @@ const char HTTP_SNS_NEOPOOL_STATUS_ACTIVE[] PROGMEM = "filter:invert(1)"; * 2 - mid * 3 - high * + * NPBoost {} + * get/set hydrolysis/electrolysis boost mode (mode = 0..2) + * get mode if is omitted, otherwise set new mode according: + * 0|OFF - boost off + * 1|ON - boost on + * 2|REDOX - boost on with redox control + * * NPTime {