nodejs-poolcontroller 7.4.0 → 7.5.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/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/Changelog +3 -0
- package/README.md +2 -2
- package/app.ts +2 -0
- package/config/Config.ts +3 -0
- package/config/VersionCheck.ts +8 -4
- package/controller/Equipment.ts +89 -29
- package/controller/Errors.ts +14 -1
- package/controller/State.ts +75 -31
- package/controller/boards/EasyTouchBoard.ts +81 -36
- package/controller/boards/IntelliCenterBoard.ts +96 -32
- package/controller/boards/IntelliTouchBoard.ts +103 -29
- package/controller/boards/NixieBoard.ts +79 -27
- package/controller/boards/SystemBoard.ts +1552 -822
- package/controller/comms/Comms.ts +84 -9
- package/controller/comms/messages/Messages.ts +10 -4
- package/controller/comms/messages/config/ChlorinatorMessage.ts +13 -4
- package/controller/comms/messages/config/CircuitGroupMessage.ts +6 -0
- package/controller/comms/messages/config/CoverMessage.ts +1 -0
- package/controller/comms/messages/config/EquipmentMessage.ts +4 -0
- package/controller/comms/messages/config/ExternalMessage.ts +43 -25
- package/controller/comms/messages/config/FeatureMessage.ts +8 -1
- package/controller/comms/messages/config/GeneralMessage.ts +8 -0
- package/controller/comms/messages/config/HeaterMessage.ts +10 -9
- package/controller/comms/messages/config/IntellichemMessage.ts +4 -1
- package/controller/comms/messages/config/OptionsMessage.ts +13 -1
- package/controller/comms/messages/config/PumpMessage.ts +4 -20
- package/controller/comms/messages/config/RemoteMessage.ts +4 -0
- package/controller/comms/messages/config/ScheduleMessage.ts +11 -0
- package/controller/comms/messages/config/SecurityMessage.ts +1 -0
- package/controller/comms/messages/config/ValveMessage.ts +12 -2
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +2 -3
- package/controller/comms/messages/status/EquipmentStateMessage.ts +74 -22
- package/controller/comms/messages/status/HeaterStateMessage.ts +15 -6
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +37 -26
- package/controller/nixie/Nixie.ts +18 -16
- package/controller/nixie/chemistry/ChemController.ts +57 -37
- package/controller/nixie/chemistry/Chlorinator.ts +7 -8
- package/controller/nixie/circuits/Circuit.ts +17 -0
- package/controller/nixie/pumps/Pump.ts +49 -24
- package/controller/nixie/schedules/Schedule.ts +1 -1
- package/defaultConfig.json +15 -0
- package/issue_template.md +1 -1
- package/logger/DataLogger.ts +37 -22
- package/package.json +3 -1
- package/web/Server.ts +515 -27
- package/web/bindings/influxDB.json +35 -0
- package/web/bindings/mqtt.json +62 -3
- package/web/bindings/mqttAlt.json +57 -4
- package/web/interfaces/httpInterface.ts +2 -0
- package/web/interfaces/influxInterface.ts +3 -2
- package/web/interfaces/mqttInterface.ts +12 -1
- package/web/services/config/Config.ts +162 -37
- package/web/services/state/State.ts +47 -3
- package/web/services/state/StateSocket.ts +1 -1
|
@@ -219,13 +219,7 @@ export class HeaterMessage {
|
|
|
219
219
|
}
|
|
220
220
|
sys.board.heaters.syncHeaterStates();
|
|
221
221
|
sys.equipment.setEquipmentIds();
|
|
222
|
-
|
|
223
|
-
case 114:
|
|
224
|
-
// something to do with heat pumps... need equipment or other packets to decipher
|
|
225
|
-
// [ 255, 0, 255], [165, 0, 112, 16, 114, 10], [144, 2, 0, 0, 0, 0, 0, 0, 0, 0], [2, 51 ]heat + cool
|
|
226
|
-
// [165,0,112,16,114,10][144,0,0,0,0,0,0,0,0,0][2,49] == no Heater, no cool
|
|
227
|
-
// [165,0,112,16,114,10][144,2,0,0,0,0,0,0,0,0][2,51] == no heat, cooling
|
|
228
|
-
// this might be heatStatus not heatMode?
|
|
222
|
+
msg.isProcessed = true;
|
|
229
223
|
break;
|
|
230
224
|
case 168:
|
|
231
225
|
{
|
|
@@ -245,7 +239,7 @@ export class HeaterMessage {
|
|
|
245
239
|
}
|
|
246
240
|
// Spa Manual Heat on/off
|
|
247
241
|
sys.general.options.manualHeat = msg.extractPayloadByte(4) === 1 ? true : false;
|
|
248
|
-
|
|
242
|
+
msg.isProcessed = true;
|
|
249
243
|
}
|
|
250
244
|
}
|
|
251
245
|
}
|
|
@@ -265,6 +259,7 @@ export class HeaterMessage {
|
|
|
265
259
|
})();
|
|
266
260
|
}
|
|
267
261
|
}
|
|
262
|
+
msg.isProcessed = true;
|
|
268
263
|
}
|
|
269
264
|
|
|
270
265
|
//private static processBody(msg: Inbound) {
|
|
@@ -305,12 +300,14 @@ export class HeaterMessage {
|
|
|
305
300
|
|
|
306
301
|
}
|
|
307
302
|
sys.board.heaters.updateHeaterServices();
|
|
303
|
+
msg.isProcessed = true;
|
|
308
304
|
}
|
|
309
305
|
private static processMaxBoostTemp(msg: Inbound) {
|
|
310
306
|
for (let i = 0; i < msg.payload.length - 1 && i < sys.equipment.maxHeaters; i++) {
|
|
311
307
|
var heater: Heater = sys.heaters.getItemById(i + 1);
|
|
312
308
|
heater.maxBoostTemp = msg.extractPayloadByte(i + 2);
|
|
313
309
|
}
|
|
310
|
+
msg.isProcessed = true;
|
|
314
311
|
}
|
|
315
312
|
private static processStartStopDelta(msg: Inbound) {
|
|
316
313
|
for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxHeaters; i++) {
|
|
@@ -318,6 +315,7 @@ export class HeaterMessage {
|
|
|
318
315
|
heater.startTempDelta = msg.extractPayloadByte(i + 1);
|
|
319
316
|
heater.stopTempDelta = msg.extractPayloadByte(i + 18);
|
|
320
317
|
}
|
|
318
|
+
msg.isProcessed = true;
|
|
321
319
|
}
|
|
322
320
|
private static processCoolingSetTemp(msg: Inbound) {
|
|
323
321
|
for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxHeaters; i++) {
|
|
@@ -325,20 +323,22 @@ export class HeaterMessage {
|
|
|
325
323
|
heater.coolingEnabled = msg.extractPayloadByte(i + 1) > 0;
|
|
326
324
|
heater.differentialTemp = msg.extractPayloadByte(i + 18);
|
|
327
325
|
}
|
|
326
|
+
msg.isProcessed = true;
|
|
328
327
|
}
|
|
329
328
|
private static processAddress(msg: Inbound) {
|
|
330
329
|
for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxHeaters; i++) {
|
|
331
330
|
var heater: Heater = sys.heaters.getItemById(i);
|
|
332
331
|
heater.address = msg.extractPayloadByte(i + 1);
|
|
333
332
|
}
|
|
333
|
+
msg.isProcessed = true;
|
|
334
334
|
}
|
|
335
335
|
private static processEfficiencyMode(msg: Inbound) {
|
|
336
336
|
for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxHeaters; i++) {
|
|
337
337
|
var heater: Heater = sys.heaters.getItemById(i);
|
|
338
338
|
heater.efficiencyMode = msg.extractPayloadByte(i + 1);
|
|
339
339
|
}
|
|
340
|
+
msg.isProcessed = true;
|
|
340
341
|
}
|
|
341
|
-
|
|
342
342
|
private static processHeaterNames(msg: Inbound) {
|
|
343
343
|
var heaterId = ((msg.extractPayloadByte(1) - 5) * 2) + 1;
|
|
344
344
|
if (heaterId <= sys.equipment.maxHeaters) {
|
|
@@ -349,5 +349,6 @@ export class HeaterMessage {
|
|
|
349
349
|
let hstate = state.heaters.getItemById(heaterId);
|
|
350
350
|
hstate.name = sys.heaters.getItemById(heaterId++).name = msg.extractPayloadString(18, 16);
|
|
351
351
|
}
|
|
352
|
+
msg.isProcessed = true;
|
|
352
353
|
}
|
|
353
354
|
}
|
|
@@ -138,7 +138,8 @@ export class IntellichemMessage {
|
|
|
138
138
|
let controller = sys.chemControllers.getItemById(id, isActive, { id: i + 1, type: 1 });
|
|
139
139
|
let scontroller = state.chemControllers.getItemById(controller.id, isActive);
|
|
140
140
|
scontroller.isActive = controller.isActive = true;
|
|
141
|
-
controller.isVirtual = false;
|
|
141
|
+
// controller.isVirtual = false;
|
|
142
|
+
controller.master = 0;
|
|
142
143
|
if (!controller.isActive) {
|
|
143
144
|
sys.chemControllers.removeItemById(controller.id);
|
|
144
145
|
state.chemControllers.removeItemById(controller.id);
|
|
@@ -163,6 +164,7 @@ export class IntellichemMessage {
|
|
|
163
164
|
}
|
|
164
165
|
}
|
|
165
166
|
}
|
|
167
|
+
msg.isProcessed = true;
|
|
166
168
|
break;
|
|
167
169
|
case 1:
|
|
168
170
|
for (let i = 0; i < 4; i++) {
|
|
@@ -175,6 +177,7 @@ export class IntellichemMessage {
|
|
|
175
177
|
controller.alkalinity = msg.extractPayloadInt((i * 2) + 26);
|
|
176
178
|
}
|
|
177
179
|
}
|
|
180
|
+
msg.isProcessed = true;
|
|
178
181
|
break;
|
|
179
182
|
}
|
|
180
183
|
}
|
|
@@ -92,9 +92,21 @@ export class OptionsMessage {
|
|
|
92
92
|
//body = sys.bodies.getItemById(4, sys.equipment.maxBodies > 3);
|
|
93
93
|
//body.heatMode = msg.extractPayloadByte(27);
|
|
94
94
|
//body.heatSetpoint = msg.extractPayloadByte(23);
|
|
95
|
+
msg.isProcessed = true;
|
|
95
96
|
break;
|
|
96
97
|
}
|
|
97
|
-
case 1: //
|
|
98
|
+
case 1: // Vacation mode
|
|
99
|
+
let yy = msg.extractPayloadByte(4) + 2000;
|
|
100
|
+
let mm = msg.extractPayloadByte(5);
|
|
101
|
+
let dd = msg.extractPayloadByte(6);
|
|
102
|
+
sys.general.options.vacation.startDate = new Date(yy, mm - 1, dd);
|
|
103
|
+
yy = msg.extractPayloadByte(7) + 2000;
|
|
104
|
+
mm = msg.extractPayloadByte(8);
|
|
105
|
+
dd = msg.extractPayloadByte(9);
|
|
106
|
+
sys.general.options.vacation.endDate = new Date(yy, mm - 1, dd);
|
|
107
|
+
sys.general.options.vacation.enabled = msg.extractPayloadByte(2) > 0;
|
|
108
|
+
sys.general.options.vacation.useTimeframe = msg.extractPayloadByte(3) > 0;
|
|
109
|
+
msg.isProcessed = true;
|
|
98
110
|
break;
|
|
99
111
|
}
|
|
100
112
|
msg.isProcessed = true;
|
|
@@ -132,8 +132,10 @@ export class PumpMessage {
|
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
|
+
msg.isProcessed = true;
|
|
135
136
|
switch (msgId) {
|
|
136
137
|
case 0:
|
|
138
|
+
msg.isProcessed = true;
|
|
137
139
|
break;
|
|
138
140
|
case 1:
|
|
139
141
|
PumpMessage.processFlowStepSize(msg);
|
|
@@ -347,38 +349,20 @@ export class PumpMessage {
|
|
|
347
349
|
circuit.circuit = _circuit;
|
|
348
350
|
circuit.flow = msg.extractPayloadByte(circuitId * 2 + 4);
|
|
349
351
|
circuit.units = 1;
|
|
350
|
-
switch (circuit.circuit) {
|
|
351
|
-
case 1:
|
|
352
|
-
{
|
|
353
|
-
let body = sys.bodies.getItemById(2, sys.equipment.maxBodies >= 2);
|
|
354
|
-
let sbody = state.temps.bodies.getItemById(2, sys.equipment.maxBodies >= 2);
|
|
355
|
-
sbody.type = body.type = 1; // spa
|
|
356
|
-
body.isActive = true;
|
|
357
|
-
break;
|
|
358
|
-
}
|
|
359
|
-
case 6:
|
|
360
|
-
{
|
|
361
|
-
let body = sys.bodies.getItemById(1, sys.equipment.maxBodies >= 1);
|
|
362
|
-
let sbody = state.temps.bodies.getItemById(1, sys.equipment.maxBodies >= 1);
|
|
363
|
-
sbody.type = body.type = 0; // pool
|
|
364
|
-
body.isActive = true;
|
|
365
|
-
body.capacity = msg.extractPayloadByte(6) * 1000;
|
|
366
|
-
break;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
352
|
}
|
|
370
353
|
else {
|
|
371
354
|
pump.circuits.removeItemById(_circuit);
|
|
372
355
|
}
|
|
373
356
|
}
|
|
374
357
|
pump.backgroundCircuit = msg.extractPayloadByte(1);
|
|
358
|
+
pump.filterSize = msg.extractPayloadByte(2) * 1000;
|
|
375
359
|
pump.turnovers = msg.extractPayloadByte(3);
|
|
360
|
+
pump.manualFilterGPM = msg.extractPayloadByte(21);
|
|
376
361
|
pump.primingSpeed = msg.extractPayloadByte(22);
|
|
377
362
|
pump.primingTime = (msg.extractPayloadByte(23) & 0xf);
|
|
378
363
|
pump.minFlow = sys.board.valueMaps.pumpTypes.get(pump.type).minFlow;
|
|
379
364
|
pump.maxFlow = sys.board.valueMaps.pumpTypes.get(pump.type).maxFlow;
|
|
380
365
|
pump.flowStepSize = sys.board.valueMaps.pumpTypes.get(pump.type).flowStepSize;
|
|
381
|
-
pump.manualFilterGPM = msg.extractPayloadByte(21);
|
|
382
366
|
pump.maxSystemTime = msg.extractPayloadByte(23) >> 4;
|
|
383
367
|
pump.maxPressureIncrease = msg.extractPayloadByte(24);
|
|
384
368
|
pump.backwashFlow = msg.extractPayloadByte(25);
|
|
@@ -93,6 +93,7 @@ export class RemoteMessage {
|
|
|
93
93
|
if (!remote.button1 && !remote.button2 && !remote.button3 && !remote.button4) remote.isActive = false;
|
|
94
94
|
else remote.isActive = true;
|
|
95
95
|
remote.name = "QuickTouch";
|
|
96
|
+
msg.isProcessed = true;
|
|
96
97
|
break;
|
|
97
98
|
}
|
|
98
99
|
case 32: // is4/is10
|
|
@@ -120,6 +121,7 @@ export class RemoteMessage {
|
|
|
120
121
|
remote.type = 1;
|
|
121
122
|
remote.name = "is4";
|
|
122
123
|
}
|
|
124
|
+
msg.isProcessed = true;
|
|
123
125
|
break;
|
|
124
126
|
}
|
|
125
127
|
case 22: // Spa Command spa side remote additional config
|
|
@@ -132,6 +134,7 @@ export class RemoteMessage {
|
|
|
132
134
|
remote.pumpId = msg.extractPayloadByte(5);
|
|
133
135
|
remote.stepSize = msg.extractPayloadByte(6);
|
|
134
136
|
remote.type = 7;
|
|
137
|
+
msg.isProcessed = true;
|
|
135
138
|
break;
|
|
136
139
|
}
|
|
137
140
|
}
|
|
@@ -187,5 +190,6 @@ export class RemoteMessage {
|
|
|
187
190
|
}
|
|
188
191
|
remote["button" + (i + 1)] = msg.extractPayloadByte(i + 2);
|
|
189
192
|
}
|
|
193
|
+
msg.isProcessed = true;
|
|
190
194
|
}
|
|
191
195
|
}
|
|
@@ -187,6 +187,7 @@ export class ScheduleMessage {
|
|
|
187
187
|
const schedule: Schedule = sys.schedules.getItemById(schedId++, false, { isActive: false });
|
|
188
188
|
if (schedule.isActive !== false) schedule.startMonth = msg.extractPayloadByte(i + 1);
|
|
189
189
|
}
|
|
190
|
+
msg.isProcessed = true;
|
|
190
191
|
}
|
|
191
192
|
private static processStartDay(msg: Inbound) {
|
|
192
193
|
let schedId = (msg.extractPayloadByte(1) - 17) * 40 + 1;
|
|
@@ -198,6 +199,7 @@ export class ScheduleMessage {
|
|
|
198
199
|
csched.startTime = schedule.startTime;
|
|
199
200
|
}
|
|
200
201
|
}
|
|
202
|
+
msg.isProcessed = true;
|
|
201
203
|
}
|
|
202
204
|
private static processStartYear(msg: Inbound) {
|
|
203
205
|
let schedId = (msg.extractPayloadByte(1) - 20) * 40 + 1;
|
|
@@ -207,6 +209,7 @@ export class ScheduleMessage {
|
|
|
207
209
|
schedule.startYear = msg.extractPayloadByte(i + 1);
|
|
208
210
|
}
|
|
209
211
|
}
|
|
212
|
+
msg.isProcessed = true;
|
|
210
213
|
}
|
|
211
214
|
private static processStartTimes(msg: Inbound) {
|
|
212
215
|
let schedId = msg.extractPayloadByte(1) * 20 + 1;
|
|
@@ -226,6 +229,7 @@ export class ScheduleMessage {
|
|
|
226
229
|
i += 2;
|
|
227
230
|
}
|
|
228
231
|
ScheduleMessage._maxSchedId = sys.schedules.getMaxId(true, 0);
|
|
232
|
+
msg.isProcessed = true;
|
|
229
233
|
}
|
|
230
234
|
private static processEndTimes(msg: Inbound) {
|
|
231
235
|
let schedId = (msg.extractPayloadByte(1) - 23) * 20 + 1;
|
|
@@ -239,6 +243,7 @@ export class ScheduleMessage {
|
|
|
239
243
|
}
|
|
240
244
|
i += 2;
|
|
241
245
|
}
|
|
246
|
+
msg.isProcessed = true;
|
|
242
247
|
}
|
|
243
248
|
private static processCircuit(msg: Inbound) {
|
|
244
249
|
let schedId = (msg.extractPayloadByte(1) - 5) * 40 + 1;
|
|
@@ -258,6 +263,7 @@ export class ScheduleMessage {
|
|
|
258
263
|
csched.circuit = schedule.circuit;
|
|
259
264
|
}
|
|
260
265
|
}
|
|
266
|
+
msg.isProcessed = true;
|
|
261
267
|
}
|
|
262
268
|
private static processRunOnce(msg: Inbound) {
|
|
263
269
|
let schedId = (msg.extractPayloadByte(1) - 8) * 40 + 1;
|
|
@@ -280,6 +286,7 @@ export class ScheduleMessage {
|
|
|
280
286
|
csched.scheduleType = schedule.scheduleType;
|
|
281
287
|
}
|
|
282
288
|
}
|
|
289
|
+
msg.isProcessed = true;
|
|
283
290
|
}
|
|
284
291
|
private static processDays(msg: Inbound) {
|
|
285
292
|
let schedId = (msg.extractPayloadByte(1) - 11) * 40 + 1;
|
|
@@ -291,6 +298,7 @@ export class ScheduleMessage {
|
|
|
291
298
|
csched.scheduleDays = csched.scheduleType === 128 ? schedule.scheduleDays : 0;
|
|
292
299
|
}
|
|
293
300
|
}
|
|
301
|
+
msg.isProcessed = true;
|
|
294
302
|
}
|
|
295
303
|
private static processHeatSource(msg: Inbound) {
|
|
296
304
|
let schedId = (msg.extractPayloadByte(1) - 28) * 40 + 1;
|
|
@@ -305,6 +313,7 @@ export class ScheduleMessage {
|
|
|
305
313
|
csched.heatSource = schedule.heatSource;
|
|
306
314
|
}
|
|
307
315
|
}
|
|
316
|
+
msg.isProcessed = true;
|
|
308
317
|
}
|
|
309
318
|
private static processHeatSetpoint(msg: Inbound) {
|
|
310
319
|
let schedId = (msg.extractPayloadByte(1) - 31) * 40 + 1;
|
|
@@ -316,6 +325,7 @@ export class ScheduleMessage {
|
|
|
316
325
|
csched.heatSetpoint = schedule.heatSetpoint;
|
|
317
326
|
}
|
|
318
327
|
}
|
|
328
|
+
msg.isProcessed = true;
|
|
319
329
|
}
|
|
320
330
|
private static processCoolSetpoint(msg: Inbound) {
|
|
321
331
|
let schedId = (msg.extractPayloadByte(1) - 34) * 40 + 1;
|
|
@@ -327,5 +337,6 @@ export class ScheduleMessage {
|
|
|
327
337
|
csched.coolSetpoint = schedule.coolSetpoint;
|
|
328
338
|
}
|
|
329
339
|
}
|
|
340
|
+
msg.isProcessed = true;
|
|
330
341
|
}
|
|
331
342
|
}
|
|
@@ -34,5 +34,6 @@ export class SecurityMessage {
|
|
|
34
34
|
role.flag2 = msg.extractPayloadByte(3);
|
|
35
35
|
role.pin = msg.extractPayloadByte(21).toString() + msg.extractPayloadByte(22).toString() + msg.extractPayloadByte(23).toString() + msg.extractPayloadByte(24).toString();
|
|
36
36
|
}
|
|
37
|
+
msg.isProcessed = true;
|
|
37
38
|
}
|
|
38
39
|
}
|
|
@@ -32,6 +32,7 @@ export class ValveMessage {
|
|
|
32
32
|
ValveMessage.processValveNames(msg);
|
|
33
33
|
break;
|
|
34
34
|
case 3: // Skip the secondary intake/return
|
|
35
|
+
msg.isProcessed = true;
|
|
35
36
|
break;
|
|
36
37
|
case 4:
|
|
37
38
|
case 5:
|
|
@@ -70,6 +71,7 @@ export class ValveMessage {
|
|
|
70
71
|
// [165,33,15,16,35,2],[132,0],[1,142]
|
|
71
72
|
// ^^^ 128 = Pump off during valve operation
|
|
72
73
|
sys.general.options.pumpDelay = msg.extractPayloadByte(0) >> 7 === 1;
|
|
74
|
+
msg.isProcessed = true;
|
|
73
75
|
}
|
|
74
76
|
private static process_ValveAssignment_IT(msg: Inbound) {
|
|
75
77
|
// sample packet
|
|
@@ -91,6 +93,7 @@ export class ValveMessage {
|
|
|
91
93
|
let svalve = state.valves.getItemById(id, true);
|
|
92
94
|
svalve.name = valve.name;
|
|
93
95
|
svalve.type = valve.type;
|
|
96
|
+
valve.master = 0;
|
|
94
97
|
}
|
|
95
98
|
else {
|
|
96
99
|
sys.valves.removeItemById(id);
|
|
@@ -110,6 +113,7 @@ export class ValveMessage {
|
|
|
110
113
|
let svalve = state.valves.getItemById(id, true);
|
|
111
114
|
svalve.name = valve.name;
|
|
112
115
|
svalve.type = valve.type;
|
|
116
|
+
valve.master = 0;
|
|
113
117
|
}
|
|
114
118
|
else {
|
|
115
119
|
sys.valves.removeItemById(id);
|
|
@@ -136,17 +140,20 @@ export class ValveMessage {
|
|
|
136
140
|
let svalve = state.valves.getItemById(id, true);
|
|
137
141
|
svalve.name = valve.name;
|
|
138
142
|
svalve.type = valve.type;
|
|
143
|
+
valve.master = 0;
|
|
139
144
|
}
|
|
140
145
|
if (!valve.isActive) {
|
|
141
146
|
sys.valves.removeItemById(id);
|
|
142
147
|
state.valves.removeItemById(id);
|
|
143
148
|
}
|
|
144
149
|
else {
|
|
145
|
-
valve.
|
|
150
|
+
valve.master = 0;
|
|
151
|
+
// valve.isVirtual = false;
|
|
146
152
|
valve.type = 0;
|
|
147
153
|
}
|
|
148
154
|
id++;
|
|
149
155
|
}
|
|
156
|
+
msg.isProcessed = true;
|
|
150
157
|
}
|
|
151
158
|
private static getName(id: number, cir: number) {
|
|
152
159
|
if (cir <= 0 || cir >= 255 || cir === 6) {
|
|
@@ -187,7 +194,8 @@ export class ValveMessage {
|
|
|
187
194
|
ndx += 2;
|
|
188
195
|
}
|
|
189
196
|
let valve: Valve = sys.valves.getItemById(id, true);
|
|
190
|
-
valve.
|
|
197
|
+
valve.master = 0;
|
|
198
|
+
// valve.isVirtual = false;
|
|
191
199
|
if (id === 3 || id === 5) {
|
|
192
200
|
valve.circuit = 247; // Hardcode the intake/return to pool/spa;
|
|
193
201
|
valve.isIntake = true;
|
|
@@ -214,6 +222,7 @@ export class ValveMessage {
|
|
|
214
222
|
}
|
|
215
223
|
// Sort them so they are in valve id order. This will ensure any OCP valves come first in the list. Valves ids > 50 are virtual valves.
|
|
216
224
|
sys.valves.sortById();
|
|
225
|
+
msg.isProcessed = true;
|
|
217
226
|
}
|
|
218
227
|
private static processValveNames(msg: Inbound) {
|
|
219
228
|
let byte = msg.extractPayloadByte(1);
|
|
@@ -228,5 +237,6 @@ export class ValveMessage {
|
|
|
228
237
|
if (typeof sys.valves.find(elem => elem.id === valveId) !== 'undefined') {
|
|
229
238
|
state.valves.getItemById(valveId).name = sys.valves.getItemById(valveId++).name = msg.extractPayloadString(18, 16);
|
|
230
239
|
}
|
|
240
|
+
msg.isProcessed = true;
|
|
231
241
|
}
|
|
232
242
|
}
|
|
@@ -64,9 +64,8 @@ export class ChlorinatorStateMessage {
|
|
|
64
64
|
//[16, 2, 0, 3][0, 73, 110, 116, 101, 108, 108, 105, 99, 104, 108, 111, 114, 45, 45, 52, 48][188, 16, 3]
|
|
65
65
|
// This is the model number of the chlorinator and the address is actually the second byte.
|
|
66
66
|
let name = msg.extractPayloadString(1, 16);
|
|
67
|
-
chlor.
|
|
68
|
-
if (typeof chlor.
|
|
69
|
-
cstate.name = chlor.name;
|
|
67
|
+
if (typeof chlor.name === 'undefined' || chlor.name === '') chlor.name = cstate.name = name;
|
|
68
|
+
if (typeof chlor.model === 'undefined') chlor.model = sys.board.valueMaps.chlorinatorModel.getValue(name.toLowerCase());
|
|
70
69
|
cstate.isActive = chlor.isActive;
|
|
71
70
|
state.emitEquipmentChanges();
|
|
72
71
|
break;
|
|
@@ -101,7 +101,9 @@ export class EquipmentStateMessage {
|
|
|
101
101
|
Message.headerSubByte = msg.header[1];
|
|
102
102
|
//console.log(process.memoryUsage());
|
|
103
103
|
if (msg.action === 2 && state.isInitialized && sys.controllerType === ControllerType.Nixie) {
|
|
104
|
-
// Start over because we didn't have communication before but we now do.
|
|
104
|
+
// Start over because we didn't have communication before but we now do. This will fall into the if
|
|
105
|
+
// below so that it goes through the intialization process. In this case we didn't see an OCP when we started
|
|
106
|
+
// but there clearly is one now.
|
|
105
107
|
sys.controllerType = ControllerType.Unknown;
|
|
106
108
|
state.status = 0;
|
|
107
109
|
}
|
|
@@ -139,19 +141,24 @@ export class EquipmentStateMessage {
|
|
|
139
141
|
|
|
140
142
|
// Shared
|
|
141
143
|
let dt = new Date();
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
144
|
+
// RKS: This was moved to the ChemControllerState message. This is flawed in that it incorrectly sets IntelliChem to no comms.
|
|
145
|
+
//if (state.chemControllers.length > 0) {
|
|
146
|
+
// // TODO: move this to chemController when we understand the packets better
|
|
147
|
+
// for (let i = 0; i < state.chemControllers.length; i++) {
|
|
148
|
+
// let ccontroller = state.chemControllers.getItemByIndex(i);
|
|
149
|
+
// if (sys.board.valueMaps.chemControllerTypes.getName(ccontroller.type) === 'intellichem') {
|
|
150
|
+
// if (dt.getTime() - ccontroller.lastComm > 60000) ccontroller.status = 1;
|
|
151
|
+
// }
|
|
152
|
+
// }
|
|
153
|
+
//}
|
|
151
154
|
state.time.hours = msg.extractPayloadByte(0);
|
|
152
155
|
state.time.minutes = msg.extractPayloadByte(1);
|
|
153
156
|
state.time.seconds = dt.getSeconds();
|
|
154
|
-
state.mode = msg.extractPayloadByte(9) & 0x81;
|
|
157
|
+
state.mode = sys.controllerType !== ControllerType.IntelliCenter ? (msg.extractPayloadByte(9) & 0x81) : (msg.extractPayloadByte(9) & 0x01);
|
|
158
|
+
|
|
159
|
+
// RKS: The units have been normalized for English and Metric for the overall panel. It is important that the val numbers match for at least the temp units since
|
|
160
|
+
// the only unit of measure native to the Touch controllers is temperature they chose to name these C or F. However, with the njsPC extensions this is non-semantic
|
|
161
|
+
// since pressure, volume, and length have been introduced.
|
|
155
162
|
sys.general.options.units = state.temps.units = msg.extractPayloadByte(9) & 0x04;
|
|
156
163
|
state.valve = msg.extractPayloadByte(10);
|
|
157
164
|
|
|
@@ -197,10 +204,19 @@ export class EquipmentStateMessage {
|
|
|
197
204
|
tbody.name = cbody.name;
|
|
198
205
|
tbody.circuit = cbody.circuit = 6;
|
|
199
206
|
tbody.heatStatus = msg.extractPayloadByte(11) & 0x0F;
|
|
200
|
-
|
|
207
|
+
// With the IntelliCenter i10D, bit 6 is not reliable. It is not set properly and requires the 204 message
|
|
208
|
+
// to process the data.
|
|
209
|
+
if (!sys.equipment.dual) {
|
|
210
|
+
if ((msg.extractPayloadByte(2) & 0x20) === 32) {
|
|
211
|
+
tbody.temp = state.temps.waterSensor1;
|
|
212
|
+
tbody.isOn = true;
|
|
213
|
+
} else tbody.isOn = false;
|
|
214
|
+
}
|
|
215
|
+
else if (state.circuits.getItemById(6).isOn === true) {
|
|
201
216
|
tbody.temp = state.temps.waterSensor1;
|
|
202
217
|
tbody.isOn = true;
|
|
203
|
-
}
|
|
218
|
+
}
|
|
219
|
+
else tbody.isOn = false;
|
|
204
220
|
}
|
|
205
221
|
if (sys.bodies.length > 1) {
|
|
206
222
|
const tbody: BodyTempState = state.temps.bodies.getItemById(2, true);
|
|
@@ -210,10 +226,16 @@ export class EquipmentStateMessage {
|
|
|
210
226
|
tbody.name = cbody.name;
|
|
211
227
|
tbody.circuit = cbody.circuit = 1;
|
|
212
228
|
tbody.heatStatus = (msg.extractPayloadByte(11) & 0xF0) >> 4;
|
|
213
|
-
if (
|
|
229
|
+
if (!sys.equipment.dual) {
|
|
230
|
+
if ((msg.extractPayloadByte(2) & 0x01) === 1) {
|
|
231
|
+
tbody.temp = sys.equipment.shared ? state.temps.waterSensor1 : state.temps.waterSensor2;
|
|
232
|
+
tbody.isOn = true;
|
|
233
|
+
} else tbody.isOn = false;
|
|
234
|
+
} else if (state.circuits.getItemById(1).isOn === true) {
|
|
214
235
|
tbody.temp = sys.equipment.shared ? state.temps.waterSensor1 : state.temps.waterSensor2;
|
|
215
236
|
tbody.isOn = true;
|
|
216
|
-
}
|
|
237
|
+
}
|
|
238
|
+
else tbody.isOn = false;
|
|
217
239
|
}
|
|
218
240
|
if (sys.bodies.length > 2) {
|
|
219
241
|
state.temps.waterSensor3 = fnTempFromByte(msg.extractPayloadByte(20));
|
|
@@ -396,8 +418,8 @@ export class EquipmentStateMessage {
|
|
|
396
418
|
sys.board.heaters.syncHeaterStates();
|
|
397
419
|
break;
|
|
398
420
|
}
|
|
399
|
-
case ControllerType.IntelliCom:
|
|
400
421
|
case ControllerType.EasyTouch:
|
|
422
|
+
case ControllerType.IntelliCom:
|
|
401
423
|
case ControllerType.IntelliTouch:
|
|
402
424
|
{
|
|
403
425
|
EquipmentStateMessage.processTouchCircuits(msg);
|
|
@@ -497,8 +519,7 @@ export class EquipmentStateMessage {
|
|
|
497
519
|
state.time.date = msg.extractPayloadByte(6);
|
|
498
520
|
state.time.month = msg.extractPayloadByte(7);
|
|
499
521
|
state.time.year = msg.extractPayloadByte(8);
|
|
500
|
-
sys.equipment.controllerFirmware = (msg.extractPayloadByte(42)
|
|
501
|
-
+ (msg.extractPayloadByte(43) / 1000)).toString();
|
|
522
|
+
sys.equipment.controllerFirmware = (msg.extractPayloadByte(42) + (msg.extractPayloadByte(43) / 1000)).toString();
|
|
502
523
|
if (sys.chlorinators.length > 0) {
|
|
503
524
|
if (msg.extractPayloadByte(37, 255) !== 255) {
|
|
504
525
|
const chlor = state.chlorinators.getItemById(1);
|
|
@@ -510,9 +531,38 @@ export class EquipmentStateMessage {
|
|
|
510
531
|
}
|
|
511
532
|
}
|
|
512
533
|
ExternalMessage.processFeatureState(9, msg);
|
|
534
|
+
//if (sys.equipment.dual === true) {
|
|
535
|
+
// // For IntelliCenter i10D the body state is on byte 26 of the 204. This impacts circuit 6.
|
|
536
|
+
// let byte = msg.extractPayloadByte(26);
|
|
537
|
+
// let pstate = state.circuits.getItemById(6, true);
|
|
538
|
+
// let oldstate = pstate.isOn;
|
|
539
|
+
// pstate.isOn = ((byte & 0x0010) === 0x0010);
|
|
540
|
+
// logger.info(`Checking i10D pool state ${byte} old:${oldstate} new: ${pstate.isOn}`);
|
|
541
|
+
// //if (oldstate !== pstate.isOn) {
|
|
542
|
+
// state.temps.bodies.getItemById(1, true).isOn = pstate.isOn;
|
|
543
|
+
// sys.board.circuits.syncCircuitRelayStates();
|
|
544
|
+
// sys.board.circuits.syncVirtualCircuitStates();
|
|
545
|
+
// sys.board.valves.syncValveStates();
|
|
546
|
+
// sys.board.filters.syncFilterStates();
|
|
547
|
+
// sys.board.heaters.syncHeaterStates();
|
|
548
|
+
// //}
|
|
549
|
+
// if (oldstate !== pstate.isOn) pstate.emitEquipmentChange();
|
|
550
|
+
//}
|
|
551
|
+
// At this point normally on is ignored. Not sure what this does.
|
|
552
|
+
let cover1 = sys.covers.getItemById(1);
|
|
553
|
+
let cover2 = sys.covers.getItemById(2);
|
|
554
|
+
if (cover1.isActive) {
|
|
555
|
+
let scover1 = state.covers.getItemById(1, true);
|
|
556
|
+
scover1.name = cover1.name;
|
|
557
|
+
state.temps.bodies.getItemById(cover1.body + 1).isCovered = scover1.isClosed = (msg.extractPayloadByte(30) & 0x0001) > 0;
|
|
558
|
+
}
|
|
559
|
+
if (cover2.isActive) {
|
|
560
|
+
let scover2 = state.covers.getItemById(2, true);
|
|
561
|
+
scover2.name = cover2.name;
|
|
562
|
+
state.temps.bodies.getItemById(cover2.body + 1).isCovered = scover2.isClosed = (msg.extractPayloadByte(30) & 0x0002) > 0;
|
|
563
|
+
}
|
|
513
564
|
msg.isProcessed = true;
|
|
514
|
-
|
|
515
|
-
// state.emitEquipmentChanges();
|
|
565
|
+
state.emitEquipmentChanges();
|
|
516
566
|
break;
|
|
517
567
|
}
|
|
518
568
|
}
|
|
@@ -530,13 +580,15 @@ export class EquipmentStateMessage {
|
|
|
530
580
|
let circuit = sys.circuits.getItemById(circuitId, false, { isActive: false });
|
|
531
581
|
if (circuit.isActive !== false) {
|
|
532
582
|
let cstate = state.circuits.getItemById(circuitId, circuit.isActive);
|
|
533
|
-
|
|
534
|
-
sys.
|
|
583
|
+
// For IntelliCenter i10D body circuits are not reported here.
|
|
584
|
+
let isOn = ((circuitId === 6 || circuitId === 1) && sys.equipment.dual === true) ? cstate.isOn : (byte & (1 << j)) > 0;
|
|
585
|
+
//let isOn = (byte & (1 << j)) > 0;
|
|
535
586
|
cstate.isOn = isOn;
|
|
536
587
|
cstate.name = circuit.name;
|
|
537
588
|
cstate.nameId = circuit.nameId;
|
|
538
589
|
cstate.showInFeatures = circuit.showInFeatures;
|
|
539
590
|
cstate.type = circuit.type;
|
|
591
|
+
sys.board.circuits.setEndTime(circuit, cstate, isOn);
|
|
540
592
|
if (sys.controllerType === ControllerType.IntelliCenter) {
|
|
541
593
|
// intellitouch sends a separate msg with themes
|
|
542
594
|
switch (circuit.type) {
|
|
@@ -34,16 +34,25 @@ export class HeaterStateMessage {
|
|
|
34
34
|
// RKS: 07-03-21 - We only know byte 2 at this point for Ultratemp for the 115 message we are processing here. The
|
|
35
35
|
// byte description
|
|
36
36
|
// ------------------------------------------------
|
|
37
|
-
// 0 Unknown
|
|
38
|
-
// 1 Unknown
|
|
37
|
+
// 0 Unknown (always seems to be 160 for response)
|
|
38
|
+
// 1 Unknown (always 1)
|
|
39
39
|
// 2 Current heater status 0=off, 1=heat, 2=cool
|
|
40
40
|
// 3-9 Unknown
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// We need to decode the message. For a 2 of
|
|
44
|
-
//[165, 1, 15, 16, 2, 29][16, 42, 3, 0, 0, 0, 0, 0, 0, 32, 0, 0, 2, 0, 88, 88, 0, 241, 95, 100, 24, 246, 0, 0, 0, 0, 0, 40, 0][4, 221]
|
|
41
|
+
|
|
42
|
+
// 114 message - outbound response
|
|
45
43
|
//[165, 0, 112, 16, 114, 10][144, 0, 0, 0, 0, 0, 0, 0, 0, 0][2, 49] // OCP to Heater
|
|
44
|
+
// byte description
|
|
45
|
+
// ------------------------------------------------
|
|
46
|
+
// 0 Unknown (always seems to be 144 for request)
|
|
47
|
+
// 1 Current heater status 0=off, 1=heat, 2=cool
|
|
48
|
+
// 3 Believed to be ofset temp
|
|
49
|
+
// 4-9 Unknown
|
|
50
|
+
|
|
51
|
+
// byto 0: always seems to be 144 for outbound
|
|
52
|
+
// byte 1: Sets heater mode to 0 = Off 1 = Heat 2 = Cool
|
|
46
53
|
//[165, 0, 16, 112, 115, 10][160, 1, 0, 3, 0, 0, 0, 0, 0, 0][2, 70] // Heater Reply
|
|
54
|
+
let heater: Heater = sys.heaters.getItemByAddress(msg.source);
|
|
55
|
+
let sheater = state.heaters.getItemById(heater.id);
|
|
47
56
|
let byte = msg.extractPayloadByte(2);
|
|
48
57
|
sheater.isOn = byte >= 1;
|
|
49
58
|
sheater.isCooling = byte === 2;
|