Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Neopool enhancements for HA #19857

Merged
merged 4 commits into from
Oct 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ All notable changes to this project will be documented in this file.
- Command ``GpioRead`` to show input state (#19810)
- ESP32 core v3 auto TasConsole USB or Serial connection by @staars
- Support for Winsen XH03x dust particle sensors using USE_PMS5003 and PMS_MODEL_ZH03X (#19850)
- NeoPool hydrolysis setpoint and max
- NeoPool command ``NPFiltrationSpeed`` to set non-standard filtration type speed
- NeoPool ``SetOption157`` to output sensitive data

### Breaking Changed
- NeoPool SENSOR topic ``Power`` renamed to ``Powerunit``

### Changed
- Prepare I2C drivers for bus2 support
Expand Down
2 changes: 1 addition & 1 deletion tasmota/include/tasmota_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t berry_light_scheme : 1; // bit 8 (v12.5.0.3) - SetOption154 - (Berry) Handle berry led using RMT0 as additional WS2812 scheme
uint32_t zcfallingedge : 1; // bit 9 (v13.0.0.1) - SetOption155 - (ZCDimmer) Enable rare falling Edge dimmer instead of leading edge
uint32_t sen5x_passive_mode : 1; // bit 10 (v13.1.0.1) - SetOption156 - (Sen5x) Run in passive mode when there is another I2C master (e.g. Ikea Vindstyrka), i.e. do not set up Sen5x sensor, higher polling interval
uint32_t spare11 : 1; // bit 11
uint32_t neopool_outputsensitive : 1; // bit 11 (v13.2.0.1) - SetOption157 - (NeoPool) Output sensitive data (1)
uint32_t spare12 : 1; // bit 12
uint32_t spare13 : 1; // bit 13
uint32_t spare14 : 1; // bit 14
Expand Down
92 changes: 79 additions & 13 deletions tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,7 @@ NeoPoolResMBitfield neopool_resolution {
#define D_NEOPOOL_JSON_FILTRATION_INTELLIGENT "Intelligent"
#define D_NEOPOOL_JSON_FILTRATION_BACKWASH "Backwash"
#define D_NEOPOOL_JSON_MODULES "Modules"
#define D_NEOPOOL_JSON_POWERUNIT "Powerunit"
#define D_NEOPOOL_JSON_CHLORINE "Chlorine"
#define D_NEOPOOL_JSON_CONDUCTIVITY "Conductivity"
#define D_NEOPOOL_JSON_FILTRATION "Filtration"
Expand Down Expand Up @@ -806,6 +807,14 @@ const char HTTP_SNS_NEOPOOL_STATUS_ACTIVE[] PROGMEM = "filter:invert(1)";
* 4 - Intelligent
* 13 - Backwash
*
* NPFiltrationSpeed {<speed>}
* (only available for non-standard filtration types)
* get/set manual filtration speed (speed = 1..3)
* get filtration speed if <speed> is omitted, otherwise set new speed
* 1 - low
* 2 - mid
* 3 - high
*
* NPTime {<time>}
* get/set system time
* get current time if <time> is omitted, otherwise set time according:
Expand Down Expand Up @@ -974,6 +983,7 @@ const char HTTP_SNS_NEOPOOL_STATUS_ACTIVE[] PROGMEM = "filter:invert(1)";
#define D_CMND_NP_BITL "BitL"
#define D_CMND_NP_FILTRATION "Filtration"
#define D_CMND_NP_FILTRATIONMODE "Filtrationmode"
#define D_CMND_NP_FILTRATIONSPEED "Filtrationspeed"
#define D_CMND_NP_TIME "Time"
#define D_CMND_NP_LIGHT "Light"
#define D_CMND_NP_PHMIN "pHMin"
Expand Down Expand Up @@ -1002,6 +1012,7 @@ const char kNPCommands[] PROGMEM = D_PRFX_NEOPOOL "|" // Prefix
D_CMND_NP_BITL "|"
D_CMND_NP_FILTRATION "|"
D_CMND_NP_FILTRATIONMODE "|"
D_CMND_NP_FILTRATIONSPEED "|"
D_CMND_NP_TIME "|"
D_CMND_NP_LIGHT "|"
D_CMND_NP_PHMIN "|"
Expand Down Expand Up @@ -1031,6 +1042,7 @@ void (* const NPCommand[])(void) PROGMEM = {
&CmndNeopoolBit,
&CmndNeopoolFiltration,
&CmndNeopoolFiltrationMode,
&CmndNeopoolFiltrationSpeed,
&CmndNeopoolTime,
&CmndNeopoolLight,
&CmndNeopoolpHMin,
Expand Down Expand Up @@ -1527,7 +1539,7 @@ void NeoPoolShow(bool json)
float f12volt = (float)NeoPoolGetData(MBF_VOLT_12)/1000;
float f24_36volt = (float)NeoPoolGetData(MBF_VOLT_24_36)/1000;
float f420mA = (float)NeoPoolGetData(MBF_AMP_4_20_MICRO)/100;
ResponseAppend_P(PSTR(",\"" D_JSON_POWERUSAGE "\":{"));
ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_POWERUNIT "\":{"));
if (neopool_power_module_version ||
NEOPOOL_MODBUS_OK == NeoPoolReadRegister(MBF_POWER_MODULE_VERSION, &neopool_power_module_version, 1)) {
ResponseAppend_P(PSTR("\"" D_JSON_VERSION "\":\"V%d.%d\","),
Expand All @@ -1537,14 +1549,21 @@ void NeoPoolShow(bool json)
}
if (neopool_power_module_nodeid[0] ||
NEOPOOL_MODBUS_OK == NeoPoolReadRegister(MBF_POWER_MODULE_NODEID, neopool_power_module_nodeid, nitems(neopool_power_module_nodeid))) {
ResponseAppend_P(PSTR("\"" D_NEOPOOL_JSON_NODE_ID "\":\"%04X %04X %04X %04X %04X %04X\","),
neopool_power_module_nodeid[0],
neopool_power_module_nodeid[1],
neopool_power_module_nodeid[2],
neopool_power_module_nodeid[3],
neopool_power_module_nodeid[4],
neopool_power_module_nodeid[5]
);
if (Settings->flag6.neopool_outputsensitive) {
ResponseAppend_P(PSTR("\"" D_NEOPOOL_JSON_NODE_ID "\":\"%04X %04X %04X %04X %04X %04X\","),
neopool_power_module_nodeid[0],
neopool_power_module_nodeid[1],
neopool_power_module_nodeid[2],
neopool_power_module_nodeid[3],
neopool_power_module_nodeid[4],
neopool_power_module_nodeid[5]
);
}
else {
ResponseAppend_P(PSTR("\"" D_NEOPOOL_JSON_NODE_ID "\":\"XXXX XXXX XXXX XXXX XXXX %04X\","),
neopool_power_module_nodeid[5]
);
}
}
ResponseAppend_P(PSTR("\"5V\":%*_f,\"12V\":%*_f,\"24-30V\":%*_f,\"4-20mA\":%*_f}"),
Settings->flag2.voltage_resolution, &f5volt,
Expand Down Expand Up @@ -1629,9 +1648,14 @@ void NeoPoolShow(bool json)
sunit = PSTR(D_NEOPOOL_UNIT_GPERH);
int dec = 1;
}
ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_HYDROLYSIS "\":{"));
fvalue = (float)NeoPoolGetData(MBF_HIDRO_CURRENT)/10;
ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_HYDROLYSIS "\":{\"" D_JSON_DATA "\":" NEOPOOL_FMT_HIDRO), dec, &fvalue);
ResponseAppend_P(PSTR( "\"" D_JSON_DATA "\":" NEOPOOL_FMT_HIDRO), dec, &fvalue);
ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_UNIT "\":\"%s\""), sunit);
fvalue = (float)NeoPoolGetData(MBF_PAR_HIDRO)/10;
ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_SETPOINT "\":" NEOPOOL_FMT_HIDRO), dec, &fvalue);
fvalue = (float)NeoPoolGetData(MBF_PAR_HIDRO_NOM)/10;
ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_MAX "\":" NEOPOOL_FMT_HIDRO), dec, &fvalue);

ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_CELL_RUNTIME "\":{"));
ResponseAppend_P(PSTR( "\"" D_NEOPOOL_JSON_CELL_RUNTIME_TOTAL "\":\"%s\""), GetDuration(NeoPoolGetDataLong(MBF_CELL_RUNTIME_LOW)).c_str());
Expand Down Expand Up @@ -1760,7 +1784,14 @@ void NeoPoolShow(bool json)
}
fvalue = (float)NeoPoolGetData(MBF_HIDRO_CURRENT)/10;
WSContentSend_PD(HTTP_SNS_NEOPOOL_HYDROLYSIS, neopool_type, dec, &fvalue, sunit);

// S1
float fhidromax = (float)NeoPoolGetData(MBF_PAR_HIDRO)/10;
ext_snprintf_P(stemp, sizeof(stemp), PSTR(NEOPOOL_FMT_HIDRO " %s"), dec, &fhidromax, sunit);
WSContentSend_PD(HTTP_SNS_NEOPOOL_STATUS, bg_color, HTTP_SNS_NEOPOOL_STATUS_INACTIVE, stemp);
WSContentSend_PD(PSTR(" "));

// S2
if (0 == (NeoPoolGetData(MBF_HIDRO_STATUS) & MBMSK_HIDRO_STATUS_MODULE_ACTIVE)) {
WSContentSend_PD(HTTP_SNS_NEOPOOL_STATUS, bg_color, HTTP_SNS_NEOPOOL_STATUS_NORMAL, PSTR(D_NEOPOOL_STATUS_OFF));
} else if (0 == (NeoPoolGetData(MBF_HIDRO_STATUS) & MBMSK_HIDRO_STATUS_FL1)) {
Expand All @@ -1773,14 +1804,14 @@ void NeoPoolShow(bool json)
WSContentSend_PD(HTTP_SNS_NEOPOOL_STATUS, bg_color, HTTP_SNS_NEOPOOL_STATUS_NORMAL, PSTR(D_NEOPOOL_STATUS_OFF));
}
WSContentSend_PD(PSTR(" "));
// S2
// S3
if (NeoPoolGetData(MBF_HIDRO_STATUS) & MBMSK_HIDRO_STATUS_COVER) {
WSContentSend_PD(HTTP_SNS_NEOPOOL_STATUS, bg_color, HTTP_SNS_NEOPOOL_STATUS_ACTIVE, PSTR(D_NEOPOOL_COVER));
} else {
WSContentSend_PD(HTTP_SNS_NEOPOOL_STATUS, bg_color, HTTP_SNS_NEOPOOL_STATUS_DISABLED, PSTR(D_NEOPOOL_COVER));
}
WSContentSend_PD(PSTR(" "));
// S3
// S4
if (NeoPoolGetData(MBF_HIDRO_STATUS) & MBMSK_HIDRO_STATUS_SHOCK_ENABLED) {
if ((NeoPoolGetData(MBF_CELL_BOOST) & MBMSK_CELL_BOOST_REDOX_CTL) == 0) {
WSContentSend_PD(HTTP_SNS_NEOPOOL_STATUS, bg_color, HTTP_SNS_NEOPOOL_STATUS_ACTIVE, PSTR(D_NEOPOOL_SHOCK "+" D_NEOPOOL_REDOX));
Expand All @@ -1791,7 +1822,7 @@ void NeoPoolShow(bool json)
WSContentSend_PD(HTTP_SNS_NEOPOOL_STATUS, bg_color, HTTP_SNS_NEOPOOL_STATUS_DISABLED, PSTR(D_NEOPOOL_SHOCK));
}
WSContentSend_PD(PSTR(" "));
// S4
// S5
if (NeoPoolGetData(MBF_HIDRO_STATUS) & MBMSK_HIDRO_STATUS_LOW) {
WSContentSend_PD(HTTP_SNS_NEOPOOL_STATUS, bg_color, HTTP_SNS_NEOPOOL_STATUS_ACTIVE, PSTR(D_NEOPOOL_LOW));
} else {
Expand Down Expand Up @@ -2225,6 +2256,41 @@ void CmndNeopoolFiltrationMode(void)
}


void CmndNeopoolFiltrationSpeed(void)
{
uint16_t speed;
uint16_t filtration_conf;

if (NEOPOOL_MODBUS_OK != NeoPoolReadRegister(MBF_PAR_FILTRATION_CONF, &filtration_conf, 1)) {
NeopoolResponseError();
return;
}
if (MBV_PAR_FILTRATION_TYPE_STANDARD == (filtration_conf & MBMSK_PAR_FILTRATION_CONF_TYPE)) {
// no speed control for standard filtration types
NeopoolCmndError();
return;
}

speed = NeoPoolGetFiltrationSpeed();
if (XdrvMailbox.data_len) {
if (XdrvMailbox.payload >= 1 && XdrvMailbox.payload <= 3) {
speed = XdrvMailbox.payload;
// Set filtration speed
if (NEOPOOL_MODBUS_OK != NeoPoolWriteRegisterWord(MBF_PAR_FILTRATION_CONF,
(filtration_conf & ~MBMSK_PAR_FILTRATION_CONF_DEF_SPEED) | ((speed - 1) << MBSHFT_PAR_FILTRATION_CONF_DEF_SPEED))) {
NeopoolResponseError();
return;
}
NeoPoolWriteRegisterWord(MBF_EXEC, 1);
} else {
NeopoolCmndError();
return;
}
}
ResponseCmndNumber(speed);
}


void CmndNeopoolTime(void)
{
uint16_t data[2];
Expand Down