nodejs-poolcontroller 7.6.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.
Files changed (91) hide show
  1. package/.eslintrc.json +44 -44
  2. package/.github/ISSUE_TEMPLATE/1-bug-report.yml +84 -0
  3. package/.github/ISSUE_TEMPLATE/2-docs.md +12 -0
  4. package/.github/ISSUE_TEMPLATE/3-proposal.md +28 -0
  5. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  6. package/CONTRIBUTING.md +74 -74
  7. package/Changelog +220 -215
  8. package/Dockerfile +17 -17
  9. package/Gruntfile.js +40 -40
  10. package/LICENSE +661 -661
  11. package/README.md +191 -191
  12. package/app.ts +1 -1
  13. package/config/Config.ts +14 -0
  14. package/config/VersionCheck.ts +2 -2
  15. package/controller/Constants.ts +2 -1
  16. package/controller/Equipment.ts +2484 -2459
  17. package/controller/Errors.ts +180 -180
  18. package/controller/Lockouts.ts +502 -436
  19. package/controller/State.ts +106 -30
  20. package/controller/boards/AquaLinkBoard.ts +1000 -0
  21. package/controller/boards/BoardFactory.ts +49 -45
  22. package/controller/boards/EasyTouchBoard.ts +2859 -2653
  23. package/controller/boards/IntelliCenterBoard.ts +4198 -4230
  24. package/controller/boards/IntelliComBoard.ts +63 -63
  25. package/controller/boards/IntelliTouchBoard.ts +273 -241
  26. package/controller/boards/NixieBoard.ts +1728 -1675
  27. package/controller/boards/SystemBoard.ts +4925 -4697
  28. package/controller/comms/Comms.ts +442 -479
  29. package/controller/comms/messages/Messages.ts +171 -25
  30. package/controller/comms/messages/config/ChlorinatorMessage.ts +5 -2
  31. package/controller/comms/messages/config/CircuitGroupMessage.ts +0 -0
  32. package/controller/comms/messages/config/CircuitMessage.ts +1 -0
  33. package/controller/comms/messages/config/ConfigMessage.ts +0 -0
  34. package/controller/comms/messages/config/CoverMessage.ts +0 -0
  35. package/controller/comms/messages/config/CustomNameMessage.ts +30 -30
  36. package/controller/comms/messages/config/EquipmentMessage.ts +0 -0
  37. package/controller/comms/messages/config/ExternalMessage.ts +0 -0
  38. package/controller/comms/messages/config/FeatureMessage.ts +0 -0
  39. package/controller/comms/messages/config/GeneralMessage.ts +0 -0
  40. package/controller/comms/messages/config/HeaterMessage.ts +142 -10
  41. package/controller/comms/messages/config/IntellichemMessage.ts +0 -0
  42. package/controller/comms/messages/config/OptionsMessage.ts +4 -21
  43. package/controller/comms/messages/config/PumpMessage.ts +53 -35
  44. package/controller/comms/messages/config/RemoteMessage.ts +0 -0
  45. package/controller/comms/messages/config/ScheduleMessage.ts +350 -347
  46. package/controller/comms/messages/config/SecurityMessage.ts +0 -0
  47. package/controller/comms/messages/config/ValveMessage.ts +1 -1
  48. package/controller/comms/messages/status/ChlorinatorStateMessage.ts +38 -86
  49. package/controller/comms/messages/status/EquipmentStateMessage.ts +58 -22
  50. package/controller/comms/messages/status/HeaterStateMessage.ts +116 -86
  51. package/controller/comms/messages/status/IntelliChemStateMessage.ts +445 -445
  52. package/controller/comms/messages/status/IntelliValveStateMessage.ts +35 -35
  53. package/controller/comms/messages/status/PumpStateMessage.ts +23 -1
  54. package/controller/comms/messages/status/VersionMessage.ts +0 -0
  55. package/controller/nixie/Nixie.ts +162 -162
  56. package/controller/nixie/NixieEquipment.ts +103 -103
  57. package/controller/nixie/bodies/Body.ts +120 -120
  58. package/controller/nixie/bodies/Filter.ts +135 -135
  59. package/controller/nixie/chemistry/ChemController.ts +2511 -2498
  60. package/controller/nixie/chemistry/Chlorinator.ts +363 -314
  61. package/controller/nixie/circuits/Circuit.ts +261 -248
  62. package/controller/nixie/heaters/Heater.ts +650 -648
  63. package/controller/nixie/pumps/Pump.ts +906 -661
  64. package/controller/nixie/schedules/Schedule.ts +313 -257
  65. package/controller/nixie/valves/Valve.ts +170 -170
  66. package/defaultConfig.json +306 -286
  67. package/logger/DataLogger.ts +448 -448
  68. package/logger/Logger.ts +0 -0
  69. package/package.json +56 -56
  70. package/tsconfig.json +25 -25
  71. package/web/Server.ts +92 -47
  72. package/web/bindings/aqualinkD.json +505 -0
  73. package/web/bindings/influxDB.json +1051 -1021
  74. package/web/bindings/mqtt.json +702 -654
  75. package/web/bindings/mqttAlt.json +731 -684
  76. package/web/bindings/rulesManager.json +54 -54
  77. package/web/bindings/smartThings-Hubitat.json +31 -31
  78. package/web/bindings/valveRelays.json +20 -20
  79. package/web/bindings/vera.json +25 -25
  80. package/web/interfaces/baseInterface.ts +137 -136
  81. package/web/interfaces/httpInterface.ts +145 -124
  82. package/web/interfaces/influxInterface.ts +276 -245
  83. package/web/interfaces/mqttInterface.ts +535 -475
  84. package/web/services/config/Config.ts +39 -18
  85. package/web/services/config/ConfigSocket.ts +0 -0
  86. package/web/services/state/State.ts +10 -0
  87. package/web/services/state/StateSocket.ts +4 -4
  88. package/web/services/utilities/Utilities.ts +44 -42
  89. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -52
  90. package/config copy.json +0 -300
  91. package/issue_template.md +0 -52
@@ -1,248 +1,261 @@
1
- import { EquipmentNotFoundError, InvalidEquipmentDataError, InvalidEquipmentIdError, ParameterOutOfRangeError } from '../../Errors';
2
- import { utils, Timestamp } from '../../Constants';
3
- import { logger } from '../../../logger/Logger';
4
-
5
- import { NixieEquipment, NixieChildEquipment, NixieEquipmentCollection, INixieControlPanel } from "../NixieEquipment";
6
- import { Circuit, CircuitCollection, sys } from "../../../controller/Equipment";
7
- import { CircuitState, state, ICircuitState, } from "../../State";
8
- import { setTimeout, clearTimeout } from 'timers';
9
- import { NixieControlPanel } from '../Nixie';
10
- import { webApp, InterfaceServerResponse } from "../../../web/Server";
11
-
12
- export class NixieCircuitCollection extends NixieEquipmentCollection<NixieCircuit> {
13
- public pollingInterval: number = 2000;
14
- private _pollTimer: NodeJS.Timeout = null;
15
- public async deleteCircuitAsync(id: number) {
16
- try {
17
- for (let i = this.length - 1; i >= 0; i--) {
18
- let circ = this[i];
19
- if (circ.id === id) {
20
- await circ.closeAsync();
21
- this.splice(i, 1);
22
- }
23
- }
24
- } catch (err) { return Promise.reject(`Nixie Control Panel deleteCircuitAsync ${err.message}`); }
25
- }
26
- public async sendOnOffSequenceAsync(id: number, count: number | { isOn: boolean, timeout: number }[]) {
27
- try {
28
- let c: NixieCircuit = this.find(elem => elem.id === id) as NixieCircuit;
29
- if (typeof c === 'undefined') return Promise.reject(new Error(`NCP: Circuit ${id} could not be found to send sequence ${count}.`));
30
- await c.sendOnOffSequenceAsync(count);
31
-
32
- } catch (err) { return logger.error(`NCP: sendOnOffSequence: ${err.message}`); }
33
- }
34
- public async setCircuitStateAsync(cstate: ICircuitState, val: boolean) {
35
- try {
36
- let c: NixieCircuit = this.find(elem => elem.id === cstate.id) as NixieCircuit;
37
- if (typeof c === 'undefined') return Promise.reject(new Error(`NCP: Circuit ${cstate.id}-${cstate.name} could not be found to set the state to ${val}.`));
38
- await c.setCircuitStateAsync(cstate, val);
39
- }
40
- catch (err) { return logger.error(`NCP: setCircuitStateAsync ${cstate.id}-${cstate.name}: ${err.message}`); }
41
- }
42
- public async setCircuitAsync(circuit: Circuit, data: any) {
43
- // By the time we get here we know that we are in control and this is a REMChem.
44
- try {
45
- let c: NixieCircuit = this.find(elem => elem.id === circuit.id) as NixieCircuit;
46
- if (typeof c === 'undefined') {
47
- circuit.master = 1;
48
- c = new NixieCircuit(this.controlPanel, circuit);
49
- this.push(c);
50
- await c.setCircuitAsync(data);
51
- logger.debug(`NixieController: A circuit was not found for id #${circuit.id} creating circuit`);
52
- }
53
- else {
54
- await c.setCircuitAsync(data);
55
- }
56
- }
57
- catch (err) { logger.error(`setCircuitAsync: ${err.message}`); return Promise.reject(err); }
58
- }
59
- public async checkCircuitEggTimerExpirationAsync(cstate: ICircuitState) {
60
- try {
61
- let c: NixieCircuit = this.find(elem => elem.id === cstate.id) as NixieCircuit;
62
- await c.checkCircuitEggTimerExpirationAsync(cstate);
63
- } catch (err) { logger.error(`NCP: Error synching circuit states: ${err}`); }
64
- }
65
- public async initAsync(circuits: CircuitCollection) {
66
- try {
67
- for (let i = 0; i < circuits.length; i++) {
68
- let circuit = circuits.getItemByIndex(i);
69
- if (circuit.master === 1) {
70
- if (typeof this.find(elem => elem.id === circuit.id) === 'undefined') {
71
- logger.info(`Initializing Nixie circuit ${circuit.name}`);
72
- let ncircuit = new NixieCircuit(this.controlPanel, circuit);
73
- this.push(ncircuit);
74
- }
75
- }
76
- }
77
- }
78
- catch (err) { return Promise.reject(logger.error(`NixieController: Circuit initAsync: ${err.message}`)); }
79
- }
80
- public async closeAsync() {
81
- try {
82
- for (let i = this.length - 1; i >= 0; i--) {
83
- try {
84
- await this[i].closeAsync();
85
- this.splice(i, 1);
86
- } catch (err) { logger.error(`Error stopping Nixie Circuit ${err}`); }
87
- }
88
-
89
- } catch (err) { } // Don't bail if we have an errror.
90
- }
91
-
92
- public async initCircuitAsync(circuit: Circuit): Promise<NixieCircuit> {
93
- try {
94
- let c: NixieCircuit = this.find(elem => elem.id === circuit.id) as NixieCircuit;
95
- if (typeof c === 'undefined') {
96
- c = new NixieCircuit(this.controlPanel, circuit);
97
- this.push(c);
98
- }
99
- return c;
100
- } catch (err) { logger.error(`initCircuitAsync: ${err.message}`); return Promise.reject(err); }
101
- }
102
- public async pollCircuitsAsync() {
103
- let self = this;
104
- try {
105
- if (typeof this._pollTimer !== 'undefined' || this._pollTimer) clearTimeout(this._pollTimer);
106
- this._pollTimer = null;
107
- let success = false;
108
-
109
- } catch (err) { logger.error(`Error polling circuits: ${err.message}`); return Promise.reject(err); }
110
- finally { this._pollTimer = setTimeout(async () => await self.pollCircuitsAsync(), this.pollingInterval || 10000); }
111
- }
112
- }
113
- export class NixieCircuit extends NixieEquipment {
114
- public circuit: Circuit;
115
- private _sequencing = false;
116
- private scheduled = false;
117
- private timeOn: Timestamp;
118
- constructor(ncp: INixieControlPanel, circuit: Circuit) {
119
- super(ncp);
120
- this.circuit = circuit;
121
- // Clear out the delays.
122
- let cstate = state.circuits.getItemById(circuit.id);
123
- cstate.startDelay = false;
124
- cstate.stopDelay = false;
125
- }
126
- public get id(): number { return typeof this.circuit !== 'undefined' ? this.circuit.id : -1; }
127
- public get eggTimerOff(): Timestamp { return typeof this.timeOn !== 'undefined' && !this.circuit.dontStop ? this.timeOn.clone().addMinutes(this.circuit.eggTimer) : undefined; }
128
- public async setCircuitAsync(data: any) {
129
- try {
130
- let circuit = this.circuit;
131
- }
132
- catch (err) { logger.error(`Nixie setCircuitAsync: ${err.message}`); return Promise.reject(err); }
133
- }
134
- public async sendOnOffSequenceAsync(count: number | { isOn: boolean, timeout: number }[], timeout?:number): Promise<InterfaceServerResponse> {
135
- try {
136
- this._sequencing = true;
137
- let arr = [];
138
- if (typeof count === 'number') {
139
- let t = typeof timeout === 'undefined' ? 100 : timeout;
140
- arr.push({ isOn: false, timeout: t }); // This may not be needed but we always need to start from off.
141
- //[{ isOn: true, timeout: 1000 }, { isOn: false, timeout: 1000 }]
142
- for (let i = 0; i < count; i++) {
143
- arr.push({ isOn: true, timeout: t });
144
- if (i < count - 1) arr.push({ isOn: false, timeout: t });
145
- }
146
- }
147
- else arr = count;
148
- // The documentation for IntelliBrite is incorrect. The sequence below will give us Party mode.
149
- // Party mode:2
150
- // Start: Off
151
- // On
152
- // Off
153
- // On
154
- // According to the docs this is the sequence they lay out.
155
- // Party mode:2
156
- // Start: On
157
- // Off
158
- // On
159
- // Off
160
- // On
161
-
162
- let res = await NixieEquipment.putDeviceService(this.circuit.connectionId, `/state/device/${this.circuit.deviceBinding}`, arr, 60000);
163
- return res;
164
- } catch (err) { logger.error(`Nixie: Error sending circuit sequence ${this.id}: ${count}`); }
165
- finally { this._sequencing = false; }
166
- }
167
- public async setThemeAsync(cstate: ICircuitState, theme: number): Promise<InterfaceServerResponse> {
168
- try {
169
-
170
-
171
-
172
- return new InterfaceServerResponse(200, 'Sucess');
173
- } catch (err) { logger.error(`Nixie: Error setting light theme ${cstate.id}-${cstate.name} to ${theme}`); }
174
- }
175
- public async setCircuitStateAsync(cstate: ICircuitState, val: boolean, scheduled: boolean = false): Promise<InterfaceServerResponse> {
176
- try {
177
- if (val !== cstate.isOn) {
178
- logger.info(`NCP: Setting Circuit ${cstate.name} to ${val}`);
179
- if (cstate.isOn && val) {
180
- // We are already on so lets check the egg timer and shut it off if it has expired.
181
- let eggOff = this.eggTimerOff;
182
- if (typeof eggOff !== 'undefined' && eggOff.getTime() <= new Date().getTime()) val = false;
183
- }
184
- // Check to see if we should be on by poking the schedules.
185
- }
186
- if (utils.isNullOrEmpty(this.circuit.connectionId) || utils.isNullOrEmpty(this.circuit.deviceBinding)) {
187
- sys.board.circuits.setEndTime(sys.circuits.getInterfaceById(cstate.id), cstate, val);
188
- cstate.isOn = val;
189
- return new InterfaceServerResponse(200, 'Success');
190
- }
191
- if (this._sequencing) return new InterfaceServerResponse(200, 'Success');
192
- let res = await NixieEquipment.putDeviceService(this.circuit.connectionId, `/state/device/${this.circuit.deviceBinding}`, { isOn: val, latch: val ? 10000 : undefined });
193
- if (res.status.code === 200) {
194
- sys.board.circuits.setEndTime(sys.circuits.getInterfaceById(cstate.id), cstate, val);
195
- // Set this up so we can process our egg timer.
196
- //if (!cstate.isOn && val) { cstate.startTime = this.timeOn = new Timestamp(); }
197
- //else if (!val) cstate.startTime = this.timeOn = undefined;
198
- cstate.isOn = val;
199
- }
200
- return res;
201
- } catch (err) { logger.error(`Nixie: Error setting circuit state ${cstate.id}-${cstate.name} to ${val}`); }
202
- }
203
- public async checkCircuitEggTimerExpirationAsync(cstate: ICircuitState) {
204
- // if circuit end time is past current time, either the schedule is finished
205
- // (this should already be turned off) or the egg timer has expired
206
- try {
207
- if (!cstate.isActive || !cstate.isOn) return;
208
- if (typeof cstate.endTime !== 'undefined') {
209
- if (cstate.endTime.toDate() < new Timestamp().toDate()) {
210
- await sys.board.circuits.setCircuitStateAsync(cstate.id, false);
211
- cstate.emitEquipmentChange();
212
- }
213
- }
214
- } catch (err) { logger.error(`Error syncing circuit: ${err}`); }
215
- }
216
- private async checkHardwareStatusAsync(connectionId: string, deviceBinding: string) {
217
- try {
218
- let dev = await NixieEquipment.getDeviceService(connectionId, `/status/device/${deviceBinding}`);
219
- return dev;
220
- } catch (err) { logger.error(`Nixie Circuit checkHardwareStatusAsync: ${err.message}`); return { hasFault: true } }
221
- }
222
- public async validateSetupAsync(circuit: Circuit, cstate: CircuitState) {
223
- try {
224
- if (typeof circuit.connectionId !== 'undefined' && circuit.connectionId !== ''
225
- && typeof circuit.deviceBinding !== 'undefined' && circuit.deviceBinding !== '') {
226
- try {
227
- let stat = await this.checkHardwareStatusAsync(circuit.connectionId, circuit.deviceBinding);
228
- // If we have a status check the return.
229
- cstate.commStatus = stat.hasFault ? 1 : 0;
230
- } catch (err) { cstate.commStatus = 1; }
231
- }
232
- else
233
- cstate.commStatus = 0;
234
- // The validation will be different if the circuit is on or not. So lets get that information.
235
- } catch (err) { logger.error(`Nixie Error checking Circuit Hardware ${this.circuit.name}: ${err.message}`); cstate.commStatus = 1; return Promise.reject(err); }
236
- }
237
- public async closeAsync() {
238
- try {
239
- let cstate = state.circuits.getItemById(this.circuit.id);
240
- cstate.stopDelay = false;
241
- cstate.startDelay = false;
242
- await this.setCircuitStateAsync(cstate, false);
243
- cstate.emitEquipmentChange();
244
- }
245
- catch (err) { logger.error(`Nixie Circuit closeAsync: ${err.message}`); return Promise.reject(err); }
246
- }
247
- public logData(filename: string, data: any) { this.controlPanel.logData(filename, data); }
248
- }
1
+ import { EquipmentNotFoundError, InvalidEquipmentDataError, InvalidEquipmentIdError, ParameterOutOfRangeError } from '../../Errors';
2
+ import { utils, Timestamp } from '../../Constants';
3
+ import { logger } from '../../../logger/Logger';
4
+
5
+ import { NixieEquipment, NixieChildEquipment, NixieEquipmentCollection, INixieControlPanel } from "../NixieEquipment";
6
+ import { Circuit, CircuitCollection, sys } from "../../../controller/Equipment";
7
+ import { CircuitState, state, ICircuitState, } from "../../State";
8
+ import { setTimeout, clearTimeout } from 'timers';
9
+ import { NixieControlPanel } from '../Nixie';
10
+ import { webApp, InterfaceServerResponse } from "../../../web/Server";
11
+ import { delayMgr } from '../../../controller/Lockouts';
12
+
13
+ export class NixieCircuitCollection extends NixieEquipmentCollection<NixieCircuit> {
14
+ public pollingInterval: number = 2000;
15
+ private _pollTimer: NodeJS.Timeout = null;
16
+ public async deleteCircuitAsync(id: number) {
17
+ try {
18
+ for (let i = this.length - 1; i >= 0; i--) {
19
+ let circ = this[i];
20
+ if (circ.id === id) {
21
+ await circ.closeAsync();
22
+ this.splice(i, 1);
23
+ }
24
+ }
25
+ } catch (err) { return Promise.reject(`Nixie Control Panel deleteCircuitAsync ${err.message}`); }
26
+ }
27
+ public async sendOnOffSequenceAsync(id: number, count: number | { isOn: boolean, timeout: number }[]) {
28
+ try {
29
+ let c: NixieCircuit = this.find(elem => elem.id === id) as NixieCircuit;
30
+ if (typeof c === 'undefined') return Promise.reject(new Error(`NCP: Circuit ${id} could not be found to send sequence ${count}.`));
31
+ await c.sendOnOffSequenceAsync(count);
32
+
33
+ } catch (err) { return logger.error(`NCP: sendOnOffSequence: ${err.message}`); }
34
+ }
35
+ public async setCircuitStateAsync(cstate: ICircuitState, val: boolean) {
36
+ try {
37
+ let c: NixieCircuit = this.find(elem => elem.id === cstate.id) as NixieCircuit;
38
+ if (typeof c === 'undefined') return Promise.reject(new Error(`NCP: Circuit ${cstate.id}-${cstate.name} could not be found to set the state to ${val}.`));
39
+ await c.setCircuitStateAsync(cstate, val);
40
+ }
41
+ catch (err) { return logger.error(`NCP: setCircuitStateAsync ${cstate.id}-${cstate.name}: ${err.message}`); }
42
+ }
43
+ public async setCircuitAsync(circuit: Circuit, data: any) {
44
+ // By the time we get here we know that we are in control and this is a REMChem.
45
+ try {
46
+ let c: NixieCircuit = this.find(elem => elem.id === circuit.id) as NixieCircuit;
47
+ if (typeof c === 'undefined') {
48
+ circuit.master = 1;
49
+ c = new NixieCircuit(this.controlPanel, circuit);
50
+ this.push(c);
51
+ await c.setCircuitAsync(data);
52
+ logger.debug(`NixieController: A circuit was not found for id #${circuit.id} creating circuit`);
53
+ }
54
+ else {
55
+ await c.setCircuitAsync(data);
56
+ }
57
+ }
58
+ catch (err) { logger.error(`setCircuitAsync: ${err.message}`); return Promise.reject(err); }
59
+ }
60
+ public async checkCircuitEggTimerExpirationAsync(cstate: ICircuitState) {
61
+ try {
62
+ let c: NixieCircuit = this.find(elem => elem.id === cstate.id) as NixieCircuit;
63
+ await c.checkCircuitEggTimerExpirationAsync(cstate);
64
+ } catch (err) { logger.error(`NCP: Error synching circuit states: ${err}`); }
65
+ }
66
+ public async initAsync(circuits: CircuitCollection) {
67
+ try {
68
+ for (let i = 0; i < circuits.length; i++) {
69
+ let circuit = circuits.getItemByIndex(i);
70
+ if (circuit.master === 1) {
71
+ if (typeof this.find(elem => elem.id === circuit.id) === 'undefined') {
72
+ logger.info(`Initializing Nixie circuit ${circuit.name}`);
73
+ let ncircuit = new NixieCircuit(this.controlPanel, circuit);
74
+ this.push(ncircuit);
75
+ }
76
+ }
77
+ }
78
+ }
79
+ catch (err) { return Promise.reject(logger.error(`NixieController: Circuit initAsync: ${err.message}`)); }
80
+ }
81
+ public async closeAsync() {
82
+ try {
83
+ for (let i = this.length - 1; i >= 0; i--) {
84
+ try {
85
+ await this[i].closeAsync();
86
+ this.splice(i, 1);
87
+ } catch (err) { logger.error(`Error stopping Nixie Circuit ${err}`); }
88
+ }
89
+
90
+ } catch (err) { } // Don't bail if we have an errror.
91
+ }
92
+
93
+ public async initCircuitAsync(circuit: Circuit): Promise<NixieCircuit> {
94
+ try {
95
+ let c: NixieCircuit = this.find(elem => elem.id === circuit.id) as NixieCircuit;
96
+ if (typeof c === 'undefined') {
97
+ c = new NixieCircuit(this.controlPanel, circuit);
98
+ this.push(c);
99
+ }
100
+ return c;
101
+ } catch (err) { logger.error(`initCircuitAsync: ${err.message}`); return Promise.reject(err); }
102
+ }
103
+ public async pollCircuitsAsync() {
104
+ let self = this;
105
+ try {
106
+ if (typeof this._pollTimer !== 'undefined' || this._pollTimer) clearTimeout(this._pollTimer);
107
+ this._pollTimer = null;
108
+ let success = false;
109
+
110
+ } catch (err) { logger.error(`Error polling circuits: ${err.message}`); return Promise.reject(err); }
111
+ finally { this._pollTimer = setTimeout(async () => await self.pollCircuitsAsync(), this.pollingInterval || 10000); }
112
+ }
113
+ }
114
+ export class NixieCircuit extends NixieEquipment {
115
+ public circuit: Circuit;
116
+ private _sequencing = false;
117
+ private scheduled = false;
118
+ private timeOn: Timestamp;
119
+ constructor(ncp: INixieControlPanel, circuit: Circuit) {
120
+ super(ncp);
121
+ this.circuit = circuit;
122
+ // Clear out the delays.
123
+ let cstate = state.circuits.getItemById(circuit.id);
124
+ cstate.startDelay = false;
125
+ cstate.stopDelay = false;
126
+ }
127
+ public get id(): number { return typeof this.circuit !== 'undefined' ? this.circuit.id : -1; }
128
+ public get eggTimerOff(): Timestamp { return typeof this.timeOn !== 'undefined' && !this.circuit.dontStop ? this.timeOn.clone().addMinutes(this.circuit.eggTimer) : undefined; }
129
+ public async setCircuitAsync(data: any) {
130
+ try {
131
+ let circuit = this.circuit;
132
+ }
133
+ catch (err) { logger.error(`Nixie setCircuitAsync: ${err.message}`); return Promise.reject(err); }
134
+ }
135
+ public async sendOnOffSequenceAsync(count: number | { isOn: boolean, timeout: number }[], timeout?:number): Promise<InterfaceServerResponse> {
136
+ try {
137
+ this._sequencing = true;
138
+ let arr = [];
139
+ if (typeof count === 'number') {
140
+ let t = typeof timeout === 'undefined' ? 100 : timeout;
141
+ arr.push({ isOn: false, timeout: t }); // This may not be needed but we always need to start from off.
142
+ //[{ isOn: true, timeout: 1000 }, { isOn: false, timeout: 1000 }]
143
+ for (let i = 0; i < count; i++) {
144
+ arr.push({ isOn: true, timeout: t });
145
+ if (i < count - 1) arr.push({ isOn: false, timeout: t });
146
+ }
147
+ }
148
+ else arr = count;
149
+ // The documentation for IntelliBrite is incorrect. The sequence below will give us Party mode.
150
+ // Party mode:2
151
+ // Start: Off
152
+ // On
153
+ // Off
154
+ // On
155
+ // According to the docs this is the sequence they lay out.
156
+ // Party mode:2
157
+ // Start: On
158
+ // Off
159
+ // On
160
+ // Off
161
+ // On
162
+
163
+ let res = await NixieEquipment.putDeviceService(this.circuit.connectionId, `/state/device/${this.circuit.deviceBinding}`, arr, 60000);
164
+ return res;
165
+ } catch (err) { logger.error(`Nixie: Error sending circuit sequence ${this.id}: ${count}`); }
166
+ finally { this._sequencing = false; }
167
+ }
168
+ public async setThemeAsync(cstate: ICircuitState, theme: number): Promise<InterfaceServerResponse> {
169
+ try {
170
+
171
+
172
+
173
+ return new InterfaceServerResponse(200, 'Sucess');
174
+ } catch (err) { logger.error(`Nixie: Error setting light theme ${cstate.id}-${cstate.name} to ${theme}`); }
175
+ }
176
+ public async setCircuitStateAsync(cstate: ICircuitState, val: boolean, scheduled: boolean = false): Promise<InterfaceServerResponse> {
177
+ try {
178
+ if (val !== cstate.isOn) {
179
+ logger.info(`NCP: Setting Circuit ${cstate.name} to ${val}`);
180
+ if (cstate.isOn && val) {
181
+ // We are already on so lets check the egg timer and shut it off if it has expired.
182
+ let eggOff = this.eggTimerOff;
183
+ if (typeof eggOff !== 'undefined' && eggOff.getTime() <= new Date().getTime()) val = false;
184
+ }
185
+ // Check to see if we should be on by poking the schedules.
186
+ }
187
+ if (utils.isNullOrEmpty(this.circuit.connectionId) || utils.isNullOrEmpty(this.circuit.deviceBinding)) {
188
+ if (val && val !== cstate.isOn){
189
+ sys.board.circuits.setEndTime(sys.circuits.getInterfaceById(cstate.id), cstate, val);
190
+ }
191
+ else if (!val){
192
+ if (cstate.manualPriorityActive) delayMgr.cancelManualPriorityDelay(cstate.id);
193
+ cstate.manualPriorityActive = false; // if the delay was previously cancelled, still need to turn this off
194
+ }
195
+ cstate.isOn = val;
196
+ return new InterfaceServerResponse(200, 'Success');
197
+ }
198
+ if (this._sequencing) return new InterfaceServerResponse(200, 'Success');
199
+ let res = await NixieEquipment.putDeviceService(this.circuit.connectionId, `/state/device/${this.circuit.deviceBinding}`, { isOn: val, latch: val ? 10000 : undefined });
200
+ if (res.status.code === 200) {
201
+ // Set this up so we can process our egg timer.
202
+ //if (!cstate.isOn && val) { cstate.startTime = this.timeOn = new Timestamp(); }
203
+ //else if (!val) cstate.startTime = this.timeOn = undefined;
204
+ if (val && val !== cstate.isOn){
205
+ sys.board.circuits.setEndTime(sys.circuits.getInterfaceById(cstate.id), cstate, val);
206
+ }
207
+ else if (!val){
208
+ delayMgr.cancelManualPriorityDelays();
209
+ cstate.manualPriorityActive = false; // if the delay was previously cancelled, still need to turn this off
210
+ }
211
+ cstate.isOn = val;
212
+ }
213
+ return res;
214
+ } catch (err) { logger.error(`Nixie: Error setting circuit state ${cstate.id}-${cstate.name} to ${val}`); }
215
+ }
216
+ public async checkCircuitEggTimerExpirationAsync(cstate: ICircuitState) {
217
+ // if circuit end time is past current time, either the schedule is finished
218
+ // (this should already be turned off) or the egg timer has expired
219
+ try {
220
+ if (!cstate.isActive || !cstate.isOn) return;
221
+ if (typeof cstate.endTime !== 'undefined') {
222
+ if (cstate.endTime.toDate() < new Timestamp().toDate()) {
223
+ await sys.board.circuits.setCircuitStateAsync(cstate.id, false);
224
+ cstate.emitEquipmentChange();
225
+ }
226
+ }
227
+ } catch (err) { logger.error(`Error syncing circuit: ${err}`); }
228
+ }
229
+ private async checkHardwareStatusAsync(connectionId: string, deviceBinding: string) {
230
+ try {
231
+ let dev = await NixieEquipment.getDeviceService(connectionId, `/status/device/${deviceBinding}`);
232
+ return dev;
233
+ } catch (err) { logger.error(`Nixie Circuit checkHardwareStatusAsync: ${err.message}`); return { hasFault: true } }
234
+ }
235
+ public async validateSetupAsync(circuit: Circuit, cstate: CircuitState) {
236
+ try {
237
+ if (typeof circuit.connectionId !== 'undefined' && circuit.connectionId !== ''
238
+ && typeof circuit.deviceBinding !== 'undefined' && circuit.deviceBinding !== '') {
239
+ try {
240
+ let stat = await this.checkHardwareStatusAsync(circuit.connectionId, circuit.deviceBinding);
241
+ // If we have a status check the return.
242
+ cstate.commStatus = stat.hasFault ? 1 : 0;
243
+ } catch (err) { cstate.commStatus = 1; }
244
+ }
245
+ else
246
+ cstate.commStatus = 0;
247
+ // The validation will be different if the circuit is on or not. So lets get that information.
248
+ } catch (err) { logger.error(`Nixie Error checking Circuit Hardware ${this.circuit.name}: ${err.message}`); cstate.commStatus = 1; return Promise.reject(err); }
249
+ }
250
+ public async closeAsync() {
251
+ try {
252
+ let cstate = state.circuits.getItemById(this.circuit.id);
253
+ cstate.stopDelay = false;
254
+ cstate.startDelay = false;
255
+ await this.setCircuitStateAsync(cstate, false);
256
+ cstate.emitEquipmentChange();
257
+ }
258
+ catch (err) { logger.error(`Nixie Circuit closeAsync: ${err.message}`); return Promise.reject(err); }
259
+ }
260
+ public logData(filename: string, data: any) { this.controlPanel.logData(filename, data); }
261
+ }