Skip to content

Commit 524c95b

Browse files
authored
Add Neopool cmnd NPReadLSB/NPReadMSB, NWriteLSB/NPWriteMSB (#24083)
* Add NeoPool display backlight register description * Add NeoPool cmnd `NPReadLSB/MSB`, `NWriteLSB/MSB`
1 parent fcf0809 commit 524c95b

File tree

2 files changed

+78
-35
lines changed

2 files changed

+78
-35
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ All notable changes to this project will be documented in this file.
1313
- Scripter array transfer via UFS (#24060)
1414
- ESP8266 GPIOViewer memory map if enabled with `#define GV_USE_ESPINFO`
1515
- Berry `tcp.write()` add `offset` and `len` (#24076)
16+
- NeoPool command `NPReadLSB`, `NPReadMSB`, `NPWriteLSB`, `NWriteMSB` for directly read/write LSB/MSB of 16-bit register
1617

1718
### Breaking Changed
1819

tasmota/tasmota_xsns_sensor/xsns_83_neopool.ino

Lines changed: 77 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
xsns_83_neopool.ino - Sugar Valley NeoPool Control System Modbus support for Tasmota
33
4-
Copyright (C) 2023 Norbert Richter
4+
Copyright (C) 2025 Norbert Richter
55
66
This program is free software: you can redistribute it and/or modify
77
it under the terms of the GNU General Public License as published by
@@ -50,17 +50,14 @@
5050
* Only one Modbus client (master) can be connected to the Modbus connector
5151
* of the same name. It is not possible to operate several clients on
5252
* connectors with the same name.
53-
*
5453
* The differently labelled Modbus connectors are completely independent
5554
* physical Modbus interfaces. Data traffic on one of the connector is
5655
* invisible on the other connectors. One exception is the DISPLAY connector,
5756
* which is present twice and is normally occupied by the built-in LCD.
5857
* Since only one Modbus client can operate one Modbus server at a time, the
5958
* DISPLAY connector is useless for our purposes as long as the internal LCD
6059
* is connected to one of the two DISPLAY connectors at the same time.
61-
*
62-
* Conclusion:
63-
* Use the WIFI or EXTERNAL connector only.
60+
* Conclusion: Use the WIFI or EXTERNAL connector only.
6461
\****************************************************************************/
6562

6663
#define XSNS_83 83
@@ -290,7 +287,7 @@ enum NeoPoolRegister {
290287
// Contains the configuration parameters for the screen controllers (language, colours, sound, etc).
291288
MBF_PAR_UICFG_MACHINE = 0x0600, // 0x0600* Machine type (see MBV_PAR_MACH_* and kNeoPoolMachineNames[])
292289
MBF_PAR_UICFG_LANGUAGE, // 0x0601* Selected language (see MBV_PAR_LANG_*)
293-
MBF_PAR_UICFG_BACKLIGHT, // 0x0602* Display backlight function (see MBV_PAR_BACKLIGHT_*)
290+
MBF_PAR_UICFG_BACKLIGHT, // 0x0602* Display backlight brightness (in %, upper part (8-bit MSB)=0-100) and function (lower part 8-bit LSB, see MBV_PAR_BACKLIGHT_*)
294291
MBF_PAR_UICFG_SOUND, // 0x0603* mask Audible alerts (see MBMSK_PAR_SOUND_*)
295292
MBF_PAR_UICFG_PASSWORD, // 0x0604* System password encoded in BCD
296293
MBF_PAR_UICFG_VISUAL_OPTIONS, // 0x0605* mask Stores the different display options for the user interface menus (bitmask). Some bits allow you to hide options that are normally visible (bits 0 to 3) while other bits allow you to show options that are normally hidden (bits 9 to 15)
@@ -517,7 +514,7 @@ enum NeoPoolConstAndBitMask {
517514
MBV_PAR_LANG_HUNGARIAN = 10,
518515
MBV_PAR_LANG_RUSSIAN = 11,
519516

520-
// MBF_PAR_UICFG_BACKLIGHT
517+
// MBF_PAR_UICFG_BACKLIGHT (LSB)
521518
MBV_PAR_BACKLIGHT_15SEC = 0, // Backlight off after 15 sec
522519
MBV_PAR_BACKLIGHT_30SEC = 1, // Backlight off after 30 sec
523520
MBV_PAR_BACKLIGHT_60SEC = 2, // Backlight off after 60 sec
@@ -1174,15 +1171,23 @@ const char HTTP_SNS_NEOPOOL_STATUS_ACTIVE[] PROGMEM = "filter:invert(1)";
11741171
*
11751172
* NPRead <addr> {<cnt>}
11761173
* NPReadL <addr> {<cnt>}
1177-
* read 16/32-bit register (cnt = 1..30|1..15), cnt = 1 if omitted
1178-
* NPRead read 16-bit register
1179-
* NPReadL read 32-bit register
1174+
* NPReadLSB <addr> {<cnt>}
1175+
* NPReadMSB <addr> {<cnt>}
1176+
* read 16|32-bit register (cnt = 1..30|1..15), cnt = 1 if omitted
1177+
* NPRead read 16-bit register
1178+
* NPReadL read 32-bit register
1179+
* NPReadLSB read 16-bit register LSB only (like NPRead, but only reads the least significant byte (LSB) of 16-bit register)
1180+
* NPReadMSB read 16-bit register MSB only (like NPRead, but only reads the most significant byte (MSB) of 16-bit register)
11801181
*
11811182
* NPWrite <addr> <data> {<data>...}
11821183
* NPWriteL <addr> <data> {<data>...}
1183-
* NPWrite write 16-bit register (data = 0..65535)
1184-
* NPWriteL write 32-bit register (data = 0..4294967295)
1185-
* The max. number of <data> parameters is 10
1184+
* NPWriteLSB <addr> <data> {<data>...}
1185+
* NPWriteMSB <addr> <data> {<data>...}
1186+
* write 16|32-bit register (the max. number of <data> parameters is 20|10)
1187+
* NPWrite write 16-bit register (data = 0..65535)
1188+
* NPWriteL write 32-bit register (data = 0..4294967295)
1189+
* NPWriteLSB write 16-bit register LSB only (data = 0..255, like NPWrite, but only writes the least significant byte (LSB) of 16-bit register)
1190+
* NPWriteMSB write 16-bit register MSB only (data = 0..255, like NPWrite, but only writes the most significant byte (LSB) of 16-bit register)
11861191
*
11871192
* NPBit <addr> <bit> {<data>}
11881193
* NPBitL <addr> <bit> {<data>}
@@ -1253,8 +1258,12 @@ const char HTTP_SNS_NEOPOOL_STATUS_ACTIVE[] PROGMEM = "filter:invert(1)";
12531258
#define D_CMND_NP_RESULT "Result"
12541259
#define D_CMND_NP_READ "Read"
12551260
#define D_CMND_NP_READL "ReadL"
1261+
#define D_CMND_NP_READLSB D_CMND_NP_READ "LSB"
1262+
#define D_CMND_NP_READMSB D_CMND_NP_READ "MSB"
12561263
#define D_CMND_NP_WRITE "Write"
12571264
#define D_CMND_NP_WRITEL "WriteL"
1265+
#define D_CMND_NP_WRITELSB D_CMND_NP_WRITE "LSB"
1266+
#define D_CMND_NP_WRITEMSB D_CMND_NP_WRITE "MSB"
12581267
#define D_CMND_NP_BIT "Bit"
12591268
#define D_CMND_NP_BITL "BitL"
12601269
#define D_CMND_NP_FILTRATION "Filtration"
@@ -1289,8 +1298,12 @@ const char kNPCommands[] PROGMEM = D_PRFX_NEOPOOL "|" // Prefix
12891298
D_CMND_NP_RESULT "|"
12901299
D_CMND_NP_READ "|"
12911300
D_CMND_NP_READL "|"
1301+
D_CMND_NP_READLSB "|"
1302+
D_CMND_NP_READMSB "|"
12921303
D_CMND_NP_WRITE "|"
12931304
D_CMND_NP_WRITEL "|"
1305+
D_CMND_NP_WRITELSB "|"
1306+
D_CMND_NP_WRITEMSB "|"
12941307
D_CMND_NP_BIT "|"
12951308
D_CMND_NP_BITL "|"
12961309
D_CMND_NP_FILTRATION "|"
@@ -1326,6 +1339,10 @@ void (* const NPCommand[])(void) PROGMEM = {
13261339
&CmndNeopoolResult,
13271340
&CmndNeopoolReadReg,
13281341
&CmndNeopoolReadReg,
1342+
&CmndNeopoolReadReg,
1343+
&CmndNeopoolReadReg,
1344+
&CmndNeopoolWriteReg,
1345+
&CmndNeopoolWriteReg,
13291346
&CmndNeopoolWriteReg,
13301347
&CmndNeopoolWriteReg,
13311348
&CmndNeopoolBit,
@@ -2520,7 +2537,7 @@ void NeoPoolShow(bool json)
25202537
* Command implementation
25212538
\****************************************************************************/
25222539

2523-
void NeopoolReadWriteResponse(uint16_t addr, uint16_t *data, uint16_t cnt, bool fbits32, int16_t bit)
2540+
void NeopoolReadWriteResponse(uint16_t addr, uint16_t *data, uint16_t cnt, bool fbits32, bool flsb, bool fmsb, int16_t bit)
25242541
{
25252542
const char *data_fmt;
25262543
uint32_t ldata;
@@ -2531,27 +2548,32 @@ void NeopoolReadWriteResponse(uint16_t addr, uint16_t *data, uint16_t cnt, bool
25312548

25322549
data_fmt = PSTR("%ld");
25332550
if (NEOPOOL_RESULT_HEX == NeoPoolSettings.result) {
2534-
data_fmt = fbits32 ? PSTR("\"0x%08X\"") : PSTR("\"0x%04X\"");
2535-
}
2536-
ldata = (uint32_t)data[0];
2537-
if (fbits32) {
2538-
ldata |= (uint32_t)data[1] << 16;
2551+
data_fmt = fbits32 ? PSTR("\"0x%08X\"") : (!flsb && !fmsb) ? PSTR("\"0x%04X\"") : PSTR("\"0x%02X\"");
25392552
}
2553+
char sdel[2] = {0};
25402554
if ( cnt > 1 ) {
2541-
char sdel[2] = {0};
25422555
ResponseAppend_P(PSTR("["));
2543-
for(uint16_t i=0; i<cnt; i++) {
2556+
}
2557+
for(uint16_t i=0; i<cnt; i++) {
2558+
if ( cnt > 1 ) {
25442559
ResponseAppend_P(PSTR("%s"), sdel);
2545-
ldata = (uint32_t)data[(fbits32+1)*i];
2546-
if (fbits32) {
2547-
ldata |= (uint32_t)data[(fbits32+1)*i+1] << 16;
2548-
}
2549-
ResponseAppend_P(data_fmt, ldata);
2550-
*sdel = ',';
25512560
}
2552-
ResponseAppend_P(PSTR("]"));
2553-
} else {
2561+
ldata = (uint32_t)data[(fbits32+1)*i];
2562+
if (fbits32) {
2563+
ldata |= (uint32_t)data[(fbits32+1)*i+1] << 16;
2564+
}
2565+
else if (flsb) {
2566+
ldata &= 0xff;
2567+
}
2568+
else if (fmsb) {
2569+
ldata >>= 8;
2570+
ldata &= 0xff;
2571+
}
25542572
ResponseAppend_P(data_fmt, ldata);
2573+
*sdel = ',';
2574+
}
2575+
if ( cnt > 1 ) {
2576+
ResponseAppend_P(PSTR("]"));
25552577
}
25562578
if (bit >= 0) {
25572579
ResponseAppend_P(PSTR(",\"" D_NEOPOOL_JSON_BIT "%d\":%ld"), bit, (ldata>>bit) & 1);
@@ -2587,6 +2609,8 @@ void CmndNeopoolReadReg(void)
25872609
uint32_t value[2] = { 0 };
25882610
uint32_t params_cnt = ParseParameters(nitems(value), value);
25892611
bool fbits32 = !strcasecmp_P(XdrvMailbox.command, PSTR(D_PRFX_NEOPOOL D_CMND_NP_READL));
2612+
bool flsb = !strcasecmp_P(XdrvMailbox.command, PSTR(D_PRFX_NEOPOOL D_CMND_NP_READLSB));
2613+
bool fmsb = !strcasecmp_P(XdrvMailbox.command, PSTR(D_PRFX_NEOPOOL D_CMND_NP_READMSB));
25902614

25912615
cnt = 1;
25922616
if (2 == params_cnt) {
@@ -2599,7 +2623,7 @@ void CmndNeopoolReadReg(void)
25992623
return;
26002624
}
26012625
}
2602-
NeopoolReadWriteResponse(addr, data, cnt, fbits32, -1);
2626+
NeopoolReadWriteResponse(addr, data, cnt, fbits32, flsb, fmsb, -1);
26032627
}
26042628

26052629

@@ -2609,16 +2633,34 @@ void CmndNeopoolWriteReg(void)
26092633
uint32_t value[(nitems(data)/2)+1] = { 0 };
26102634
uint32_t params_cnt = ParseParameters(nitems(value), value);
26112635
bool fbits32 = !strcasecmp_P(XdrvMailbox.command, PSTR(D_PRFX_NEOPOOL D_CMND_NP_WRITEL));
2636+
bool flsb = !strcasecmp_P(XdrvMailbox.command, PSTR(D_PRFX_NEOPOOL D_CMND_NP_WRITELSB));
2637+
bool fmsb = !strcasecmp_P(XdrvMailbox.command, PSTR(D_PRFX_NEOPOOL D_CMND_NP_WRITEMSB));
26122638

2613-
if (params_cnt > 1) {
2639+
cnt = params_cnt-1;
2640+
if (params_cnt > 1 && cnt < (fbits32 ? (nitems(data)/2) : nitems(data))) {
26142641
addr = value[0];
2615-
cnt = params_cnt-1;
2642+
if (flsb || fmsb) {
2643+
if (NEOPOOL_MODBUS_OK != NeoPoolReadRegister(addr, data, fbits32 ? (cnt*2) : cnt)) {
2644+
NeopoolResponseError();
2645+
return;
2646+
}
2647+
}
26162648
for (uint32_t i = 0; i < cnt; i++) {
26172649
if (fbits32) {
26182650
data[i*2] = value[i+1]; // LSB
26192651
data[i*2+1] = value[i+1]>>16; // MSB
26202652
} else {
2621-
data[i] = value[i+1];
2653+
if (flsb) {
2654+
data[i] &= 0xff00;
2655+
data[i] |= (value[i+1] & 0xff);
2656+
}
2657+
else if (fmsb) {
2658+
data[i] &= 0x00ff;
2659+
data[i] |= (value[i+1] & 0xff)<<8;
2660+
}
2661+
else {
2662+
data[i] = value[i+1];
2663+
}
26222664
}
26232665
}
26242666
if (NEOPOOL_MODBUS_OK != NeoPoolWriteRegister(addr, data, fbits32 ? cnt*2 : cnt)) {
@@ -2630,7 +2672,7 @@ void CmndNeopoolWriteReg(void)
26302672
NeopoolResponseError();
26312673
return;
26322674
}
2633-
NeopoolReadWriteResponse(addr, data, cnt, fbits32, -1);
2675+
NeopoolReadWriteResponse(addr, data, cnt, fbits32, flsb, fmsb, -1);
26342676
}
26352677

26362678

@@ -2674,7 +2716,7 @@ void CmndNeopoolBit(void)
26742716
NeopoolResponseError();
26752717
return;
26762718
}
2677-
NeopoolReadWriteResponse(addr, &data, 1, fbits32, bit);
2719+
NeopoolReadWriteResponse(addr, &data, 1, fbits32, false, false, bit);
26782720
return;
26792721
}
26802722

0 commit comments

Comments
 (0)