nodejs-poolcontroller 7.3.0 → 7.6.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/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/Changelog +23 -0
- package/README.md +5 -5
- package/app.ts +2 -0
- package/config/Config.ts +3 -0
- package/config/VersionCheck.ts +8 -4
- package/controller/Constants.ts +88 -0
- package/controller/Equipment.ts +246 -66
- package/controller/Errors.ts +24 -1
- package/controller/Lockouts.ts +423 -0
- package/controller/State.ts +314 -54
- package/controller/boards/EasyTouchBoard.ts +107 -59
- package/controller/boards/IntelliCenterBoard.ts +186 -125
- package/controller/boards/IntelliTouchBoard.ts +104 -30
- package/controller/boards/NixieBoard.ts +721 -159
- package/controller/boards/SystemBoard.ts +2370 -1108
- package/controller/comms/Comms.ts +85 -10
- 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 +44 -26
- 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 +15 -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 +13 -3
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +2 -3
- package/controller/comms/messages/status/EquipmentStateMessage.ts +78 -24
- package/controller/comms/messages/status/HeaterStateMessage.ts +42 -9
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +37 -26
- package/controller/nixie/Nixie.ts +18 -16
- package/controller/nixie/bodies/Body.ts +4 -1
- package/controller/nixie/chemistry/ChemController.ts +80 -77
- package/controller/nixie/chemistry/Chlorinator.ts +9 -8
- package/controller/nixie/circuits/Circuit.ts +55 -6
- package/controller/nixie/heaters/Heater.ts +192 -32
- package/controller/nixie/pumps/Pump.ts +146 -84
- package/controller/nixie/schedules/Schedule.ts +3 -2
- package/controller/nixie/valves/Valve.ts +1 -1
- package/defaultConfig.json +32 -1
- package/issue_template.md +1 -1
- package/logger/DataLogger.ts +37 -22
- package/package.json +20 -18
- package/web/Server.ts +520 -29
- package/web/bindings/influxDB.json +96 -8
- package/web/bindings/mqtt.json +151 -40
- package/web/bindings/mqttAlt.json +114 -4
- package/web/interfaces/httpInterface.ts +2 -0
- package/web/interfaces/influxInterface.ts +36 -19
- package/web/interfaces/mqttInterface.ts +14 -3
- package/web/services/config/Config.ts +171 -44
- package/web/services/state/State.ts +49 -5
- package/web/services/state/StateSocket.ts +18 -1
|
@@ -107,6 +107,7 @@ export class HeaterMessage {
|
|
|
107
107
|
catch (err) { logger.error(`Error with OCP reclaiming control over gas heater: ${err}`) }
|
|
108
108
|
})();
|
|
109
109
|
}
|
|
110
|
+
heater.master = 0;
|
|
110
111
|
sys.heaters.getItemById(2).isActive = false;
|
|
111
112
|
sys.heaters.getItemById(3).isActive = false;
|
|
112
113
|
sys.heaters.getItemById(4).isActive = false;
|
|
@@ -133,6 +134,7 @@ export class HeaterMessage {
|
|
|
133
134
|
catch (err) { logger.error(`Error with OCP reclaiming control over Ultratemp: ${err}`) }
|
|
134
135
|
})();
|
|
135
136
|
}
|
|
137
|
+
heatPump.master = 0;
|
|
136
138
|
heatPump.name = 'Ultratemp';
|
|
137
139
|
heatPump.body = 32;
|
|
138
140
|
heatPump.type = 4;
|
|
@@ -158,6 +160,7 @@ export class HeaterMessage {
|
|
|
158
160
|
catch (err) { logger.error(`Error with OCP reclaiming control over heat pump: ${err}`) }
|
|
159
161
|
})();
|
|
160
162
|
}
|
|
163
|
+
heatPump.master = 0;
|
|
161
164
|
heatPump.name = 'Heat Pump';
|
|
162
165
|
heatPump.body = 32;
|
|
163
166
|
heatPump.type = 3;
|
|
@@ -184,6 +187,7 @@ export class HeaterMessage {
|
|
|
184
187
|
catch (err) { logger.error(`Error with OCP reclaiming control over solar heater: ${err}`) }
|
|
185
188
|
})();
|
|
186
189
|
}
|
|
190
|
+
solar.master = 0;
|
|
187
191
|
solar.name = 'Solar Heater';
|
|
188
192
|
solar.type = 2;
|
|
189
193
|
solar.isActive = true;
|
|
@@ -215,13 +219,7 @@ export class HeaterMessage {
|
|
|
215
219
|
}
|
|
216
220
|
sys.board.heaters.syncHeaterStates();
|
|
217
221
|
sys.equipment.setEquipmentIds();
|
|
218
|
-
|
|
219
|
-
case 114:
|
|
220
|
-
// something to do with heat pumps... need equipment or other packets to decipher
|
|
221
|
-
// [ 255, 0, 255], [165, 0, 112, 16, 114, 10], [144, 2, 0, 0, 0, 0, 0, 0, 0, 0], [2, 51 ]heat + cool
|
|
222
|
-
// [165,0,112,16,114,10][144,0,0,0,0,0,0,0,0,0][2,49] == no Heater, no cool
|
|
223
|
-
// [165,0,112,16,114,10][144,2,0,0,0,0,0,0,0,0][2,51] == no heat, cooling
|
|
224
|
-
// this might be heatStatus not heatMode?
|
|
222
|
+
msg.isProcessed = true;
|
|
225
223
|
break;
|
|
226
224
|
case 168:
|
|
227
225
|
{
|
|
@@ -241,7 +239,7 @@ export class HeaterMessage {
|
|
|
241
239
|
}
|
|
242
240
|
// Spa Manual Heat on/off
|
|
243
241
|
sys.general.options.manualHeat = msg.extractPayloadByte(4) === 1 ? true : false;
|
|
244
|
-
|
|
242
|
+
msg.isProcessed = true;
|
|
245
243
|
}
|
|
246
244
|
}
|
|
247
245
|
}
|
|
@@ -261,6 +259,7 @@ export class HeaterMessage {
|
|
|
261
259
|
})();
|
|
262
260
|
}
|
|
263
261
|
}
|
|
262
|
+
msg.isProcessed = true;
|
|
264
263
|
}
|
|
265
264
|
|
|
266
265
|
//private static processBody(msg: Inbound) {
|
|
@@ -293,6 +292,7 @@ export class HeaterMessage {
|
|
|
293
292
|
catch (err) { logger.error(`Error with OCP reclaiming control over heater: ${err}`) }
|
|
294
293
|
})();
|
|
295
294
|
}
|
|
295
|
+
heater.master = 0;
|
|
296
296
|
let hstate = state.heaters.getItemById(i);
|
|
297
297
|
// hstate.isVirtual = false;
|
|
298
298
|
hstate.name = heater.name;
|
|
@@ -300,12 +300,14 @@ export class HeaterMessage {
|
|
|
300
300
|
|
|
301
301
|
}
|
|
302
302
|
sys.board.heaters.updateHeaterServices();
|
|
303
|
+
msg.isProcessed = true;
|
|
303
304
|
}
|
|
304
305
|
private static processMaxBoostTemp(msg: Inbound) {
|
|
305
306
|
for (let i = 0; i < msg.payload.length - 1 && i < sys.equipment.maxHeaters; i++) {
|
|
306
307
|
var heater: Heater = sys.heaters.getItemById(i + 1);
|
|
307
308
|
heater.maxBoostTemp = msg.extractPayloadByte(i + 2);
|
|
308
309
|
}
|
|
310
|
+
msg.isProcessed = true;
|
|
309
311
|
}
|
|
310
312
|
private static processStartStopDelta(msg: Inbound) {
|
|
311
313
|
for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxHeaters; i++) {
|
|
@@ -313,6 +315,7 @@ export class HeaterMessage {
|
|
|
313
315
|
heater.startTempDelta = msg.extractPayloadByte(i + 1);
|
|
314
316
|
heater.stopTempDelta = msg.extractPayloadByte(i + 18);
|
|
315
317
|
}
|
|
318
|
+
msg.isProcessed = true;
|
|
316
319
|
}
|
|
317
320
|
private static processCoolingSetTemp(msg: Inbound) {
|
|
318
321
|
for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxHeaters; i++) {
|
|
@@ -320,20 +323,22 @@ export class HeaterMessage {
|
|
|
320
323
|
heater.coolingEnabled = msg.extractPayloadByte(i + 1) > 0;
|
|
321
324
|
heater.differentialTemp = msg.extractPayloadByte(i + 18);
|
|
322
325
|
}
|
|
326
|
+
msg.isProcessed = true;
|
|
323
327
|
}
|
|
324
328
|
private static processAddress(msg: Inbound) {
|
|
325
329
|
for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxHeaters; i++) {
|
|
326
330
|
var heater: Heater = sys.heaters.getItemById(i);
|
|
327
331
|
heater.address = msg.extractPayloadByte(i + 1);
|
|
328
332
|
}
|
|
333
|
+
msg.isProcessed = true;
|
|
329
334
|
}
|
|
330
335
|
private static processEfficiencyMode(msg: Inbound) {
|
|
331
336
|
for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxHeaters; i++) {
|
|
332
337
|
var heater: Heater = sys.heaters.getItemById(i);
|
|
333
338
|
heater.efficiencyMode = msg.extractPayloadByte(i + 1);
|
|
334
339
|
}
|
|
340
|
+
msg.isProcessed = true;
|
|
335
341
|
}
|
|
336
|
-
|
|
337
342
|
private static processHeaterNames(msg: Inbound) {
|
|
338
343
|
var heaterId = ((msg.extractPayloadByte(1) - 5) * 2) + 1;
|
|
339
344
|
if (heaterId <= sys.equipment.maxHeaters) {
|
|
@@ -344,5 +349,6 @@ export class HeaterMessage {
|
|
|
344
349
|
let hstate = state.heaters.getItemById(heaterId);
|
|
345
350
|
hstate.name = sys.heaters.getItemById(heaterId++).name = msg.extractPayloadString(18, 16);
|
|
346
351
|
}
|
|
352
|
+
msg.isProcessed = true;
|
|
347
353
|
}
|
|
348
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) {
|
|
@@ -167,7 +174,7 @@ export class ValveMessage {
|
|
|
167
174
|
// for i10d.
|
|
168
175
|
let ndx: number = 2;
|
|
169
176
|
let id = 1;
|
|
170
|
-
for (let i = 0; i < sys.equipment.maxValves
|
|
177
|
+
for (let i = 0; i < sys.equipment.maxValves; i++) {
|
|
171
178
|
if (id === 3 && !sys.equipment.shared) {
|
|
172
179
|
// The intake/return valves are skipped for non-shared systems.
|
|
173
180
|
sys.valves.removeItemById(3);
|
|
@@ -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
|
|
|
@@ -163,8 +170,8 @@ export class EquipmentStateMessage {
|
|
|
163
170
|
// 1. IntelliCenter has "manual" time set (Internet will automatically adjust) and autoAdjustDST is enabled
|
|
164
171
|
// 2. *Touch is "manual" (only option) and autoAdjustDST is enabled - (same as #1)
|
|
165
172
|
// 3. clock source is "server" isn't an OCP option but can be enabled on the clients
|
|
166
|
-
if (dt.getMinutes() % 5 === 0 && sys.general.options.clockSource === 'server') {
|
|
167
|
-
if ((Math.abs(dt.getTime() - state.time.getTime()) > 60 *
|
|
173
|
+
if (dt.getMinutes() % 5 === 0 && dt.getSeconds() <= 10 && sys.general.options.clockSource === 'server') {
|
|
174
|
+
if ((Math.abs(dt.getTime() - state.time.getTime()) > 60 * 2 * 1000) && !state.time.isUpdating) {
|
|
168
175
|
state.time.isUpdating = true;
|
|
169
176
|
sys.board.system.setDateTimeAsync({ dt, dst: sys.general.options.adjustDST || 0, })
|
|
170
177
|
.then(() => {
|
|
@@ -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));
|
|
@@ -390,13 +412,14 @@ export class EquipmentStateMessage {
|
|
|
390
412
|
sys.board.circuits.syncCircuitRelayStates();
|
|
391
413
|
sys.board.circuits.syncVirtualCircuitStates();
|
|
392
414
|
sys.board.valves.syncValveStates();
|
|
415
|
+
sys.board.filters.syncFilterStates();
|
|
393
416
|
state.emitControllerChange();
|
|
394
417
|
state.emitEquipmentChanges();
|
|
395
418
|
sys.board.heaters.syncHeaterStates();
|
|
396
419
|
break;
|
|
397
420
|
}
|
|
398
|
-
case ControllerType.IntelliCom:
|
|
399
421
|
case ControllerType.EasyTouch:
|
|
422
|
+
case ControllerType.IntelliCom:
|
|
400
423
|
case ControllerType.IntelliTouch:
|
|
401
424
|
{
|
|
402
425
|
EquipmentStateMessage.processTouchCircuits(msg);
|
|
@@ -405,6 +428,7 @@ export class EquipmentStateMessage {
|
|
|
405
428
|
sys.board.features.syncGroupStates();
|
|
406
429
|
sys.board.circuits.syncVirtualCircuitStates();
|
|
407
430
|
sys.board.valves.syncValveStates();
|
|
431
|
+
sys.board.filters.syncFilterStates();
|
|
408
432
|
state.emitControllerChange();
|
|
409
433
|
state.emitEquipmentChanges();
|
|
410
434
|
sys.board.heaters.syncHeaterStates();
|
|
@@ -495,8 +519,7 @@ export class EquipmentStateMessage {
|
|
|
495
519
|
state.time.date = msg.extractPayloadByte(6);
|
|
496
520
|
state.time.month = msg.extractPayloadByte(7);
|
|
497
521
|
state.time.year = msg.extractPayloadByte(8);
|
|
498
|
-
sys.equipment.controllerFirmware = (msg.extractPayloadByte(42)
|
|
499
|
-
+ (msg.extractPayloadByte(43) / 1000)).toString();
|
|
522
|
+
sys.equipment.controllerFirmware = (msg.extractPayloadByte(42) + (msg.extractPayloadByte(43) / 1000)).toString();
|
|
500
523
|
if (sys.chlorinators.length > 0) {
|
|
501
524
|
if (msg.extractPayloadByte(37, 255) !== 255) {
|
|
502
525
|
const chlor = state.chlorinators.getItemById(1);
|
|
@@ -508,9 +531,38 @@ export class EquipmentStateMessage {
|
|
|
508
531
|
}
|
|
509
532
|
}
|
|
510
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
|
+
}
|
|
511
564
|
msg.isProcessed = true;
|
|
512
|
-
|
|
513
|
-
// state.emitEquipmentChanges();
|
|
565
|
+
state.emitEquipmentChanges();
|
|
514
566
|
break;
|
|
515
567
|
}
|
|
516
568
|
}
|
|
@@ -528,13 +580,15 @@ export class EquipmentStateMessage {
|
|
|
528
580
|
let circuit = sys.circuits.getItemById(circuitId, false, { isActive: false });
|
|
529
581
|
if (circuit.isActive !== false) {
|
|
530
582
|
let cstate = state.circuits.getItemById(circuitId, circuit.isActive);
|
|
531
|
-
|
|
532
|
-
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;
|
|
533
586
|
cstate.isOn = isOn;
|
|
534
587
|
cstate.name = circuit.name;
|
|
535
588
|
cstate.nameId = circuit.nameId;
|
|
536
589
|
cstate.showInFeatures = circuit.showInFeatures;
|
|
537
590
|
cstate.type = circuit.type;
|
|
591
|
+
sys.board.circuits.setEndTime(circuit, cstate, isOn);
|
|
538
592
|
if (sys.controllerType === ControllerType.IntelliCenter) {
|
|
539
593
|
// intellitouch sends a separate msg with themes
|
|
540
594
|
switch (circuit.type) {
|