nodejs-poolcontroller 7.6.1 → 8.0.0
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 +36 -45
- package/.github/ISSUE_TEMPLATE/1-bug-report.yml +84 -0
- package/.github/ISSUE_TEMPLATE/2-docs.md +12 -0
- package/.github/ISSUE_TEMPLATE/3-proposal.md +28 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/CONTRIBUTING.md +74 -74
- package/Changelog +242 -215
- package/Dockerfile +17 -17
- package/Gruntfile.js +40 -40
- package/LICENSE +661 -661
- package/README.md +195 -191
- 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 +26 -8
- package/config/VersionCheck.ts +8 -4
- package/controller/Constants.ts +59 -25
- package/controller/Equipment.ts +2667 -2459
- package/controller/Errors.ts +181 -180
- package/controller/Lockouts.ts +534 -436
- package/controller/State.ts +596 -77
- package/controller/boards/AquaLinkBoard.ts +1003 -0
- package/controller/boards/BoardFactory.ts +53 -45
- package/controller/boards/EasyTouchBoard.ts +3079 -2653
- package/controller/boards/IntelliCenterBoard.ts +3821 -4230
- package/controller/boards/IntelliComBoard.ts +69 -63
- package/controller/boards/IntelliTouchBoard.ts +384 -241
- package/controller/boards/NixieBoard.ts +1871 -1675
- package/controller/boards/SunTouchBoard.ts +393 -0
- package/controller/boards/SystemBoard.ts +5244 -4697
- package/controller/comms/Comms.ts +905 -541
- package/controller/comms/ScreenLogic.ts +1663 -0
- package/controller/comms/messages/Messages.ts +382 -54
- package/controller/comms/messages/config/ChlorinatorMessage.ts +8 -4
- package/controller/comms/messages/config/CircuitGroupMessage.ts +5 -2
- package/controller/comms/messages/config/CircuitMessage.ts +82 -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 +31 -30
- 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 +145 -11
- package/controller/comms/messages/config/IntellichemMessage.ts +2 -1
- package/controller/comms/messages/config/OptionsMessage.ts +16 -27
- package/controller/comms/messages/config/PumpMessage.ts +62 -47
- package/controller/comms/messages/config/RemoteMessage.ts +80 -13
- package/controller/comms/messages/config/ScheduleMessage.ts +390 -347
- package/controller/comms/messages/config/SecurityMessage.ts +2 -1
- package/controller/comms/messages/config/ValveMessage.ts +44 -27
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +44 -91
- package/controller/comms/messages/status/EquipmentStateMessage.ts +139 -30
- package/controller/comms/messages/status/HeaterStateMessage.ts +135 -86
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +448 -445
- package/controller/comms/messages/status/IntelliValveStateMessage.ts +36 -35
- package/controller/comms/messages/status/PumpStateMessage.ts +92 -2
- package/controller/comms/messages/status/VersionMessage.ts +2 -1
- package/controller/nixie/Nixie.ts +173 -162
- package/controller/nixie/NixieEquipment.ts +104 -103
- package/controller/nixie/bodies/Body.ts +120 -120
- package/controller/nixie/bodies/Filter.ts +135 -135
- package/controller/nixie/chemistry/ChemController.ts +2682 -2498
- package/controller/nixie/chemistry/ChemDoser.ts +806 -0
- package/controller/nixie/chemistry/Chlorinator.ts +367 -314
- package/controller/nixie/circuits/Circuit.ts +402 -248
- package/controller/nixie/heaters/Heater.ts +815 -649
- package/controller/nixie/pumps/Pump.ts +934 -661
- package/controller/nixie/schedules/Schedule.ts +319 -257
- package/controller/nixie/valves/Valve.ts +170 -170
- package/defaultConfig.json +346 -286
- package/logger/DataLogger.ts +448 -448
- package/logger/Logger.ts +38 -9
- package/package.json +60 -56
- package/tsconfig.json +25 -25
- package/web/Server.ts +275 -117
- package/web/bindings/aqualinkD.json +560 -0
- package/web/bindings/homeassistant.json +437 -0
- package/web/bindings/influxDB.json +1066 -1021
- package/web/bindings/mqtt.json +721 -654
- package/web/bindings/mqttAlt.json +746 -684
- package/web/bindings/rulesManager.json +54 -54
- package/web/bindings/smartThings-Hubitat.json +31 -31
- package/web/bindings/valveRelays.json +20 -20
- package/web/bindings/vera.json +25 -25
- package/web/interfaces/baseInterface.ts +188 -136
- package/web/interfaces/httpInterface.ts +148 -124
- package/web/interfaces/influxInterface.ts +283 -245
- package/web/interfaces/mqttInterface.ts +695 -475
- package/web/interfaces/ruleInterface.ts +87 -0
- package/web/services/config/Config.ts +177 -49
- package/web/services/config/ConfigSocket.ts +2 -1
- package/web/services/state/State.ts +154 -3
- package/web/services/state/StateSocket.ts +69 -18
- package/web/services/utilities/Utilities.ts +232 -42
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -52
- package/config copy.json +0 -300
- package/issue_template.md +0 -52
|
@@ -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
|
|
@@ -28,11 +29,12 @@ export class ChlorinatorMessage {
|
|
|
28
29
|
for (let i = 0; i < 4 && i + 30 < msg.payload.length; i++) {
|
|
29
30
|
let isActive = msg.extractPayloadByte(i + 22) === 1;
|
|
30
31
|
chlor = sys.chlorinators.getItemById(chlorId);
|
|
31
|
-
if (chlor.master
|
|
32
|
+
if (chlor.master !== 0) continue; // RSG: probably never need this. See Touch chlor below.
|
|
32
33
|
if (isActive) {
|
|
33
34
|
chlor = sys.chlorinators.getItemById(chlorId, true);
|
|
34
35
|
let schlor = state.chlorinators.getItemById(chlor.id, true);
|
|
35
36
|
chlor.isActive = schlor.isActive = true;
|
|
37
|
+
chlor.master = 0;
|
|
36
38
|
chlor.body = msg.extractPayloadByte(i + 2);
|
|
37
39
|
chlor.type = msg.extractPayloadByte(i + 6);
|
|
38
40
|
if (!chlor.disabled && !chlor.isDosing) {
|
|
@@ -51,6 +53,7 @@ export class ChlorinatorMessage {
|
|
|
51
53
|
schlor.poolSetpoint = chlor.poolSetpoint;
|
|
52
54
|
schlor.spaSetpoint = chlor.spaSetpoint;
|
|
53
55
|
schlor.type = chlor.type;
|
|
56
|
+
schlor.model = chlor.model;
|
|
54
57
|
schlor.isActive = chlor.isActive;
|
|
55
58
|
schlor.superChlorHours = chlor.superChlorHours;
|
|
56
59
|
state.emitEquipmentChanges();
|
|
@@ -69,9 +72,10 @@ export class ChlorinatorMessage {
|
|
|
69
72
|
}
|
|
70
73
|
}
|
|
71
74
|
public static processTouch(msg: Inbound) {
|
|
75
|
+
//[255, 0, 255][165, 1, 15, 16, 25, 22][1, 90, 128, 58, 128, 0, 73, 110, 116, 101, 108, 108, 105, 99, 104, 108, 111, 114, 45, 45, 54, 48][8, 50]
|
|
72
76
|
// This is for the 25 message that is broadcast from the OCP.
|
|
73
77
|
let chlor = sys.chlorinators.getItemById(1);
|
|
74
|
-
if (chlor.master
|
|
78
|
+
if (chlor.master !== 0 && typeof chlor.master !== 'undefined') return; // Some Aquarite chlors need more frequent control (via Nixie) but will be disabled via Touch. https://github.com/tagyoureit/nodejs-poolController/issues/349
|
|
75
79
|
let isActive = (msg.extractPayloadByte(0) & 0x01) === 1;
|
|
76
80
|
if (isActive) {
|
|
77
81
|
let chlor = sys.chlorinators.getItemById(1, true);
|
|
@@ -82,7 +86,7 @@ export class ChlorinatorMessage {
|
|
|
82
86
|
// chlorinator. These should be 0 anyway.
|
|
83
87
|
schlor.spaSetpoint = chlor.spaSetpoint = msg.extractPayloadByte(0) >> 1;
|
|
84
88
|
schlor.poolSetpoint = chlor.poolSetpoint = msg.extractPayloadByte(1);
|
|
85
|
-
chlor.address =
|
|
89
|
+
chlor.address = msg.dest;
|
|
86
90
|
schlor.body = chlor.body = sys.equipment.maxBodies >= 1 || sys.equipment.shared === true ? 32 : 0;
|
|
87
91
|
}
|
|
88
92
|
if (typeof chlor.name === 'undefined') schlor.name = chlor.name = msg.extractPayloadString(6, 16);
|
|
@@ -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
|
|
@@ -113,7 +114,8 @@ export class CircuitGroupMessage {
|
|
|
113
114
|
group.nameId = sgroup.nameId = feature.nameId;
|
|
114
115
|
group.type = sgroup.type = sys.board.valueMaps.circuitGroupTypes.getValue('circuit');
|
|
115
116
|
group.isActive = _isActive;
|
|
116
|
-
if (typeof group.showInFeatures === 'undefined')
|
|
117
|
+
if (typeof group.showInFeatures === 'undefined') group.showInFeatures = true;
|
|
118
|
+
sgroup.showInFeatures = group.showInFeatures;
|
|
117
119
|
let circuits: CircuitGroupCircuitCollection = group.circuits;
|
|
118
120
|
for (let byte = 1; byte <= 7; byte++){
|
|
119
121
|
let offByte = msg.extractPayloadByte(byte);
|
|
@@ -189,6 +191,7 @@ export class CircuitGroupMessage {
|
|
|
189
191
|
group.isActive = sgroup.isActive = true;
|
|
190
192
|
if (typeof group.showInFeatures === 'undefined') group.showInFeatures = true;
|
|
191
193
|
sgroup.type = group.type;
|
|
194
|
+
sgroup.showInFeatures = group.showInFeatures;
|
|
192
195
|
}
|
|
193
196
|
state.emitEquipmentChanges();
|
|
194
197
|
msg.isProcessed = true;
|
|
@@ -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
|
|
@@ -18,12 +19,13 @@ import { Inbound } from "../Messages";
|
|
|
18
19
|
import { sys, Body, Circuit, ICircuit } from "../../../Equipment";
|
|
19
20
|
import { state, BodyTempState } from "../../../State";
|
|
20
21
|
import { logger } from "../../../../logger/Logger";
|
|
22
|
+
import { ControllerType } from "../../../Constants";
|
|
21
23
|
|
|
22
24
|
export class CircuitMessage {
|
|
23
25
|
public static processTouch(msg: Inbound): void {
|
|
24
26
|
switch (msg.action) {
|
|
25
27
|
case 11: // IntelliTouch Circuits
|
|
26
|
-
CircuitMessage.processCircuitAttributes(msg);
|
|
28
|
+
sys.controllerType === ControllerType.SunTouch ? CircuitMessage.processSunTouchCircuit(msg) : CircuitMessage.processCircuitAttributes(msg);
|
|
27
29
|
break;
|
|
28
30
|
case 39: // IntelliTouch Light Groups
|
|
29
31
|
case 167:
|
|
@@ -153,7 +155,13 @@ export class CircuitMessage {
|
|
|
153
155
|
let circuit: Circuit = sys.circuits.getItemById(circuitId++, true);
|
|
154
156
|
|
|
155
157
|
// For some odd reason the circuit type for circuit 6 does not equal pool while circuit 1 does equal spa.
|
|
156
|
-
|
|
158
|
+
// Apparently in later versions, spa does not do this either
|
|
159
|
+
if (circuit.id === 1)
|
|
160
|
+
circuit.type = 13
|
|
161
|
+
else if (circuit.id == 6)
|
|
162
|
+
circuit.type = 12
|
|
163
|
+
else
|
|
164
|
+
circuit.type = msg.extractPayloadByte(i);
|
|
157
165
|
circuit.isActive = true;
|
|
158
166
|
circuit.master = 0;
|
|
159
167
|
}
|
|
@@ -175,7 +183,8 @@ export class CircuitMessage {
|
|
|
175
183
|
let maxCircuitId = sys.board.equipmentIds.circuits.end;
|
|
176
184
|
for (let i = circuitId + 1; i < msg.payload.length && circuitId <= maxCircuitId; i++) {
|
|
177
185
|
let circuit: Circuit = sys.circuits.getItemById(circuitId++, true);
|
|
178
|
-
|
|
186
|
+
let cstate = state.circuits.getItemById(circuit.id, true);
|
|
187
|
+
cstate.showInFeatures = circuit.showInFeatures = msg.extractPayloadByte(i) > 0;
|
|
179
188
|
}
|
|
180
189
|
msg.isProcessed = true;
|
|
181
190
|
}
|
|
@@ -230,7 +239,49 @@ export class CircuitMessage {
|
|
|
230
239
|
}
|
|
231
240
|
msg.isProcessed = true;
|
|
232
241
|
}
|
|
233
|
-
|
|
242
|
+
// SunTouch
|
|
243
|
+
private static processSunTouchCircuit(msg: Inbound) {
|
|
244
|
+
let id = msg.extractPayloadByte(0);
|
|
245
|
+
// We need to remap the SunTouch circuits because the features start with 5.
|
|
246
|
+
// SunTouch bit mapping for circuits and features
|
|
247
|
+
// Bit Mask Circuit/Feature id msg
|
|
248
|
+
// 1 = 0x01 Spa 1 1
|
|
249
|
+
// 2 = 0x02 Aux 1 2 2
|
|
250
|
+
// 3 = 0x04 Aux 2 3 3
|
|
251
|
+
// 4 = 0x08 Aux 3 4 4
|
|
252
|
+
// 5 = 0x10 Feature 1 7 5
|
|
253
|
+
// 6 = 0x20 Pool 6 6
|
|
254
|
+
// 7 = 0x40 Feature 2 8 7
|
|
255
|
+
// 8 = 0x80 Feature 3 9 8
|
|
256
|
+
// 9 = 0x01 Feature 4 10 9
|
|
257
|
+
if ([5, 7, 8, 9].includes(id)) {
|
|
258
|
+
id = id === 5 ? 7 : id + 1;
|
|
259
|
+
let feat = sys.features.getItemById(id, true);
|
|
260
|
+
let fstate = state.features.getItemById(id, true);
|
|
261
|
+
fstate.isActive = feat.isActive = true;
|
|
262
|
+
feat.master = 0;
|
|
263
|
+
fstate.nameId = feat.nameId = msg.extractPayloadByte(2);
|
|
264
|
+
fstate.type = feat.type = msg.extractPayloadByte(1) & 63;
|
|
265
|
+
feat.freeze = (msg.extractPayloadByte(1) & 64) > 0;
|
|
266
|
+
feat.showInFeatures = fstate.showInFeatures = typeof feat.showInFeatures === 'undefined' ? true : feat.showInFeatures;
|
|
267
|
+
if (typeof feat.eggTimer === 'undefined' || feat.eggTimer === 0) feat.eggTimer = 720;
|
|
268
|
+
if (typeof feat.dontStop === 'undefined') feat.dontStop = feat.eggTimer === 1620;
|
|
269
|
+
if (typeof feat.name === 'undefined') feat.name = fstate.name = sys.board.valueMaps.circuitNames.transform(feat.nameId).desc;
|
|
270
|
+
}
|
|
271
|
+
else if ([1, 2, 3, 4, 6].includes(id)) {
|
|
272
|
+
let circ = sys.circuits.getItemById(id, true);
|
|
273
|
+
let cstate = state.circuits.getItemById(id, true);
|
|
274
|
+
cstate.isActive = circ.isActive = true;
|
|
275
|
+
circ.master = 0;
|
|
276
|
+
cstate.nameId = circ.nameId = msg.extractPayloadByte(2);
|
|
277
|
+
cstate.type = circ.type = msg.extractPayloadByte(1) & 63;
|
|
278
|
+
circ.freeze = (msg.extractPayloadByte(1) & 64) > 0;
|
|
279
|
+
circ.showInFeatures = cstate.showInFeatures = typeof circ.showInFeatures === 'undefined' ? true : circ.showInFeatures;
|
|
280
|
+
if (typeof circ.eggTimer === 'undefined' || circ.eggTimer === 0) circ.eggTimer = 720;
|
|
281
|
+
if (typeof circ.dontStop === 'undefined') circ.dontStop = circ.eggTimer === 1620;
|
|
282
|
+
if (typeof circ.name === 'undefined') circ.name = cstate.name = sys.board.valueMaps.circuitNames.transform(circ.nameId).desc;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
234
285
|
// Intellitouch
|
|
235
286
|
private static processCircuitAttributes(msg: Inbound) {
|
|
236
287
|
// Sample packet
|
|
@@ -238,11 +289,12 @@ export class CircuitMessage {
|
|
|
238
289
|
const id = msg.extractPayloadByte(0);
|
|
239
290
|
const functionId = msg.extractPayloadByte(1);
|
|
240
291
|
const nameId = msg.extractPayloadByte(2);
|
|
241
|
-
let _isActive = functionId !== sys.board.valueMaps.circuitFunctions.getValue('notused') && nameId !== 0;
|
|
292
|
+
let _isActive = functionId !== sys.board.valueMaps.circuitFunctions.getValue('notused') && (nameId !== 0 || sys.controllerType === ControllerType.SunTouch);
|
|
242
293
|
if (!sys.board.equipmentIds.invalidIds.isValidId(id)) { _isActive = false; }
|
|
243
294
|
if (_isActive) {
|
|
244
295
|
const type = functionId & 63;
|
|
245
296
|
let circuit: ICircuit = sys.circuits.getInterfaceById(id, _isActive);
|
|
297
|
+
circuit.master = 0;
|
|
246
298
|
circuit.name = sys.board.circuits.getNameById(nameId);
|
|
247
299
|
circuit.nameId = nameId;
|
|
248
300
|
circuit.type = type;
|
|
@@ -271,14 +323,14 @@ export class CircuitMessage {
|
|
|
271
323
|
case 6: // pool
|
|
272
324
|
body = sys.bodies.getItemById(1, sys.equipment.maxBodies > 0);
|
|
273
325
|
sbody = state.temps.bodies.getItemById(1, sys.equipment.maxBodies > 0);
|
|
274
|
-
sbody.name = body.name = "Pool";
|
|
326
|
+
if (typeof body.name === 'undefined') sbody.name = body.name = "Pool";
|
|
275
327
|
sbody.type = body.type = 0; // RKS: The body types were backwards here but correct everywhere else e.g. PumpMessage.
|
|
276
328
|
circuit.type === 2 ? body.isActive = true : body.isActive = false;
|
|
277
329
|
break;
|
|
278
330
|
case 1: // spa
|
|
279
331
|
body = sys.bodies.getItemById(2, sys.equipment.maxBodies > 1);
|
|
280
|
-
sbody = state.temps.bodies.getItemById(
|
|
281
|
-
sbody.name = body.name = "Spa";
|
|
332
|
+
sbody = state.temps.bodies.getItemById(2, sys.equipment.maxBodies > 1);
|
|
333
|
+
if(typeof body.name === 'undefined') sbody.name = body.name = "Spa";
|
|
282
334
|
sbody.type = body.type = 1;
|
|
283
335
|
// process bodies - there might be a better place to do this but without other comparison packets from pools with expansion packs it is hard to determine
|
|
284
336
|
// also, if we get this far spa should always be active. not sure if would ever not be active if we are here.
|
|
@@ -302,11 +354,28 @@ export class CircuitMessage {
|
|
|
302
354
|
sys.lightGroups.removeItemById(sys.board.equipmentIds.circuitGroups.start);
|
|
303
355
|
state.lightGroups.removeItemById(sys.board.equipmentIds.circuitGroups.start);
|
|
304
356
|
}
|
|
305
|
-
sys.
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
357
|
+
if (!sys.board.equipmentIds.circuits.isInRange(id)) {
|
|
358
|
+
sys.circuits.removeItemById(id);
|
|
359
|
+
state.circuits.removeItemById(id);
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
let circuit = sys.circuits.getItemById(id, true);
|
|
363
|
+
let cstate = sys.circuits.getItemById(id, true);
|
|
364
|
+
cstate.showInFeatures = circuit.showInFeatures = false;
|
|
365
|
+
cstate.type = circuit.type = functionId & 63;
|
|
366
|
+
cstate.name = circuit.name = sys.board.circuits.getNameById(nameId || id);
|
|
367
|
+
cstate.nameId = circuit.nameId = nameId || id;
|
|
368
|
+
cstate.isActive = circuit.isActive = true;
|
|
369
|
+
}
|
|
370
|
+
if (!sys.board.equipmentIds.features.isInRange(id)) {
|
|
371
|
+
sys.features.removeItemById(id);
|
|
372
|
+
state.features.removeItemById(id);
|
|
373
|
+
}
|
|
309
374
|
sys.circuitGroups.removeItemById(id);
|
|
375
|
+
//sys.features.removeItemById(id);
|
|
376
|
+
//state.features.removeItemById(id);
|
|
377
|
+
//sys.circuits.removeItemById(id);
|
|
378
|
+
//state.circuits.removeItemById(id);
|
|
310
379
|
}
|
|
311
380
|
msg.isProcessed = true;
|
|
312
381
|
}
|
|
@@ -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
|
|
@@ -103,6 +104,7 @@ export class ConfigMessage {
|
|
|
103
104
|
}
|
|
104
105
|
break;
|
|
105
106
|
case ControllerType.EasyTouch:
|
|
107
|
+
case ControllerType.SunTouch:
|
|
106
108
|
case ControllerType.IntelliCom:
|
|
107
109
|
case ControllerType.IntelliTouch:
|
|
108
110
|
// switch (msg.action) { }
|
|
@@ -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
|
|
@@ -1,31 +1,32 @@
|
|
|
1
|
-
/* nodejs-poolController. An application to control pool equipment.
|
|
2
|
-
Copyright (C) 2016, 2017, 2018, 2019, 2020
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
let
|
|
25
|
-
customName
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
sys.
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
/* nodejs-poolController. An application to control pool equipment.
|
|
2
|
+
Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021, 2022.
|
|
3
|
+
Russell Goldin, tagyoureit. russ.goldin@gmail.com
|
|
4
|
+
|
|
5
|
+
This program is free software: you can redistribute it and/or modify
|
|
6
|
+
it under the terms of the GNU Affero General Public License as
|
|
7
|
+
published by the Free Software Foundation, either version 3 of the
|
|
8
|
+
License, or (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU Affero General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
*/
|
|
18
|
+
import { Inbound } from "../Messages";
|
|
19
|
+
import { sys } from "../../../Equipment";
|
|
20
|
+
export class CustomNameMessage
|
|
21
|
+
{
|
|
22
|
+
public static process ( msg: Inbound ): void
|
|
23
|
+
{
|
|
24
|
+
let customNameId = msg.extractPayloadByte( 0 );
|
|
25
|
+
let customName = sys.customNames.getItemById( customNameId, customNameId <= sys.equipment.maxCustomNames );
|
|
26
|
+
customName.name = msg.extractPayloadString( 1, 11 );
|
|
27
|
+
// customName.isActive = customNameId <= sys.equipment.maxCustomNames && !customName.name.includes('USERNAME-')
|
|
28
|
+
if (customNameId >= sys.equipment.maxCustomNames) sys.equipment.maxCustomNames = customNameId + 1;
|
|
29
|
+
sys.board.system.syncCustomNamesValueMap();
|
|
30
|
+
msg.isProcessed = true;
|
|
31
|
+
}
|
|
31
32
|
}
|
|
@@ -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
|
|
@@ -131,7 +132,9 @@ export class EquipmentMessage {
|
|
|
131
132
|
sys.bodies.removeItemById(bodyId);
|
|
132
133
|
state.temps.bodies.removeItemById(bodyId);
|
|
133
134
|
}
|
|
135
|
+
state.equipment.single = sys.equipment.single = sys.equipment.shared == false && sys.equipment.dual === false;
|
|
134
136
|
state.equipment.shared = sys.equipment.shared;
|
|
137
|
+
state.equipment.dual = sys.equipment.dual;
|
|
135
138
|
state.equipment.model = sys.equipment.model;
|
|
136
139
|
state.equipment.controllerType = sys.controllerType;
|
|
137
140
|
state.equipment.maxBodies = sys.equipment.maxBodies;
|
|
@@ -149,6 +152,7 @@ export class EquipmentMessage {
|
|
|
149
152
|
case ControllerType.IntelliCom:
|
|
150
153
|
case ControllerType.EasyTouch:
|
|
151
154
|
case ControllerType.IntelliTouch:
|
|
155
|
+
case ControllerType.SunTouch:
|
|
152
156
|
switch (msg.action) {
|
|
153
157
|
case 252:
|
|
154
158
|
EquipmentMessage.processSoftwareVersion(msg);
|
|
@@ -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
|
|
@@ -16,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
16
17
|
*/
|
|
17
18
|
import { Inbound } from "../Messages";
|
|
18
19
|
import { sys, Body, ICircuitGroup, LightGroup, CircuitGroup } from "../../../Equipment";
|
|
19
|
-
import { state, ICircuitGroupState, LightGroupState } from "../../../State";
|
|
20
|
+
import { state, ICircuitGroupState, LightGroupState, CircuitGroupState } from "../../../State";
|
|
20
21
|
import { Timestamp, utils } from "../../../Constants";
|
|
21
22
|
import { logger } from "../../../../logger/Logger";
|
|
22
23
|
export class ExternalMessage {
|
|
@@ -208,6 +209,7 @@ export class ExternalMessage {
|
|
|
208
209
|
sgroup = state.circuitGroups.getItemById(groupId, true);
|
|
209
210
|
sgroup.type = group.type = type;
|
|
210
211
|
if (typeof group.showInFeatures === 'undefined') group.showInFeatures = sgroup.showInFeatures = true;
|
|
212
|
+
sgroup.showInFeatures = group.showInFeatures;
|
|
211
213
|
sys.lightGroups.removeItemById(groupId);
|
|
212
214
|
state.lightGroups.removeItemById(groupId);
|
|
213
215
|
sgroup.isActive = group.isActive = true;
|
|
@@ -274,6 +276,8 @@ export class ExternalMessage {
|
|
|
274
276
|
private static processHeater(msg: Inbound) {
|
|
275
277
|
// So a user is changing the heater info. Lets
|
|
276
278
|
// hijack it and get it ourselves.
|
|
279
|
+
// Installing hybrid heater.
|
|
280
|
+
//[165, 63, 15, 16, 168, 30][10, 0, 2, 5, 32, 5, 6, 3, 0, 6, 112, 72, 121, 98, 114, 105, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1][4, 230]
|
|
277
281
|
let isActive = msg.extractPayloadByte(3) !== 0;
|
|
278
282
|
let heaterId = msg.extractPayloadByte(2) + 1;
|
|
279
283
|
if (isActive) {
|
|
@@ -406,6 +410,7 @@ export class ExternalMessage {
|
|
|
406
410
|
for (let j = 0; j < 8; j++) {
|
|
407
411
|
let group = sys.circuitGroups.getInterfaceById(groupId);
|
|
408
412
|
let gstate = group.type === 1 ? state.lightGroups.getItemById(groupId, group.isActive) : state.circuitGroups.getItemById(groupId, group.isActive);
|
|
413
|
+
|
|
409
414
|
if (group.isActive !== false) {
|
|
410
415
|
let isOn = ((byte & (1 << (j))) >> j) > 0;
|
|
411
416
|
sys.board.circuits.setEndTime(group, gstate, isOn);
|
|
@@ -442,6 +447,9 @@ export class ExternalMessage {
|
|
|
442
447
|
break;
|
|
443
448
|
}
|
|
444
449
|
}
|
|
450
|
+
else if(gstate.dataName === 'circuitGroup') {
|
|
451
|
+
(gstate as CircuitGroupState).showInFeatures = group.showInFeatures;
|
|
452
|
+
}
|
|
445
453
|
}
|
|
446
454
|
else {
|
|
447
455
|
state.circuitGroups.removeItemById(groupId);
|
|
@@ -850,7 +858,7 @@ export class ExternalMessage {
|
|
|
850
858
|
// chlorinator. These should be 0 anyway.
|
|
851
859
|
schlor.poolSetpoint = chlor.spaSetpoint = msg.extractPayloadByte(0) >> 1;
|
|
852
860
|
schlor.spaSetpoint = chlor.poolSetpoint = msg.extractPayloadByte(1);
|
|
853
|
-
chlor.address = chlor.id + 79;
|
|
861
|
+
if (typeof chlor.address === 'undefined') chlor.address = 80; // chlor.id + 79;
|
|
854
862
|
schlor.body = chlor.body = sys.equipment.maxBodies >= 1 || sys.equipment.shared === true ? 32 : 0;
|
|
855
863
|
}
|
|
856
864
|
schlor.superChlor = chlor.superChlor = msg.extractPayloadByte(2) - 128 > 0;
|
|
@@ -868,4 +876,26 @@ export class ExternalMessage {
|
|
|
868
876
|
state.chlorinators.removeItemById(1);
|
|
869
877
|
}
|
|
870
878
|
}
|
|
879
|
+
public static processTouchSetHeatMode(msg: Inbound) {
|
|
880
|
+
// We get here because some other controller is setting the heat
|
|
881
|
+
// mode. The OCP will emit an 8 later but it can be very slow
|
|
882
|
+
// in doing this. ScreenLogic also captures this message so it
|
|
883
|
+
// doesn't get behind.
|
|
884
|
+
//[165, 1, 16, 34, 136, 4][86, 100, 3, 0][2, 33]
|
|
885
|
+
//payload: [temp1, temp2, mode2 << 2 | mode1, setPoint],
|
|
886
|
+
let bstate1 = state.temps.bodies.getItemById(1);
|
|
887
|
+
let bstate2 = state.temps.bodies.getItemById(2);
|
|
888
|
+
let body1 = sys.bodies.getItemById(1);
|
|
889
|
+
let body2 = sys.bodies.getItemById(2);
|
|
890
|
+
let mode1 = msg.extractPayloadByte(2) & 0x03;
|
|
891
|
+
let mode2 = (msg.extractPayloadByte(2) & 0x0C) >> 2;
|
|
892
|
+
bstate1.setPoint = body1.heatSetpoint = msg.extractPayloadByte(0);
|
|
893
|
+
bstate1.coolSetpoint = body1.coolSetpoint = msg.extractPayloadByte(3);
|
|
894
|
+
bstate2.setPoint = body2.heatSetpoint = msg.extractPayloadByte(1);
|
|
895
|
+
bstate1.heatMode = body1.heatMode = mode1;
|
|
896
|
+
bstate2.heatMode = body2.heatMode = mode2;
|
|
897
|
+
msg.isProcessed = true;
|
|
898
|
+
state.emitEquipmentChanges();
|
|
899
|
+
|
|
900
|
+
}
|
|
871
901
|
}
|
|
@@ -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
|
|
@@ -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
|