nodejs-poolcontroller 7.7.0 → 8.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +26 -35
- package/Changelog +22 -0
- package/README.md +7 -3
- package/anslq25/MessagesMock.ts +218 -0
- package/anslq25/boards/MockBoardFactory.ts +50 -0
- package/anslq25/boards/MockEasyTouchBoard.ts +696 -0
- package/anslq25/boards/MockSystemBoard.ts +217 -0
- package/anslq25/chemistry/MockChlorinator.ts +75 -0
- package/anslq25/pumps/MockPump.ts +84 -0
- package/app.ts +10 -14
- package/config/Config.ts +13 -9
- package/config/VersionCheck.ts +6 -2
- package/controller/Constants.ts +58 -25
- package/controller/Equipment.ts +225 -41
- package/controller/Errors.ts +2 -1
- package/controller/Lockouts.ts +34 -2
- package/controller/State.ts +491 -48
- package/controller/boards/AquaLinkBoard.ts +6 -3
- package/controller/boards/BoardFactory.ts +5 -1
- package/controller/boards/EasyTouchBoard.ts +1971 -1751
- package/controller/boards/IntelliCenterBoard.ts +1311 -1688
- package/controller/boards/IntelliComBoard.ts +7 -1
- package/controller/boards/IntelliTouchBoard.ts +153 -42
- package/controller/boards/NixieBoard.ts +209 -66
- package/controller/boards/SunTouchBoard.ts +393 -0
- package/controller/boards/SystemBoard.ts +1862 -1543
- package/controller/comms/Comms.ts +539 -138
- package/controller/comms/ScreenLogic.ts +1663 -0
- package/controller/comms/messages/Messages.ts +242 -60
- package/controller/comms/messages/config/ChlorinatorMessage.ts +4 -3
- package/controller/comms/messages/config/CircuitGroupMessage.ts +5 -2
- package/controller/comms/messages/config/CircuitMessage.ts +81 -13
- package/controller/comms/messages/config/ConfigMessage.ts +3 -1
- package/controller/comms/messages/config/CoverMessage.ts +2 -1
- package/controller/comms/messages/config/CustomNameMessage.ts +2 -1
- package/controller/comms/messages/config/EquipmentMessage.ts +5 -1
- package/controller/comms/messages/config/ExternalMessage.ts +33 -3
- package/controller/comms/messages/config/FeatureMessage.ts +2 -1
- package/controller/comms/messages/config/GeneralMessage.ts +2 -1
- package/controller/comms/messages/config/HeaterMessage.ts +3 -1
- package/controller/comms/messages/config/IntellichemMessage.ts +2 -1
- package/controller/comms/messages/config/OptionsMessage.ts +12 -6
- package/controller/comms/messages/config/PumpMessage.ts +9 -12
- package/controller/comms/messages/config/RemoteMessage.ts +80 -13
- package/controller/comms/messages/config/ScheduleMessage.ts +43 -3
- package/controller/comms/messages/config/SecurityMessage.ts +2 -1
- package/controller/comms/messages/config/ValveMessage.ts +43 -26
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +8 -7
- package/controller/comms/messages/status/EquipmentStateMessage.ts +93 -20
- package/controller/comms/messages/status/HeaterStateMessage.ts +24 -5
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +7 -4
- package/controller/comms/messages/status/IntelliValveStateMessage.ts +2 -1
- package/controller/comms/messages/status/PumpStateMessage.ts +72 -4
- package/controller/comms/messages/status/VersionMessage.ts +2 -1
- package/controller/nixie/Nixie.ts +15 -4
- package/controller/nixie/NixieEquipment.ts +1 -0
- package/controller/nixie/chemistry/ChemController.ts +300 -129
- package/controller/nixie/chemistry/ChemDoser.ts +806 -0
- package/controller/nixie/chemistry/Chlorinator.ts +133 -129
- package/controller/nixie/circuits/Circuit.ts +171 -30
- package/controller/nixie/heaters/Heater.ts +337 -173
- package/controller/nixie/pumps/Pump.ts +264 -236
- package/controller/nixie/schedules/Schedule.ts +9 -3
- package/defaultConfig.json +46 -5
- package/logger/Logger.ts +38 -9
- package/package.json +13 -9
- package/web/Server.ts +235 -122
- package/web/bindings/aqualinkD.json +114 -59
- package/web/bindings/homeassistant.json +437 -0
- package/web/bindings/influxDB.json +15 -0
- package/web/bindings/mqtt.json +28 -9
- package/web/bindings/mqttAlt.json +15 -0
- package/web/interfaces/baseInterface.ts +58 -7
- package/web/interfaces/httpInterface.ts +5 -2
- package/web/interfaces/influxInterface.ts +9 -2
- package/web/interfaces/mqttInterface.ts +234 -74
- package/web/interfaces/ruleInterface.ts +87 -0
- package/web/services/config/Config.ts +140 -33
- package/web/services/config/ConfigSocket.ts +2 -1
- package/web/services/state/State.ts +144 -3
- package/web/services/state/StateSocket.ts +65 -14
- package/web/services/utilities/Utilities.ts +189 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* nodejs-poolController. An application to control pool equipment.
|
|
2
|
-
Copyright (C) 2016, 2017, 2018, 2019, 2020
|
|
2
|
+
Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021, 2022.
|
|
3
|
+
Russell Goldin, tagyoureit. russ.goldin@gmail.com
|
|
3
4
|
|
|
4
5
|
This program is free software: you can redistribute it and/or modify
|
|
5
6
|
it under the terms of the GNU Affero General Public License as
|
|
@@ -14,12 +15,51 @@ GNU Affero General Public License for more details.
|
|
|
14
15
|
You should have received a copy of the GNU Affero General Public License
|
|
15
16
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
17
|
*/
|
|
17
|
-
import { Inbound } from "../Messages";
|
|
18
|
+
import { Inbound, Outbound, Protocol } from "../Messages";
|
|
18
19
|
import { state } from "../../../State";
|
|
19
20
|
import { sys, ControllerType } from "../../../Equipment";
|
|
21
|
+
import { conn } from "../../Comms";
|
|
22
|
+
import { logger } from "../../../../logger/Logger";
|
|
23
|
+
|
|
20
24
|
export class PumpStateMessage {
|
|
25
|
+
private static detectPumpType(msg: Inbound) {
|
|
26
|
+
let pumpType = -1;
|
|
27
|
+
switch (msg.action) {
|
|
28
|
+
case 1:
|
|
29
|
+
{
|
|
30
|
+
let speed = (msg.extractPayloadByte(2) * 256) + msg.extractPayloadByte(3);
|
|
31
|
+
if (speed > 0) {
|
|
32
|
+
pumpType = speed < 300 ? sys.board.valueMaps.pumpTypes.getValue('vf') : sys.board.valueMaps.pumpTypes.getValue('vs');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
break;
|
|
36
|
+
case 9:
|
|
37
|
+
case 10:
|
|
38
|
+
pumpType = sys.board.valueMaps.pumpTypes.getValue('vsf');
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
if (pumpType > 0) {
|
|
42
|
+
let pump = sys.pumps.find(x => x.address === msg.dest);
|
|
43
|
+
if (typeof pump === 'undefined') {
|
|
44
|
+
let id = sys.pumps.filter(elem => elem.master === 0).getMaxId(false, 0) + 1;
|
|
45
|
+
pump = sys.pumps.getItemById(id, true);
|
|
46
|
+
pump.name = `Pump ${msg.dest - 95}`;
|
|
47
|
+
pump.address = msg.dest;
|
|
48
|
+
pump.isActive = true;
|
|
49
|
+
pump.type = pumpType;
|
|
50
|
+
pump.master = 0;
|
|
51
|
+
}
|
|
52
|
+
let spump = state.pumps.getItemById(pump.id, true);
|
|
53
|
+
spump.address = pump.address;
|
|
54
|
+
spump.type = pump.type;
|
|
55
|
+
spump.isActive = pump.isActive;
|
|
56
|
+
spump.name = pump.name;
|
|
57
|
+
spump.type = pump.type;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
21
60
|
public static process(msg: Inbound) {
|
|
22
61
|
if (sys.controllerType === ControllerType.Unknown) return;
|
|
62
|
+
if (msg.dest >= 96 && sys.controllerType === ControllerType.SunTouch) PumpStateMessage.detectPumpType(msg);
|
|
23
63
|
|
|
24
64
|
// We only want to process the messages that are coming from the pump not to the pump. At some point
|
|
25
65
|
// this filter was removed. Any messages that are coming from the panel are simply requests to the pump
|
|
@@ -33,6 +73,29 @@ export class PumpStateMessage {
|
|
|
33
73
|
let ptype = sys.board.valueMaps.pumpTypes.transform(pumpCfg.type);
|
|
34
74
|
let pump = state.pumps.getItemById(pumpId, pumpCfg.isActive === true);
|
|
35
75
|
switch (msg.action) {
|
|
76
|
+
case 1:
|
|
77
|
+
if (msg.source === 96 && sys.controllerType === ControllerType.EasyTouch) {
|
|
78
|
+
if (sys.equipment.modules.getItemByIndex(0, false).type >= 128) {
|
|
79
|
+
// EasyTouch Version 1 controllers do not request the current information about rpms or wattage from the pump. We need to ask in
|
|
80
|
+
// its stead.
|
|
81
|
+
let out = Outbound.create({
|
|
82
|
+
portId: pumpCfg.portId || 0,
|
|
83
|
+
protocol: Protocol.Pump,
|
|
84
|
+
dest: pumpCfg.address,
|
|
85
|
+
action: 7,
|
|
86
|
+
payload: [],
|
|
87
|
+
retries: 1,
|
|
88
|
+
response: true,
|
|
89
|
+
onComplete: (err, _) => {
|
|
90
|
+
if (err) {
|
|
91
|
+
logger.error(`EasyTouch 1 request pump status failed for ${pump.name}: ${err.message}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
conn.queueSendMessage(out);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
break;
|
|
36
99
|
case 7:
|
|
37
100
|
//[165, 63, 15, 16, 2, 29][11, 47, 32, 0, 0, 0, 0, 0, 0, 32, 0, 0, 2, 0, 59, 59, 0, 241, 56, 121, 24, 246, 0, 0, 0, 0, 0, 23, 0][4, 219]
|
|
38
101
|
//[165, 0, 96, 16, 1, 4][2, 196, 7, 58][2, 33]
|
|
@@ -57,7 +120,7 @@ export class PumpStateMessage {
|
|
|
57
120
|
}
|
|
58
121
|
public static processHayward(msg: Inbound) {
|
|
59
122
|
switch (msg.action) {
|
|
60
|
-
case 12:
|
|
123
|
+
case 12: // This is a pump status message
|
|
61
124
|
PumpStateMessage.processHaywardStar(msg);
|
|
62
125
|
break;
|
|
63
126
|
}
|
|
@@ -67,7 +130,10 @@ export class PumpStateMessage {
|
|
|
67
130
|
//[0x10, 0x02, 0x00, 0x0C, 0x00][0x00, 0x62, 0x17, 0x81][0x01, 0x18, 0x10, 0x03]
|
|
68
131
|
//[0x10, 0x02, 0x00, 0x0C, 0x00][0x00, 0x2D, 0x02, 0x36][0x00, 0x83, 0x10, 0x03] -- Response from pump
|
|
69
132
|
let ptype = sys.board.valueMaps.pumpTypes.transformByName('hwvs');
|
|
70
|
-
let
|
|
133
|
+
let address = msg.source + 96;
|
|
134
|
+
//console.log({ src: msg.source, dest: msg.dest, action: msg.action, address: address });
|
|
135
|
+
|
|
136
|
+
let pump = sys.pumps.find(elem => elem.address === address && elem.type === 6);
|
|
71
137
|
if (typeof pump !== 'undefined') {
|
|
72
138
|
let pstate = state.pumps.getItemById(pump.id, true);
|
|
73
139
|
// 3450 * .5
|
|
@@ -75,6 +141,8 @@ export class PumpStateMessage {
|
|
|
75
141
|
// This is really goofy as the watts are actually the hex string from the two bytes.
|
|
76
142
|
pstate.watts = parseInt(msg.extractPayloadByte(2).toString(16) + msg.extractPayloadByte(3).toString(16), 10);
|
|
77
143
|
pstate.isActive = true;
|
|
144
|
+
pstate.command = (pstate.rpm > 0 || pstate.watts > 0) ? 10 : 0;
|
|
145
|
+
pstate.driveState
|
|
78
146
|
state.emitEquipmentChanges();
|
|
79
147
|
}
|
|
80
148
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* nodejs-poolController. An application to control pool equipment.
|
|
2
|
-
Copyright (C) 2016, 2017, 2018, 2019, 2020
|
|
2
|
+
Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021, 2022.
|
|
3
|
+
Russell Goldin, tagyoureit. russ.goldin@gmail.com
|
|
3
4
|
|
|
4
5
|
This program is free software: you can redistribute it and/or modify
|
|
5
6
|
it under the terms of the GNU Affero General Public License as
|
|
@@ -5,6 +5,7 @@ import { webApp } from "../../web/Server";
|
|
|
5
5
|
import { logger } from "../../logger/Logger";
|
|
6
6
|
import { INixieControlPanel } from "./NixieEquipment";
|
|
7
7
|
import { NixieChemControllerCollection } from "./chemistry/ChemController";
|
|
8
|
+
import { NixieChemDoserCollection } from "./chemistry/ChemDoser";
|
|
8
9
|
|
|
9
10
|
import { sys, PoolSystem } from "../../controller/Equipment";
|
|
10
11
|
import { NixieCircuitCollection } from './circuits/Circuit';
|
|
@@ -55,6 +56,7 @@ export class NixieControlPanel implements INixieControlPanel {
|
|
|
55
56
|
// Only equipment controlled by Nixie is represented on the controller. If interaction with
|
|
56
57
|
// other equipment is required this should be sent back through the original controller.
|
|
57
58
|
// Command sequence is <OCP>Board -> SystemBoard -> NixieController whenever the master is not identified as Nixie.
|
|
59
|
+
chemDosers: NixieChemDoserCollection = new NixieChemDoserCollection(this);
|
|
58
60
|
chemControllers: NixieChemControllerCollection = new NixieChemControllerCollection(this);
|
|
59
61
|
chlorinators: NixieChlorinatorCollection = new NixieChlorinatorCollection(this);
|
|
60
62
|
circuits: NixieCircuitCollection = new NixieCircuitCollection(this);
|
|
@@ -64,7 +66,14 @@ export class NixieControlPanel implements INixieControlPanel {
|
|
|
64
66
|
heaters: NixieHeaterCollection = new NixieHeaterCollection(this);
|
|
65
67
|
pumps: NixiePumpCollection = new NixiePumpCollection(this);
|
|
66
68
|
schedules: NixieScheduleCollection = new NixieScheduleCollection(this);
|
|
67
|
-
|
|
69
|
+
public async setServiceModeAsync() {
|
|
70
|
+
await this.circuits.setServiceModeAsync();
|
|
71
|
+
await this.heaters.setServiceModeAsync();
|
|
72
|
+
await this.chlorinators.setServiceModeAsync();
|
|
73
|
+
await this.chemControllers.setServiceModeAsync();
|
|
74
|
+
await this.chemDosers.setServiceModeAsync();
|
|
75
|
+
await this.pumps.setServiceModeAsync();
|
|
76
|
+
}
|
|
68
77
|
public async initAsync(equipment: PoolSystem) {
|
|
69
78
|
try {
|
|
70
79
|
|
|
@@ -80,6 +89,7 @@ export class NixieControlPanel implements INixieControlPanel {
|
|
|
80
89
|
await this.heaters.initAsync(equipment.heaters);
|
|
81
90
|
await this.chlorinators.initAsync(equipment.chlorinators);
|
|
82
91
|
await this.chemControllers.initAsync(equipment.chemControllers);
|
|
92
|
+
await this.chemDosers.initAsync(equipment.chemDosers);
|
|
83
93
|
await this.pumps.initAsync(equipment.pumps);
|
|
84
94
|
await this.schedules.initAsync(equipment.schedules);
|
|
85
95
|
logger.info(`Nixie Controller Initialized`)
|
|
@@ -97,7 +107,7 @@ export class NixieControlPanel implements INixieControlPanel {
|
|
|
97
107
|
lines = buff.toString().split('\n');
|
|
98
108
|
}
|
|
99
109
|
return lines;
|
|
100
|
-
} catch (err) { logger.error(err); }
|
|
110
|
+
} catch (err) { logger.error(`Error reading log file ${logFile}: ${err.message}`); }
|
|
101
111
|
}
|
|
102
112
|
public async logData(logFile: string, data: any) {
|
|
103
113
|
try {
|
|
@@ -114,10 +124,11 @@ export class NixieControlPanel implements INixieControlPanel {
|
|
|
114
124
|
else
|
|
115
125
|
lines.unshift(data.toString());
|
|
116
126
|
fs.writeFileSync(logPath, lines.join('\n'));
|
|
117
|
-
} catch (err) { logger.error(err); }
|
|
127
|
+
} catch (err) { logger.error(`Error logging to ${logFile}: ${err.message}`); }
|
|
118
128
|
}
|
|
119
129
|
public async closeAsync() {
|
|
120
130
|
// Close all the associated equipment.
|
|
131
|
+
await this.chemDosers.closeAsync();
|
|
121
132
|
await this.chemControllers.closeAsync();
|
|
122
133
|
await this.chlorinators.closeAsync();
|
|
123
134
|
await this.heaters.closeAsync();
|
|
@@ -156,7 +167,7 @@ export class NixieControlPanel implements INixieControlPanel {
|
|
|
156
167
|
await ncp.chemControllers.syncRemoteREMFeeds(srv);
|
|
157
168
|
}
|
|
158
169
|
return srv;
|
|
159
|
-
} catch (err) { logger.error(err); }
|
|
170
|
+
} catch (err) { logger.error(`Error gettting REM Servers: ${err.message}`); }
|
|
160
171
|
}
|
|
161
172
|
}
|
|
162
173
|
|
|
@@ -86,6 +86,7 @@ export class NixieEquipmentCollection<T> extends Array<NixieEquipment> {
|
|
|
86
86
|
let eq = this[ndx];
|
|
87
87
|
await eq.closeAsync();
|
|
88
88
|
this.splice(ndx, 1);
|
|
89
|
+
logger.info(`Removing chem doser id# ${id} at index ndx`);
|
|
89
90
|
}
|
|
90
91
|
else
|
|
91
92
|
logger.warn(`A Nixie equipment item was not found with id ${id}. Equipment not removed.`);
|