nodejs-poolcontroller 7.5.1 → 7.7.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/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/Changelog +19 -0
- package/Dockerfile +3 -3
- package/README.md +13 -8
- package/app.ts +1 -1
- package/config/Config.ts +38 -2
- package/config/VersionCheck.ts +27 -12
- package/controller/Constants.ts +2 -1
- package/controller/Equipment.ts +193 -9
- package/controller/Errors.ts +10 -0
- package/controller/Lockouts.ts +503 -0
- package/controller/State.ts +269 -64
- package/controller/boards/AquaLinkBoard.ts +1000 -0
- package/controller/boards/BoardFactory.ts +4 -0
- package/controller/boards/EasyTouchBoard.ts +468 -144
- package/controller/boards/IntelliCenterBoard.ts +466 -307
- package/controller/boards/IntelliTouchBoard.ts +37 -5
- package/controller/boards/NixieBoard.ts +671 -141
- package/controller/boards/SystemBoard.ts +1397 -641
- package/controller/comms/Comms.ts +462 -362
- package/controller/comms/messages/Messages.ts +174 -30
- package/controller/comms/messages/config/ChlorinatorMessage.ts +6 -3
- package/controller/comms/messages/config/CircuitMessage.ts +1 -0
- package/controller/comms/messages/config/ExternalMessage.ts +10 -8
- package/controller/comms/messages/config/HeaterMessage.ts +141 -29
- package/controller/comms/messages/config/OptionsMessage.ts +9 -2
- package/controller/comms/messages/config/PumpMessage.ts +53 -35
- package/controller/comms/messages/config/ScheduleMessage.ts +33 -25
- package/controller/comms/messages/config/ValveMessage.ts +2 -2
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +38 -86
- package/controller/comms/messages/status/EquipmentStateMessage.ts +59 -23
- package/controller/comms/messages/status/HeaterStateMessage.ts +57 -3
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +56 -8
- package/controller/comms/messages/status/PumpStateMessage.ts +23 -1
- package/controller/nixie/Nixie.ts +1 -1
- package/controller/nixie/bodies/Body.ts +3 -0
- package/controller/nixie/chemistry/ChemController.ts +164 -51
- package/controller/nixie/chemistry/Chlorinator.ts +137 -88
- package/controller/nixie/circuits/Circuit.ts +51 -19
- package/controller/nixie/heaters/Heater.ts +241 -31
- package/controller/nixie/pumps/Pump.ts +488 -206
- package/controller/nixie/schedules/Schedule.ts +91 -35
- package/controller/nixie/valves/Valve.ts +1 -1
- package/defaultConfig.json +20 -0
- package/package.json +21 -21
- package/web/Server.ts +94 -49
- package/web/bindings/aqualinkD.json +505 -0
- package/web/bindings/influxDB.json +71 -1
- package/web/bindings/mqtt.json +98 -39
- package/web/bindings/mqttAlt.json +59 -1
- package/web/interfaces/baseInterface.ts +1 -0
- package/web/interfaces/httpInterface.ts +23 -2
- package/web/interfaces/influxInterface.ts +45 -10
- package/web/interfaces/mqttInterface.ts +114 -54
- package/web/services/config/Config.ts +55 -132
- package/web/services/state/State.ts +81 -4
- package/web/services/state/StateSocket.ts +4 -4
- package/web/services/utilities/Utilities.ts +8 -6
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -52
- package/config copy.json +0 -300
- package/issue_template.md +0 -52
|
@@ -4,12 +4,13 @@ import { logger } from '../../../logger/Logger';
|
|
|
4
4
|
|
|
5
5
|
import { NixieEquipment, NixieChildEquipment, NixieEquipmentCollection, INixieControlPanel } from "../NixieEquipment";
|
|
6
6
|
import { Heater, HeaterCollection, sys } from "../../../controller/Equipment";
|
|
7
|
-
import { HeaterState, state, } from "../../State";
|
|
7
|
+
import { BodyTempState, HeaterState, state, } from "../../State";
|
|
8
8
|
import { setTimeout, clearTimeout } from 'timers';
|
|
9
9
|
import { NixieControlPanel } from '../Nixie';
|
|
10
10
|
import { webApp, InterfaceServerResponse } from "../../../web/Server";
|
|
11
11
|
import { conn } from '../../../controller/comms/Comms';
|
|
12
12
|
import { Outbound, Protocol, Response } from '../../../controller/comms/messages/Messages';
|
|
13
|
+
import { delayMgr } from '../../Lockouts';
|
|
13
14
|
|
|
14
15
|
export class NixieHeaterCollection extends NixieEquipmentCollection<NixieHeaterBase> {
|
|
15
16
|
public async deleteHeaterAsync(id: number) {
|
|
@@ -96,6 +97,8 @@ export class NixieHeaterBase extends NixieEquipment {
|
|
|
96
97
|
protected bodyOnTime: number;
|
|
97
98
|
protected isOn: boolean = false;
|
|
98
99
|
protected isCooling: boolean = false;
|
|
100
|
+
protected lastHeatCycle: Date;
|
|
101
|
+
protected lastCoolCycle: Date;
|
|
99
102
|
constructor(ncp: INixieControlPanel, heater: Heater) {
|
|
100
103
|
super(ncp);
|
|
101
104
|
this.heater = heater;
|
|
@@ -103,6 +106,7 @@ export class NixieHeaterBase extends NixieEquipment {
|
|
|
103
106
|
public get suspendPolling(): boolean { return this._suspendPolling > 0; }
|
|
104
107
|
public set suspendPolling(val: boolean) { this._suspendPolling = Math.max(0, this._suspendPolling + (val ? 1 : -1)); }
|
|
105
108
|
public get id(): number { return typeof this.heater !== 'undefined' ? this.heater.id : -1; }
|
|
109
|
+
public getCooldownTime() { return 0; }
|
|
106
110
|
public static create(ncp: INixieControlPanel, heater: Heater): NixieHeaterBase {
|
|
107
111
|
let type = sys.board.valueMaps.heaterTypes.transform(heater.type);
|
|
108
112
|
switch (type.name) {
|
|
@@ -144,34 +148,52 @@ export class NixieHeaterBase extends NixieEquipment {
|
|
|
144
148
|
}
|
|
145
149
|
export class NixieGasHeater extends NixieHeaterBase {
|
|
146
150
|
public pollingInterval: number = 10000;
|
|
147
|
-
declare heater: Heater;
|
|
151
|
+
//declare heater: Heater;
|
|
148
152
|
constructor(ncp: INixieControlPanel, heater: Heater) {
|
|
149
153
|
super(ncp, heater);
|
|
150
154
|
this.heater = heater;
|
|
155
|
+
if (typeof this.heater.stopTempDelta === 'undefined') this.heater.stopTempDelta = 1;
|
|
156
|
+
if (typeof this.heater.minCycleTime === 'undefined') this.heater.minCycleTime = 2;
|
|
151
157
|
this.pollEquipmentAsync();
|
|
152
158
|
}
|
|
153
159
|
public get id(): number { return typeof this.heater !== 'undefined' ? this.heater.id : -1; }
|
|
160
|
+
public getCooldownTime(): number {
|
|
161
|
+
// Delays are always in terms of seconds so convert the minute to seconds.
|
|
162
|
+
if (this.heater.cooldownDelay === 0 || typeof this.lastHeatCycle === 'undefined') return 0;
|
|
163
|
+
let now = new Date().getTime();
|
|
164
|
+
let cooldown = this.isOn ? this.heater.cooldownDelay * 60000 : Math.round( ((this.lastHeatCycle.getDate() + this.heater.cooldownDelay * 60000) - now) / 1000);
|
|
165
|
+
return Math.min(Math.max(0, cooldown), this.heater.cooldownDelay * 60);
|
|
166
|
+
}
|
|
154
167
|
public async setHeaterStateAsync(hstate: HeaterState, isOn: boolean) {
|
|
155
168
|
try {
|
|
156
169
|
// Initialize the desired state.
|
|
157
170
|
this.isOn = isOn;
|
|
158
171
|
this.isCooling = false;
|
|
172
|
+
let target = hstate.startupDelay === false && isOn;
|
|
173
|
+
if (target && typeof hstate.endTime !== 'undefined') {
|
|
174
|
+
// Calculate a short cycle time so that the gas heater does not cycle
|
|
175
|
+
// too often. For gas heaters this is 60 seconds. This gives enough time
|
|
176
|
+
// for the heater control circuit to make a full cycle.
|
|
177
|
+
if (new Date().getTime() - hstate.endTime.getTime() < this.heater.minCycleTime * 60000) {
|
|
178
|
+
logger.verbose(`${hstate.name} short cycle detected deferring turn on state`);
|
|
179
|
+
target = false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
159
182
|
// Here we go we need to set the firemans switch state.
|
|
160
|
-
if (hstate.isOn !==
|
|
183
|
+
if (hstate.isOn !== target) {
|
|
161
184
|
logger.info(`Nixie: Set Heater ${hstate.id}-${hstate.name} to ${isOn}`);
|
|
162
185
|
}
|
|
163
|
-
if (
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
return;
|
|
186
|
+
if (typeof this._lastState === 'undefined' || target || this._lastState !== target) {
|
|
187
|
+
if (utils.isNullOrEmpty(this.heater.connectionId) || utils.isNullOrEmpty(this.heater.deviceBinding)) {
|
|
188
|
+
this._lastState = hstate.isOn = target;
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
let res = await NixieEquipment.putDeviceService(this.heater.connectionId, `/state/device/${this.heater.deviceBinding}`,
|
|
192
|
+
{ isOn: target, latch: target ? 10000 : undefined });
|
|
193
|
+
if (res.status.code === 200) this._lastState = hstate.isOn = target;
|
|
194
|
+
else logger.error(`Nixie Error setting heater state: ${res.status.code} -${res.status.message} ${res.error.message}`);
|
|
195
|
+
}
|
|
196
|
+
if (target) this.lastHeatCycle = new Date();
|
|
175
197
|
}
|
|
176
198
|
} catch (err) { return logger.error(`Nixie Error setting heater state ${hstate.id}-${hstate.name}: ${err.message}`); }
|
|
177
199
|
}
|
|
@@ -228,25 +250,59 @@ export class NixieSolarHeater extends NixieHeaterBase {
|
|
|
228
250
|
public get id(): number { return typeof this.heater !== 'undefined' ? this.heater.id : -1; }
|
|
229
251
|
public async setHeaterStateAsync(hstate: HeaterState, isOn: boolean, isCooling: boolean) {
|
|
230
252
|
try {
|
|
253
|
+
let origState = hstate.isOn;
|
|
231
254
|
// Initialize the desired state.
|
|
232
255
|
this.isOn = isOn;
|
|
233
256
|
this.isCooling = isCooling;
|
|
234
|
-
|
|
235
|
-
if (hstate.
|
|
236
|
-
|
|
257
|
+
let target = hstate.startupDelay === false && isOn;
|
|
258
|
+
if (target && typeof hstate.endTime !== 'undefined') {
|
|
259
|
+
// Calculate a short cycle time so that the solar heater does not cycle
|
|
260
|
+
// too often. For solar heaters this is 60 seconds. This gives enough time
|
|
261
|
+
// for the valve to rotate and start heating. If the solar and water sensors are
|
|
262
|
+
// not having issues this should be plenty of time.
|
|
263
|
+
if (new Date().getTime() - hstate.endTime.getTime() < 60000) {
|
|
264
|
+
logger.verbose(`${hstate.name} short cycle detected deferring turn on state`);
|
|
265
|
+
target = false;
|
|
266
|
+
}
|
|
237
267
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
268
|
+
|
|
269
|
+
// Here we go we need to set the valve status that is attached to solar.
|
|
270
|
+
if (hstate.isOn !== target) {
|
|
271
|
+
logger.info(`Nixie: Set Heater ${hstate.id}-${hstate.name} to ${isOn}`);
|
|
241
272
|
}
|
|
242
|
-
if (typeof this._lastState === 'undefined' ||
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
273
|
+
if (typeof this._lastState === 'undefined' || target || this._lastState !== target) {
|
|
274
|
+
if (utils.isNullOrEmpty(this.heater.connectionId) || utils.isNullOrEmpty(this.heater.deviceBinding)) {
|
|
275
|
+
this._lastState = hstate.isOn = target;
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
let res = await NixieEquipment.putDeviceService(this.heater.connectionId, `/state/device/${this.heater.deviceBinding}`,
|
|
279
|
+
{ isOn: target, latch: target ? 10000 : undefined });
|
|
280
|
+
if (res.status.code === 200) this._lastState = hstate.isOn = target;
|
|
281
|
+
else logger.error(`Nixie Error setting heater state: ${res.status.code} -${res.status.message} ${res.error.message}`);
|
|
282
|
+
}
|
|
283
|
+
if (target) {
|
|
284
|
+
if (isCooling) this.lastCoolCycle = new Date();
|
|
285
|
+
else if (isOn) this.lastHeatCycle = new Date();
|
|
286
|
+
}
|
|
246
287
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
288
|
+
// In this instance we need to see if there are cleaner circuits that we need to turn off
|
|
289
|
+
// then delay for the current body because the solar just came on.
|
|
290
|
+
if (hstate.isOn && sys.general.options.cleanerSolarDelay && !origState) {
|
|
291
|
+
let arrTypes = sys.board.valueMaps.circuitFunctions.toArray().filter(x => { return x.name.indexOf('cleaner') !== -1 && x.body === hstate.bodyId });
|
|
292
|
+
let cleaners = sys.circuits.filter(x => { return arrTypes.findIndex(t => { return t.val === x.type }) !== -1 });
|
|
293
|
+
// Turn off all the cleaner circuits and set an on delay if they are on.
|
|
294
|
+
for (let i = 0; i < cleaners.length; i++) {
|
|
295
|
+
let cleaner = cleaners.getItemByIndex(i);
|
|
296
|
+
if (cleaner.isActive) {
|
|
297
|
+
let cstate = state.circuits.getItemById(cleaner.id);
|
|
298
|
+
if (cstate.isOn && sys.general.options.cleanerSolarDelayTime > 0) {
|
|
299
|
+
// Turn off the circuit then set a delay.
|
|
300
|
+
logger.info(`Setting cleaner solar delay for ${cleaner.name} to ${sys.general.options.cleanerSolarDelayTime}`);
|
|
301
|
+
await sys.board.circuits.setCircuitStateAsync(cstate.id, false);
|
|
302
|
+
delayMgr.setCleanerStartDelay(cstate, hstate.bodyId, sys.general.options.cleanerSolarDelayTime);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
250
306
|
}
|
|
251
307
|
} catch (err) { return logger.error(`Nixie Error setting heater state ${hstate.id}-${hstate.name}: ${err.message}`); }
|
|
252
308
|
}
|
|
@@ -304,6 +360,11 @@ export class NixieHeatpump extends NixieHeaterBase {
|
|
|
304
360
|
this.suspendPolling = true;
|
|
305
361
|
this.isOn = isOn;
|
|
306
362
|
this.isCooling = isCooling;
|
|
363
|
+
if (!hstate.startupDelay) {
|
|
364
|
+
if (isOn && !isCooling) this.lastHeatCycle = new Date();
|
|
365
|
+
else if (isCooling) this.lastCoolCycle = new Date();
|
|
366
|
+
}
|
|
367
|
+
// When this is implemented lets not forget to deal with the startup and any desired cool down delay. See UltraTemp for implementation.
|
|
307
368
|
} catch (err) { return logger.error(`Nixie Error setting heater state ${hstate.id}-${hstate.name}: ${err.message}`); }
|
|
308
369
|
finally { this.suspendPolling = false; }
|
|
309
370
|
}
|
|
@@ -334,6 +395,7 @@ export class NixieHeatpump extends NixieHeaterBase {
|
|
|
334
395
|
sheater.type = 2;
|
|
335
396
|
let success = await new Promise<boolean>((resolve, reject) => {
|
|
336
397
|
let out = Outbound.create({
|
|
398
|
+
portId: this.heater.portId || 0,
|
|
337
399
|
protocol: Protocol.Heater,
|
|
338
400
|
source: 16,
|
|
339
401
|
dest: this.heater.address,
|
|
@@ -395,10 +457,55 @@ export class NixieUltratemp extends NixieHeatpump {
|
|
|
395
457
|
}, this.pollingInterval || 10000);
|
|
396
458
|
}
|
|
397
459
|
}
|
|
460
|
+
public async setHeaterStateAsync(hstate: HeaterState, isOn: boolean, isCooling: boolean) {
|
|
461
|
+
try {
|
|
462
|
+
// Initialize the desired state.
|
|
463
|
+
this.isCooling = isCooling;
|
|
464
|
+
if (hstate.isOn !== isOn) {
|
|
465
|
+
logger.info(`Nixie: Set Heater ${hstate.id}-${hstate.name} to ${isCooling ? 'cooling' : isOn ? 'heating' : 'off'}`);
|
|
466
|
+
|
|
467
|
+
}
|
|
468
|
+
if (isOn && !hstate.startupDelay) this.lastHeatCycle = new Date();
|
|
469
|
+
hstate.isOn = isOn;
|
|
470
|
+
} catch (err) { return logger.error(`Nixie Error setting heater state ${hstate.id}-${hstate.name}: ${err.message}`); }
|
|
471
|
+
}
|
|
472
|
+
public async releaseHeater(sheater: HeaterState): Promise<boolean> {
|
|
473
|
+
try {
|
|
474
|
+
let success = await new Promise<boolean>((resolve, reject) => {
|
|
475
|
+
let out = Outbound.create({
|
|
476
|
+
portId: this.heater.portId || 0,
|
|
477
|
+
protocol: Protocol.Heater,
|
|
478
|
+
source: 16,
|
|
479
|
+
dest: this.heater.address,
|
|
480
|
+
action: 114,
|
|
481
|
+
payload: [],
|
|
482
|
+
retries: 3, // We are going to try 4 times.
|
|
483
|
+
response: Response.create({ protocol: Protocol.Heater, action: 115 }),
|
|
484
|
+
onAbort: () => { },
|
|
485
|
+
onComplete: (err) => {
|
|
486
|
+
if (err) {
|
|
487
|
+
// If the Ultratemp is not responding we need to store that off but at this point we know none of the codes. If a 115 does
|
|
488
|
+
// come across this will be cleared by the processing of that message.
|
|
489
|
+
sheater.commStatus = sys.board.valueMaps.equipmentCommStatus.getValue('commerr');
|
|
490
|
+
state.equipment.messages.setMessageByCode(`heater:${sheater.id}:comms`, 'error', `Communication error with ${sheater.name}`);
|
|
491
|
+
resolve(false);
|
|
492
|
+
}
|
|
493
|
+
else { resolve(true); }
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
out.appendPayloadBytes(0, 10);
|
|
497
|
+
out.setPayloadByte(0, 144);
|
|
498
|
+
out.setPayloadByte(1, 0, 0);
|
|
499
|
+
conn.queueSendMessage(out);
|
|
500
|
+
});
|
|
501
|
+
return success;
|
|
502
|
+
} catch (err) { logger.error(`Communication error with Ultratemp : ${err.message}`); }
|
|
503
|
+
}
|
|
398
504
|
public async setStatus(sheater: HeaterState): Promise<boolean> {
|
|
399
505
|
try {
|
|
400
506
|
let success = await new Promise<boolean>((resolve, reject) => {
|
|
401
507
|
let out = Outbound.create({
|
|
508
|
+
portId: this.heater.portId || 0,
|
|
402
509
|
protocol: Protocol.Heater,
|
|
403
510
|
source: 16,
|
|
404
511
|
dest: this.heater.address,
|
|
@@ -420,7 +527,16 @@ export class NixieUltratemp extends NixieHeatpump {
|
|
|
420
527
|
});
|
|
421
528
|
out.appendPayloadBytes(0, 10);
|
|
422
529
|
out.setPayloadByte(0, 144);
|
|
423
|
-
|
|
530
|
+
// If we are in startup delay simply tell the heater that it is off.
|
|
531
|
+
if (sheater.startupDelay || this.closing)
|
|
532
|
+
out.setPayloadByte(1, 0, 0);
|
|
533
|
+
else {
|
|
534
|
+
if (this.isOn) {
|
|
535
|
+
if (!this.isCooling) this.lastHeatCycle = new Date();
|
|
536
|
+
else this.lastCoolCycle = new Date();
|
|
537
|
+
}
|
|
538
|
+
out.setPayloadByte(1, this.isOn ? (this.isCooling ? 2 : 1) : 0, 0);
|
|
539
|
+
}
|
|
424
540
|
conn.queueSendMessage(out);
|
|
425
541
|
});
|
|
426
542
|
return success;
|
|
@@ -432,10 +548,104 @@ export class NixieUltratemp extends NixieHeatpump {
|
|
|
432
548
|
this.closing = true;
|
|
433
549
|
if (typeof this._pollTimer !== 'undefined' || this._pollTimer) clearTimeout(this._pollTimer);
|
|
434
550
|
this._pollTimer = null;
|
|
551
|
+
let sheater = state.heaters.getItemById(this.id);
|
|
552
|
+
await this.releaseHeater(sheater);
|
|
435
553
|
logger.info(`Closing Heater ${this.heater.name}`);
|
|
436
|
-
|
|
437
554
|
}
|
|
438
555
|
catch (err) { logger.error(`Ultratemp closeAsync: ${err.message}`); return Promise.reject(err); }
|
|
439
556
|
}
|
|
440
557
|
}
|
|
441
|
-
export class NixieMastertemp extends NixieGasHeater {
|
|
558
|
+
export class NixieMastertemp extends NixieGasHeater {
|
|
559
|
+
constructor(ncp: INixieControlPanel, heater: Heater) {
|
|
560
|
+
super(ncp, heater);
|
|
561
|
+
// Set the polling interval to 3 seconds.
|
|
562
|
+
this.pollEquipmentAsync();
|
|
563
|
+
this.pollingInterval = 3000;
|
|
564
|
+
}
|
|
565
|
+
/* public getCooldownTime(): number {
|
|
566
|
+
// Delays are always in terms of seconds so convert the minute to seconds.
|
|
567
|
+
if (this.heater.cooldownDelay === 0 || typeof this.lastHeatCycle === 'undefined') return 0;
|
|
568
|
+
let now = new Date().getTime();
|
|
569
|
+
let cooldown = this.isOn ? this.heater.cooldownDelay * 60000 : Math.round(((this.lastHeatCycle.getDate() + this.heater.cooldownDelay * 60000) - now) / 1000);
|
|
570
|
+
return Math.min(Math.max(0, cooldown), this.heater.cooldownDelay * 60);
|
|
571
|
+
} */
|
|
572
|
+
public async setHeaterStateAsync(hstate: HeaterState, isOn: boolean) {
|
|
573
|
+
try {
|
|
574
|
+
// Initialize the desired state.
|
|
575
|
+
this.isCooling = false;
|
|
576
|
+
// Here we go we need to set the firemans switch state.
|
|
577
|
+
if (hstate.isOn !== isOn) {
|
|
578
|
+
logger.info(`Nixie: Set Heater ${hstate.id}-${hstate.name} to ${isOn}`);
|
|
579
|
+
}
|
|
580
|
+
if (isOn && !hstate.startupDelay) this.lastHeatCycle = new Date();
|
|
581
|
+
hstate.isOn = isOn;
|
|
582
|
+
} catch (err) { return logger.error(`Nixie Error setting heater state ${hstate.id}-${hstate.name}: ${err.message}`); }
|
|
583
|
+
}
|
|
584
|
+
public async pollEquipmentAsync() {
|
|
585
|
+
let self = this;
|
|
586
|
+
try {
|
|
587
|
+
this.suspendPolling = true;
|
|
588
|
+
if (typeof this._pollTimer !== 'undefined' || this._pollTimer) clearTimeout(this._pollTimer);
|
|
589
|
+
this._pollTimer = null;
|
|
590
|
+
if (this._suspendPolling > 1) return;
|
|
591
|
+
let sheater = state.heaters.getItemById(this.heater.id, !this.closing);
|
|
592
|
+
if (!this.closing) await this.setStatus(sheater);
|
|
593
|
+
}
|
|
594
|
+
catch (err) { logger.error(`Error polling MasterTemp heater - ${err}`); }
|
|
595
|
+
finally {
|
|
596
|
+
this.suspendPolling = false; if (!this.closing) this._pollTimer = setTimeout(async () => {
|
|
597
|
+
try { await self.pollEquipmentAsync() } catch (err) { }
|
|
598
|
+
}, this.pollingInterval || 3000);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
public async setStatus(sheater: HeaterState): Promise<boolean> {
|
|
602
|
+
try {
|
|
603
|
+
let success = await new Promise<boolean>((resolve, reject) => {
|
|
604
|
+
let out = Outbound.create({
|
|
605
|
+
portId: this.heater.portId || 0,
|
|
606
|
+
protocol: Protocol.Heater,
|
|
607
|
+
source: 16,
|
|
608
|
+
dest: this.heater.address,
|
|
609
|
+
action: 112,
|
|
610
|
+
payload: [],
|
|
611
|
+
retries: 3, // We are going to try 4 times.
|
|
612
|
+
response: Response.create({ protocol: Protocol.Heater, action: 116 }),
|
|
613
|
+
onAbort: () => { },
|
|
614
|
+
onComplete: (err) => {
|
|
615
|
+
if (err) {
|
|
616
|
+
// If the MasterTemp is not responding we need to store that off but at this point we know none of the codes. If a 115 does
|
|
617
|
+
// come across this will be cleared by the processing of that message.
|
|
618
|
+
sheater.commStatus = sys.board.valueMaps.equipmentCommStatus.getValue('commerr');
|
|
619
|
+
state.equipment.messages.setMessageByCode(`heater:${sheater.id}:comms`, 'error', `Communication error with ${sheater.name}`);
|
|
620
|
+
resolve(false);
|
|
621
|
+
}
|
|
622
|
+
else { resolve(true); }
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
out.appendPayloadBytes(0, 11);
|
|
626
|
+
// If we have a startup delay we need to simply send 0 to the heater to make sure that it is off.
|
|
627
|
+
if (sheater.startupDelay)
|
|
628
|
+
out.setPayloadByte(0, 0);
|
|
629
|
+
else {
|
|
630
|
+
// The cooldown delay is a bit hard to figure out here since I think the heater does it on its own.
|
|
631
|
+
out.setPayloadByte(0, sheater.bodyId <= 2 ? sheater.bodyId : 0);
|
|
632
|
+
}
|
|
633
|
+
out.setPayloadByte(1, sys.bodies.getItemById(1).heatSetpoint || 0);
|
|
634
|
+
out.setPayloadByte(2, sys.bodies.getItemById(2).heatSetpoint || 0);
|
|
635
|
+
conn.queueSendMessage(out);
|
|
636
|
+
});
|
|
637
|
+
return success;
|
|
638
|
+
} catch (err) { logger.error(`Communication error with MasterTemp : ${err.message}`); }
|
|
639
|
+
}
|
|
640
|
+
public async closeAsync() {
|
|
641
|
+
try {
|
|
642
|
+
this.suspendPolling = true;
|
|
643
|
+
this.closing = true;
|
|
644
|
+
if (typeof this._pollTimer !== 'undefined' || this._pollTimer) clearTimeout(this._pollTimer);
|
|
645
|
+
this._pollTimer = null;
|
|
646
|
+
logger.info(`Closing Heater ${this.heater.name}`);
|
|
647
|
+
|
|
648
|
+
}
|
|
649
|
+
catch (err) { logger.error(`MasterTemp closeAsync: ${err.message}`); return Promise.reject(err); }
|
|
650
|
+
}
|
|
651
|
+
}
|