nodejs-poolcontroller 7.6.0 → 7.6.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.
Files changed (85) hide show
  1. package/.eslintrc.json +44 -44
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +52 -52
  3. package/CONTRIBUTING.md +74 -74
  4. package/Changelog +215 -215
  5. package/Dockerfile +17 -17
  6. package/Gruntfile.js +40 -40
  7. package/LICENSE +661 -661
  8. package/README.md +191 -186
  9. package/app.ts +0 -0
  10. package/config/Config.ts +24 -2
  11. package/config/VersionCheck.ts +27 -12
  12. package/config copy.json +299 -299
  13. package/controller/Constants.ts +0 -0
  14. package/controller/Equipment.ts +2459 -2405
  15. package/controller/Errors.ts +180 -180
  16. package/controller/Lockouts.ts +436 -422
  17. package/controller/State.ts +51 -26
  18. package/controller/boards/BoardFactory.ts +45 -45
  19. package/controller/boards/EasyTouchBoard.ts +2653 -2537
  20. package/controller/boards/IntelliCenterBoard.ts +4230 -4034
  21. package/controller/boards/IntelliComBoard.ts +63 -63
  22. package/controller/boards/IntelliTouchBoard.ts +241 -241
  23. package/controller/boards/NixieBoard.ts +1675 -1660
  24. package/controller/boards/SystemBoard.ts +4697 -4463
  25. package/controller/comms/Comms.ts +138 -1
  26. package/controller/comms/messages/Messages.ts +3 -5
  27. package/controller/comms/messages/config/ChlorinatorMessage.ts +1 -1
  28. package/controller/comms/messages/config/CircuitGroupMessage.ts +0 -0
  29. package/controller/comms/messages/config/CircuitMessage.ts +0 -0
  30. package/controller/comms/messages/config/ConfigMessage.ts +0 -0
  31. package/controller/comms/messages/config/CoverMessage.ts +0 -0
  32. package/controller/comms/messages/config/CustomNameMessage.ts +30 -30
  33. package/controller/comms/messages/config/EquipmentMessage.ts +0 -0
  34. package/controller/comms/messages/config/ExternalMessage.ts +9 -7
  35. package/controller/comms/messages/config/FeatureMessage.ts +0 -0
  36. package/controller/comms/messages/config/GeneralMessage.ts +0 -0
  37. package/controller/comms/messages/config/HeaterMessage.ts +0 -20
  38. package/controller/comms/messages/config/IntellichemMessage.ts +0 -0
  39. package/controller/comms/messages/config/OptionsMessage.ts +25 -1
  40. package/controller/comms/messages/config/PumpMessage.ts +0 -0
  41. package/controller/comms/messages/config/RemoteMessage.ts +0 -0
  42. package/controller/comms/messages/config/ScheduleMessage.ts +347 -342
  43. package/controller/comms/messages/config/SecurityMessage.ts +0 -0
  44. package/controller/comms/messages/config/ValveMessage.ts +0 -0
  45. package/controller/comms/messages/status/ChlorinatorStateMessage.ts +0 -0
  46. package/controller/comms/messages/status/EquipmentStateMessage.ts +1 -1
  47. package/controller/comms/messages/status/HeaterStateMessage.ts +86 -86
  48. package/controller/comms/messages/status/IntelliChemStateMessage.ts +445 -397
  49. package/controller/comms/messages/status/IntelliValveStateMessage.ts +35 -35
  50. package/controller/comms/messages/status/PumpStateMessage.ts +0 -0
  51. package/controller/comms/messages/status/VersionMessage.ts +0 -0
  52. package/controller/nixie/Nixie.ts +162 -162
  53. package/controller/nixie/NixieEquipment.ts +103 -103
  54. package/controller/nixie/bodies/Body.ts +120 -120
  55. package/controller/nixie/bodies/Filter.ts +135 -135
  56. package/controller/nixie/chemistry/ChemController.ts +2498 -2398
  57. package/controller/nixie/chemistry/Chlorinator.ts +314 -314
  58. package/controller/nixie/circuits/Circuit.ts +248 -245
  59. package/controller/nixie/heaters/Heater.ts +648 -600
  60. package/controller/nixie/pumps/Pump.ts +661 -661
  61. package/controller/nixie/schedules/Schedule.ts +257 -257
  62. package/controller/nixie/valves/Valve.ts +170 -170
  63. package/defaultConfig.json +286 -286
  64. package/issue_template.md +51 -51
  65. package/logger/DataLogger.ts +448 -448
  66. package/logger/Logger.ts +0 -0
  67. package/package.json +56 -56
  68. package/tsconfig.json +25 -25
  69. package/web/Server.ts +2 -2
  70. package/web/bindings/influxDB.json +1021 -981
  71. package/web/bindings/mqtt.json +654 -654
  72. package/web/bindings/mqttAlt.json +684 -684
  73. package/web/bindings/rulesManager.json +54 -54
  74. package/web/bindings/smartThings-Hubitat.json +31 -31
  75. package/web/bindings/valveRelays.json +20 -20
  76. package/web/bindings/vera.json +25 -25
  77. package/web/interfaces/baseInterface.ts +136 -136
  78. package/web/interfaces/httpInterface.ts +124 -124
  79. package/web/interfaces/influxInterface.ts +245 -241
  80. package/web/interfaces/mqttInterface.ts +475 -475
  81. package/web/services/config/Config.ts +10 -108
  82. package/web/services/config/ConfigSocket.ts +0 -0
  83. package/web/services/state/State.ts +71 -4
  84. package/web/services/state/StateSocket.ts +0 -0
  85. package/web/services/utilities/Utilities.ts +42 -42
@@ -1,245 +1,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
-
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) {
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, timeout?:number): Promise<InterfaceServerResponse> {
135
- try {
136
- this._sequencing = true;
137
- let arr = [];
138
- let t = typeof timeout === 'undefined' ? 100 : timeout;
139
- arr.push({ isOn: false, timeout: t }); // This may not be needed but we always need to start from off.
140
- //[{ isOn: true, timeout: 1000 }, { isOn: false, timeout: 1000 }]
141
- for (let i = 0; i < count; i++) {
142
- arr.push({ isOn: true, timeout: t });
143
- if(i < count - 1) arr.push({ isOn: false, timeout: t });
144
- }
145
- // The documentation for IntelliBrite is incorrect. The sequence below will give us Party mode.
146
- // Party mode:2
147
- // Start: Off
148
- // On
149
- // Off
150
- // On
151
- // According to the docs this is the sequence they lay out.
152
- // Party mode:2
153
- // Start: On
154
- // Off
155
- // On
156
- // Off
157
- // On
158
-
159
- let res = await NixieEquipment.putDeviceService(this.circuit.connectionId, `/state/device/${this.circuit.deviceBinding}`, arr, 60000);
160
- return res;
161
- } catch (err) { logger.error(`Nixie: Error sending circuit sequence ${this.id}: ${count}`); }
162
- finally { this._sequencing = false; }
163
- }
164
- public async setThemeAsync(cstate: ICircuitState, theme: number): Promise<InterfaceServerResponse> {
165
- try {
166
-
167
-
168
-
169
- return new InterfaceServerResponse(200, 'Sucess');
170
- } catch (err) { logger.error(`Nixie: Error setting light theme ${cstate.id}-${cstate.name} to ${theme}`); }
171
- }
172
- public async setCircuitStateAsync(cstate: ICircuitState, val: boolean, scheduled: boolean = false): Promise<InterfaceServerResponse> {
173
- try {
174
- if (val !== cstate.isOn) {
175
- logger.info(`NCP: Setting Circuit ${cstate.name} to ${val}`);
176
- if (cstate.isOn && val) {
177
- // We are already on so lets check the egg timer and shut it off if it has expired.
178
- let eggOff = this.eggTimerOff;
179
- if (typeof eggOff !== 'undefined' && eggOff.getTime() <= new Date().getTime()) val = false;
180
- }
181
- // Check to see if we should be on by poking the schedules.
182
- }
183
- if (utils.isNullOrEmpty(this.circuit.connectionId) || utils.isNullOrEmpty(this.circuit.deviceBinding)) {
184
- sys.board.circuits.setEndTime(sys.circuits.getInterfaceById(cstate.id), cstate, val);
185
- cstate.isOn = val;
186
- return new InterfaceServerResponse(200, 'Success');
187
- }
188
- if (this._sequencing) return new InterfaceServerResponse(200, 'Success');
189
- let res = await NixieEquipment.putDeviceService(this.circuit.connectionId, `/state/device/${this.circuit.deviceBinding}`, { isOn: val, latch: val ? 10000 : undefined });
190
- if (res.status.code === 200) {
191
- sys.board.circuits.setEndTime(sys.circuits.getInterfaceById(cstate.id), cstate, val);
192
- // Set this up so we can process our egg timer.
193
- //if (!cstate.isOn && val) { cstate.startTime = this.timeOn = new Timestamp(); }
194
- //else if (!val) cstate.startTime = this.timeOn = undefined;
195
- cstate.isOn = val;
196
- }
197
- return res;
198
- } catch (err) { logger.error(`Nixie: Error setting circuit state ${cstate.id}-${cstate.name} to ${val}`); }
199
- }
200
- public async checkCircuitEggTimerExpirationAsync(cstate: ICircuitState) {
201
- // if circuit end time is past current time, either the schedule is finished
202
- // (this should already be turned off) or the egg timer has expired
203
- try {
204
- if (!cstate.isActive || !cstate.isOn) return;
205
- if (typeof cstate.endTime !== 'undefined') {
206
- if (cstate.endTime.toDate() < new Timestamp().toDate()) {
207
- await sys.board.circuits.setCircuitStateAsync(cstate.id, false);
208
- cstate.emitEquipmentChange();
209
- }
210
- }
211
- } catch (err) { logger.error(`Error syncing circuit: ${err}`); }
212
- }
213
- private async checkHardwareStatusAsync(connectionId: string, deviceBinding: string) {
214
- try {
215
- let dev = await NixieEquipment.getDeviceService(connectionId, `/status/device/${deviceBinding}`);
216
- return dev;
217
- } catch (err) { logger.error(`Nixie Circuit checkHardwareStatusAsync: ${err.message}`); return { hasFault: true } }
218
- }
219
- public async validateSetupAsync(circuit: Circuit, cstate: CircuitState) {
220
- try {
221
- if (typeof circuit.connectionId !== 'undefined' && circuit.connectionId !== ''
222
- && typeof circuit.deviceBinding !== 'undefined' && circuit.deviceBinding !== '') {
223
- try {
224
- let stat = await this.checkHardwareStatusAsync(circuit.connectionId, circuit.deviceBinding);
225
- // If we have a status check the return.
226
- cstate.commStatus = stat.hasFault ? 1 : 0;
227
- } catch (err) { cstate.commStatus = 1; }
228
- }
229
- else
230
- cstate.commStatus = 0;
231
- // The validation will be different if the circuit is on or not. So lets get that information.
232
- } catch (err) { logger.error(`Nixie Error checking Circuit Hardware ${this.circuit.name}: ${err.message}`); cstate.commStatus = 1; return Promise.reject(err); }
233
- }
234
- public async closeAsync() {
235
- try {
236
- let cstate = state.circuits.getItemById(this.circuit.id);
237
- cstate.stopDelay = false;
238
- cstate.startDelay = false;
239
- await this.setCircuitStateAsync(cstate, false);
240
- cstate.emitEquipmentChange();
241
- }
242
- catch (err) { logger.error(`Nixie Circuit closeAsync: ${err.message}`); return Promise.reject(err); }
243
- }
244
- public logData(filename: string, data: any) { this.controlPanel.logData(filename, data); }
245
- }
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
+ }