nodejs-poolcontroller 8.1.2 → 8.4.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 (106) hide show
  1. package/.eslintrc.json +36 -36
  2. package/.github/ISSUE_TEMPLATE/1-bug-report.yml +84 -84
  3. package/.github/ISSUE_TEMPLATE/2-docs.md +12 -12
  4. package/.github/ISSUE_TEMPLATE/3-proposal.md +28 -28
  5. package/.github/ISSUE_TEMPLATE/config.yml +8 -8
  6. package/.github/copilot-instructions.md +63 -0
  7. package/.github/workflows/ghcr-publish.yml +67 -0
  8. package/AGENTS.md +597 -0
  9. package/CONTRIBUTING.md +74 -74
  10. package/Changelog +292 -257
  11. package/Dockerfile +62 -19
  12. package/Gruntfile.js +40 -40
  13. package/LICENSE +661 -661
  14. package/README.md +318 -191
  15. package/anslq25/MessagesMock.ts +221 -221
  16. package/anslq25/boards/MockBoardFactory.ts +49 -49
  17. package/anslq25/boards/MockEasyTouchBoard.ts +696 -696
  18. package/anslq25/boards/MockSystemBoard.ts +216 -216
  19. package/anslq25/chemistry/MockChlorinator.ts +98 -98
  20. package/anslq25/pumps/MockPump.ts +83 -83
  21. package/app.ts +115 -115
  22. package/config/Config.ts +57 -7
  23. package/config/VersionCheck.ts +63 -35
  24. package/controller/Constants.ts +809 -805
  25. package/controller/Equipment.ts +2688 -2664
  26. package/controller/Errors.ts +181 -181
  27. package/controller/Lockouts.ts +549 -549
  28. package/controller/State.ts +3738 -3690
  29. package/controller/boards/AquaLinkBoard.ts +1003 -1003
  30. package/controller/boards/BoardFactory.ts +53 -53
  31. package/controller/boards/EasyTouchBoard.ts +3202 -3202
  32. package/controller/boards/IntelliCenterBoard.ts +4393 -3899
  33. package/controller/boards/IntelliComBoard.ts +69 -69
  34. package/controller/boards/IntelliTouchBoard.ts +382 -382
  35. package/controller/boards/NixieBoard.ts +1944 -1929
  36. package/controller/boards/SunTouchBoard.ts +400 -400
  37. package/controller/boards/SystemBoard.ts +5268 -5268
  38. package/controller/comms/Comms.ts +1272 -1214
  39. package/controller/comms/ScreenLogic.ts +1665 -1665
  40. package/controller/comms/messages/Messages.ts +1433 -1243
  41. package/controller/comms/messages/config/ChlorinatorMessage.ts +5 -0
  42. package/controller/comms/messages/config/CircuitGroupMessage.ts +0 -0
  43. package/controller/comms/messages/config/CircuitMessage.ts +0 -0
  44. package/controller/comms/messages/config/ConfigMessage.ts +6 -0
  45. package/controller/comms/messages/config/CoverMessage.ts +0 -0
  46. package/controller/comms/messages/config/CustomNameMessage.ts +31 -31
  47. package/controller/comms/messages/config/EquipmentMessage.ts +216 -210
  48. package/controller/comms/messages/config/ExternalMessage.ts +96 -10
  49. package/controller/comms/messages/config/FeatureMessage.ts +0 -0
  50. package/controller/comms/messages/config/GeneralMessage.ts +0 -0
  51. package/controller/comms/messages/config/HeaterMessage.ts +0 -0
  52. package/controller/comms/messages/config/IntellichemMessage.ts +0 -0
  53. package/controller/comms/messages/config/OptionsMessage.ts +194 -174
  54. package/controller/comms/messages/config/PumpMessage.ts +0 -0
  55. package/controller/comms/messages/config/RemoteMessage.ts +0 -0
  56. package/controller/comms/messages/config/ScheduleMessage.ts +401 -390
  57. package/controller/comms/messages/config/SecurityMessage.ts +0 -0
  58. package/controller/comms/messages/config/ValveMessage.ts +0 -0
  59. package/controller/comms/messages/status/ChlorinatorStateMessage.ts +0 -0
  60. package/controller/comms/messages/status/EquipmentStateMessage.ts +1158 -822
  61. package/controller/comms/messages/status/HeaterStateMessage.ts +135 -135
  62. package/controller/comms/messages/status/IntelliChemStateMessage.ts +448 -448
  63. package/controller/comms/messages/status/IntelliValveStateMessage.ts +36 -36
  64. package/controller/comms/messages/status/PumpStateMessage.ts +0 -0
  65. package/controller/comms/messages/status/RegalModbusStateMessage.ts +411 -0
  66. package/controller/comms/messages/status/VersionMessage.ts +103 -41
  67. package/controller/nixie/Nixie.ts +173 -173
  68. package/controller/nixie/NixieEquipment.ts +104 -104
  69. package/controller/nixie/bodies/Body.ts +120 -120
  70. package/controller/nixie/bodies/Filter.ts +135 -135
  71. package/controller/nixie/chemistry/ChemController.ts +2724 -2724
  72. package/controller/nixie/chemistry/ChemDoser.ts +806 -806
  73. package/controller/nixie/chemistry/Chlorinator.ts +367 -367
  74. package/controller/nixie/circuits/Circuit.ts +478 -478
  75. package/controller/nixie/heaters/Heater.ts +834 -834
  76. package/controller/nixie/pumps/Pump.ts +1194 -996
  77. package/controller/nixie/schedules/Schedule.ts +401 -401
  78. package/controller/nixie/valves/Valve.ts +170 -170
  79. package/defaultConfig.json +352 -347
  80. package/docker-compose.yml +32 -0
  81. package/logger/DataLogger.ts +448 -448
  82. package/logger/Logger.ts +448 -436
  83. package/package.json +58 -60
  84. package/sendSocket.js +32 -32
  85. package/tsconfig.json +25 -25
  86. package/types/express-multer.d.ts +32 -0
  87. package/web/Server.ts +1937 -1927
  88. package/web/bindings/aqualinkD.json +559 -559
  89. package/web/bindings/influxDB.json +1066 -1066
  90. package/web/bindings/mqtt.json +721 -721
  91. package/web/bindings/mqttAlt.json +746 -746
  92. package/web/bindings/rulesManager.json +54 -54
  93. package/web/bindings/smartThings-Hubitat.json +31 -31
  94. package/web/bindings/valveRelays.json +20 -20
  95. package/web/bindings/vera.json +25 -25
  96. package/web/interfaces/baseInterface.ts +188 -188
  97. package/web/interfaces/httpInterface.ts +148 -148
  98. package/web/interfaces/influxInterface.ts +283 -283
  99. package/web/interfaces/mqttInterface.ts +695 -695
  100. package/web/interfaces/ruleInterface.ts +101 -87
  101. package/web/services/config/Config.ts +1063 -1053
  102. package/web/services/config/ConfigSocket.ts +0 -0
  103. package/web/services/state/State.ts +0 -0
  104. package/web/services/state/StateSocket.ts +0 -0
  105. package/web/services/utilities/Utilities.ts +233 -233
  106. package/.github/workflows/docker-publish-njsPC-linux.yml +0 -50
@@ -1,217 +1,217 @@
1
- /* nodejs-poolController. An application to control pool equipment.
2
- Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021, 2022.
3
- Russell Goldin, tagyoureit. russ.goldin@gmail.com
4
-
5
- This program is free software: you can redistribute it and/or modify
6
- it under the terms of the GNU Affero General Public License as
7
- published by the Free Software Foundation, either version 3 of the
8
- License, or (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU Affero General Public License for more details.
14
-
15
- You should have received a copy of the GNU Affero General Public License
16
- along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- import { logger } from "../../logger/Logger";
20
- import { setTimeout as setTimeoutSync } from 'timers';
21
- import { Inbound, Outbound, Protocol } from "../../controller/comms/messages/Messages";
22
- import { byteValueMap, byteValueMaps, SystemBoard } from "../../controller/boards/SystemBoard";
23
- import { Anslq25, PoolSystem, sys } from "../../controller/Equipment";
24
- import { ControllerType, utils } from "../../controller/Constants";
25
- import { conn } from "../../controller/comms/Comms";
26
- import { MockEasyTouch } from "./MockEasyTouchBoard";
27
-
28
- export class MockSystemBoard {
29
- public valueMaps: byteValueMaps = new byteValueMaps();
30
- protected _statusTimer: NodeJS.Timeout;
31
- protected _statusCheckRef: number = 0;
32
- protected _statusInterval: number = 5000;
33
- constructor(system: PoolSystem) {
34
- // sys.anslq25.portId = 0; // pass this in.
35
- setTimeout(() => {
36
- this.processStatusAsync().then(() => { });
37
- }, 5000);
38
- }
39
- public expansionBoards: byteValueMap = new byteValueMap();
40
- public get statusInterval(): number { return this._statusInterval };
41
- public system: MockSystemCommands = new MockSystemCommands(this);
42
- public circuits: MockCircuitCommands = new MockCircuitCommands(this);
43
- public schedules: MockScheduleCommands = new MockScheduleCommands(this);
44
- public heaters: MockHeaterCommands = new MockHeaterCommands(this);
45
- public valves: MockValveCommands = new MockValveCommands(this);
46
- public remotes: MockRemoteCommands = new MockRemoteCommands(this);
47
- public pumps: MockPumpCommands = new MockPumpCommands(this);
48
- public static convertOutbound(outboundMsg: Outbound) { };
49
- public async sendAsync(msg: Outbound){
50
- return await msg.sendAsync();
51
- // is the controller on a real/physical port or a mock port?
52
- /* let port = conn.findPortById(sys.anslq25.portId);
53
- if (port.mock) {
54
- let inbound = new Inbound();
55
- inbound.protocol = msg.protocol;
56
- inbound.header = msg.header;
57
- inbound.payload = msg.payload;
58
- inbound.term = msg.term;
59
- inbound.portId = msg.portId;
60
- // don't need to wait for packet to process
61
- setTimeout(()=>{conn.sendMockPacket(inbound)}, 10);
62
- return Promise.resolve();
63
- }
64
- else {
65
- return await msg.sendAsync();
66
- } */
67
- }
68
- public process(msg: Inbound): Outbound { return new Outbound(Protocol.Broadcast,0,0,0,[]); }
69
- protected killStatusCheck() {
70
- if (typeof this._statusTimer !== 'undefined' && this._statusTimer) clearTimeout(this._statusTimer);
71
- this._statusTimer = undefined;
72
- this._statusCheckRef = 0;
73
- }
74
- public suspendStatus(bSuspend: boolean) {
75
- // The way status suspension works is by using a reference value that is incremented and decremented
76
- // the status check is only performed when the reference value is 0. So suspending the status check 3 times and un-suspending
77
- // it 2 times will still result in the status check being suspended. This method also ensures the reference never falls below 0.
78
- if (bSuspend) this._statusCheckRef++;
79
- else this._statusCheckRef = Math.max(0, this._statusCheckRef - 1);
80
- if (this._statusCheckRef > 1) logger.verbose(`Suspending ANSLQ25 status check: ${bSuspend} -- ${this._statusCheckRef}`);
81
- }
82
- public async setAnslq25Async(data: any): Promise<Anslq25> {
83
- let self = this;
84
- try {
85
- this.suspendStatus(true);
86
- // if (typeof data.isActive === 'undefined') return Promise.reject(`Mock System Board: No isActive flag provided.`);
87
- if (typeof data.anslq25portId === 'undefined') return Promise.reject(new Error(`Mock System Board: No portId provided.`));
88
- if (typeof data.anslq25ControllerType === 'undefined') return Promise.reject(new Error(`Mock System Board: No controller type provided.`));
89
- if (typeof data.anslq25model === 'undefined') return Promise.reject(new Error(`Mock System Board: No model provided.`));
90
- //for (let i = 1; i <= )
91
- let isActive = true; // utils.makeBool(data.isActive);
92
- let portId = parseInt(data.anslq25portId, 10);
93
- let port = conn.findPortById(portId);
94
- if (typeof port === 'undefined') return Promise.reject(new Error(`Mock System Board: Invalid portId provided.`));
95
- if (portId === 0) return Promise.reject(new Error(`Please choose a port other than the primary port.`));
96
- let mockControllerType = data.anslq25ControllerType;
97
- let model = parseInt(data.anslq25model, 10);
98
- let broadcastComms = data.broadcastComms;
99
- if (typeof broadcastComms === 'undefined') return Promise.reject(new Error(`A value for broadcast comms must be provided.`));
100
- sys.anslq25.portId = portId;
101
- sys.anslq25.broadcastComms = broadcastComms;
102
- switch (mockControllerType) {
103
- case ControllerType.EasyTouch:{
104
- sys.anslq25ControllerType = ControllerType.EasyTouch;
105
- // (sys.anslq25Board as MockEasyTouch).initExpansionModules(model);
106
- break;
107
- }
108
- default: {
109
- logger.warn(`No ANSLQ25 Mock Board definiton yet for: ${mockControllerType}`);
110
- return Promise.reject(new Error(`No ANSLQ25 Mock Board definiton yet for: ${mockControllerType}`));
111
- }
112
- }
113
- sys.anslq25.isActive = isActive;
114
- sys.anslq25.model = model;
115
-
116
- } catch (err) {
117
- logger.error(`Error changing port id: ${err.message}`);
118
- }
119
- finally {
120
- this.suspendStatus(false);
121
- this._statusTimer = setTimeoutSync(async () => await self.processStatusAsync(), this.statusInterval);
122
- }
123
- }
124
- public async deleteAnslq25Async(data: any) {
125
- try {
126
-
127
- this.killStatusCheck();
128
- this.closeAsync();
129
- sys.anslq25.isActive = false;
130
- sys.anslq25.portId = undefined;
131
- sys.anslq25.model = undefined;
132
- sys.anslq25ControllerType = ControllerType.None;
133
- }
134
- catch (err){
135
-
136
- }
137
- finally {
138
- this.suspendStatus(false);
139
- }
140
-
141
- }
142
-
143
- public async processStatusAsync() {
144
- let self = this;
145
- try {
146
- if (this._statusCheckRef > 0) return;
147
- this.suspendStatus(true);
148
-
149
- await sys.anslq25Board.system.sendStatusAsync();
150
- }
151
- catch (err) {
152
- logger.error(`Error running mock processStatusAsync: ${err}`);
153
- }
154
- finally {
155
- this.suspendStatus(false);
156
- if (sys.anslq25.isActive){
157
- if (this.statusInterval > 0) this._statusTimer = setTimeoutSync(async () => await self.processStatusAsync(), this.statusInterval);
158
- }
159
-
160
- }
161
- }
162
- // public async setPortId(portId: number) {
163
- // let self = this;
164
- // try {
165
- // this.suspendStatus(true);
166
- // sys.anslq25.portId = portId;
167
-
168
- // } catch (err) {
169
- // logger.error(`Error changing port id: ${err.message}`);
170
- // }
171
- // finally {
172
- // this.suspendStatus(false);
173
- // this._statusTimer = setTimeoutSync(async () => await self.processStatusAsync(), this.statusInterval);
174
- // }
175
- // }
176
- public async closeAsync() {
177
- try {
178
- }
179
- catch (err) { logger.error(err); }
180
- }
181
- }
182
- export class MockBoardCommands {
183
- protected mockBoard: MockSystemBoard = null;
184
- constructor(parent: MockSystemBoard) { this.mockBoard = parent; }
185
- }
186
- export class MockSystemCommands extends MockBoardCommands {
187
- public sendAck(msg:Inbound) { };
188
- public async processDateTimeAsync(msg: Inbound){ };
189
- public async processCustomNameAsync(msg: Inbound){ };
190
- public async processSettingsAsync(msg: Inbound){ };
191
- public async sendStatusAsync() { };
192
- }
193
-
194
- export class MockCircuitCommands extends MockBoardCommands {
195
- public async processCircuitAsync( msg: Inbound) { };
196
- public async processLightGroupAsync( msg: Inbound) { };
197
- }
198
- export class MockScheduleCommands extends MockBoardCommands {
199
- public async processScheduleAsync( msg: Inbound) { };
200
- }
201
- export class MockHeaterCommands extends MockBoardCommands {
202
- public async processHeatModesAsync(msg: Inbound) { };
203
- public async processHeaterConfigAsync(msg: Inbound) { };
204
- }
205
- export class MockValveCommands extends MockBoardCommands {
206
- public async processValveOptionsAsync(msg: Inbound) { };
207
- public async processValveAssignmentsAsync(msg: Inbound) { };
208
- }
209
- export class MockRemoteCommands extends MockBoardCommands {
210
- public async processIS4IS10RemoteAsync(msg: Inbound) { };
211
- public async processQuickTouchRemoteAsync(msg: Inbound) { };
212
- public async processSpaCommandRemoteAsync(msg: Inbound) { };
213
- }
214
- export class MockPumpCommands extends MockBoardCommands {
215
- public async processPumpConfigAsync(msg: Inbound) { };
216
- public async processHighSpeedCircuitsAsync(msg: Inbound) { };
1
+ /* nodejs-poolController. An application to control pool equipment.
2
+ Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021, 2022.
3
+ Russell Goldin, tagyoureit. russ.goldin@gmail.com
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Affero General Public License as
7
+ published by the Free Software Foundation, either version 3 of the
8
+ License, or (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Affero General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Affero General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ import { logger } from "../../logger/Logger";
20
+ import { setTimeout as setTimeoutSync } from 'timers';
21
+ import { Inbound, Outbound, Protocol } from "../../controller/comms/messages/Messages";
22
+ import { byteValueMap, byteValueMaps, SystemBoard } from "../../controller/boards/SystemBoard";
23
+ import { Anslq25, PoolSystem, sys } from "../../controller/Equipment";
24
+ import { ControllerType, utils } from "../../controller/Constants";
25
+ import { conn } from "../../controller/comms/Comms";
26
+ import { MockEasyTouch } from "./MockEasyTouchBoard";
27
+
28
+ export class MockSystemBoard {
29
+ public valueMaps: byteValueMaps = new byteValueMaps();
30
+ protected _statusTimer: NodeJS.Timeout;
31
+ protected _statusCheckRef: number = 0;
32
+ protected _statusInterval: number = 5000;
33
+ constructor(system: PoolSystem) {
34
+ // sys.anslq25.portId = 0; // pass this in.
35
+ setTimeout(() => {
36
+ this.processStatusAsync().then(() => { });
37
+ }, 5000);
38
+ }
39
+ public expansionBoards: byteValueMap = new byteValueMap();
40
+ public get statusInterval(): number { return this._statusInterval };
41
+ public system: MockSystemCommands = new MockSystemCommands(this);
42
+ public circuits: MockCircuitCommands = new MockCircuitCommands(this);
43
+ public schedules: MockScheduleCommands = new MockScheduleCommands(this);
44
+ public heaters: MockHeaterCommands = new MockHeaterCommands(this);
45
+ public valves: MockValveCommands = new MockValveCommands(this);
46
+ public remotes: MockRemoteCommands = new MockRemoteCommands(this);
47
+ public pumps: MockPumpCommands = new MockPumpCommands(this);
48
+ public static convertOutbound(outboundMsg: Outbound) { };
49
+ public async sendAsync(msg: Outbound){
50
+ return await msg.sendAsync();
51
+ // is the controller on a real/physical port or a mock port?
52
+ /* let port = conn.findPortById(sys.anslq25.portId);
53
+ if (port.mock) {
54
+ let inbound = new Inbound();
55
+ inbound.protocol = msg.protocol;
56
+ inbound.header = msg.header;
57
+ inbound.payload = msg.payload;
58
+ inbound.term = msg.term;
59
+ inbound.portId = msg.portId;
60
+ // don't need to wait for packet to process
61
+ setTimeout(()=>{conn.sendMockPacket(inbound)}, 10);
62
+ return Promise.resolve();
63
+ }
64
+ else {
65
+ return await msg.sendAsync();
66
+ } */
67
+ }
68
+ public process(msg: Inbound): Outbound { return new Outbound(Protocol.Broadcast,0,0,0,[]); }
69
+ protected killStatusCheck() {
70
+ if (typeof this._statusTimer !== 'undefined' && this._statusTimer) clearTimeout(this._statusTimer);
71
+ this._statusTimer = undefined;
72
+ this._statusCheckRef = 0;
73
+ }
74
+ public suspendStatus(bSuspend: boolean) {
75
+ // The way status suspension works is by using a reference value that is incremented and decremented
76
+ // the status check is only performed when the reference value is 0. So suspending the status check 3 times and un-suspending
77
+ // it 2 times will still result in the status check being suspended. This method also ensures the reference never falls below 0.
78
+ if (bSuspend) this._statusCheckRef++;
79
+ else this._statusCheckRef = Math.max(0, this._statusCheckRef - 1);
80
+ if (this._statusCheckRef > 1) logger.verbose(`Suspending ANSLQ25 status check: ${bSuspend} -- ${this._statusCheckRef}`);
81
+ }
82
+ public async setAnslq25Async(data: any): Promise<Anslq25> {
83
+ let self = this;
84
+ try {
85
+ this.suspendStatus(true);
86
+ // if (typeof data.isActive === 'undefined') return Promise.reject(`Mock System Board: No isActive flag provided.`);
87
+ if (typeof data.anslq25portId === 'undefined') return Promise.reject(new Error(`Mock System Board: No portId provided.`));
88
+ if (typeof data.anslq25ControllerType === 'undefined') return Promise.reject(new Error(`Mock System Board: No controller type provided.`));
89
+ if (typeof data.anslq25model === 'undefined') return Promise.reject(new Error(`Mock System Board: No model provided.`));
90
+ //for (let i = 1; i <= )
91
+ let isActive = true; // utils.makeBool(data.isActive);
92
+ let portId = parseInt(data.anslq25portId, 10);
93
+ let port = conn.findPortById(portId);
94
+ if (typeof port === 'undefined') return Promise.reject(new Error(`Mock System Board: Invalid portId provided.`));
95
+ if (portId === 0) return Promise.reject(new Error(`Please choose a port other than the primary port.`));
96
+ let mockControllerType = data.anslq25ControllerType;
97
+ let model = parseInt(data.anslq25model, 10);
98
+ let broadcastComms = data.broadcastComms;
99
+ if (typeof broadcastComms === 'undefined') return Promise.reject(new Error(`A value for broadcast comms must be provided.`));
100
+ sys.anslq25.portId = portId;
101
+ sys.anslq25.broadcastComms = broadcastComms;
102
+ switch (mockControllerType) {
103
+ case ControllerType.EasyTouch:{
104
+ sys.anslq25ControllerType = ControllerType.EasyTouch;
105
+ // (sys.anslq25Board as MockEasyTouch).initExpansionModules(model);
106
+ break;
107
+ }
108
+ default: {
109
+ logger.warn(`No ANSLQ25 Mock Board definiton yet for: ${mockControllerType}`);
110
+ return Promise.reject(new Error(`No ANSLQ25 Mock Board definiton yet for: ${mockControllerType}`));
111
+ }
112
+ }
113
+ sys.anslq25.isActive = isActive;
114
+ sys.anslq25.model = model;
115
+
116
+ } catch (err) {
117
+ logger.error(`Error changing port id: ${err.message}`);
118
+ }
119
+ finally {
120
+ this.suspendStatus(false);
121
+ this._statusTimer = setTimeoutSync(async () => await self.processStatusAsync(), this.statusInterval);
122
+ }
123
+ }
124
+ public async deleteAnslq25Async(data: any) {
125
+ try {
126
+
127
+ this.killStatusCheck();
128
+ this.closeAsync();
129
+ sys.anslq25.isActive = false;
130
+ sys.anslq25.portId = undefined;
131
+ sys.anslq25.model = undefined;
132
+ sys.anslq25ControllerType = ControllerType.None;
133
+ }
134
+ catch (err){
135
+
136
+ }
137
+ finally {
138
+ this.suspendStatus(false);
139
+ }
140
+
141
+ }
142
+
143
+ public async processStatusAsync() {
144
+ let self = this;
145
+ try {
146
+ if (this._statusCheckRef > 0) return;
147
+ this.suspendStatus(true);
148
+
149
+ await sys.anslq25Board.system.sendStatusAsync();
150
+ }
151
+ catch (err) {
152
+ logger.error(`Error running mock processStatusAsync: ${err}`);
153
+ }
154
+ finally {
155
+ this.suspendStatus(false);
156
+ if (sys.anslq25.isActive){
157
+ if (this.statusInterval > 0) this._statusTimer = setTimeoutSync(async () => await self.processStatusAsync(), this.statusInterval);
158
+ }
159
+
160
+ }
161
+ }
162
+ // public async setPortId(portId: number) {
163
+ // let self = this;
164
+ // try {
165
+ // this.suspendStatus(true);
166
+ // sys.anslq25.portId = portId;
167
+
168
+ // } catch (err) {
169
+ // logger.error(`Error changing port id: ${err.message}`);
170
+ // }
171
+ // finally {
172
+ // this.suspendStatus(false);
173
+ // this._statusTimer = setTimeoutSync(async () => await self.processStatusAsync(), this.statusInterval);
174
+ // }
175
+ // }
176
+ public async closeAsync() {
177
+ try {
178
+ }
179
+ catch (err) { logger.error(err); }
180
+ }
181
+ }
182
+ export class MockBoardCommands {
183
+ protected mockBoard: MockSystemBoard = null;
184
+ constructor(parent: MockSystemBoard) { this.mockBoard = parent; }
185
+ }
186
+ export class MockSystemCommands extends MockBoardCommands {
187
+ public sendAck(msg:Inbound) { };
188
+ public async processDateTimeAsync(msg: Inbound){ };
189
+ public async processCustomNameAsync(msg: Inbound){ };
190
+ public async processSettingsAsync(msg: Inbound){ };
191
+ public async sendStatusAsync() { };
192
+ }
193
+
194
+ export class MockCircuitCommands extends MockBoardCommands {
195
+ public async processCircuitAsync( msg: Inbound) { };
196
+ public async processLightGroupAsync( msg: Inbound) { };
197
+ }
198
+ export class MockScheduleCommands extends MockBoardCommands {
199
+ public async processScheduleAsync( msg: Inbound) { };
200
+ }
201
+ export class MockHeaterCommands extends MockBoardCommands {
202
+ public async processHeatModesAsync(msg: Inbound) { };
203
+ public async processHeaterConfigAsync(msg: Inbound) { };
204
+ }
205
+ export class MockValveCommands extends MockBoardCommands {
206
+ public async processValveOptionsAsync(msg: Inbound) { };
207
+ public async processValveAssignmentsAsync(msg: Inbound) { };
208
+ }
209
+ export class MockRemoteCommands extends MockBoardCommands {
210
+ public async processIS4IS10RemoteAsync(msg: Inbound) { };
211
+ public async processQuickTouchRemoteAsync(msg: Inbound) { };
212
+ public async processSpaCommandRemoteAsync(msg: Inbound) { };
213
+ }
214
+ export class MockPumpCommands extends MockBoardCommands {
215
+ public async processPumpConfigAsync(msg: Inbound) { };
216
+ public async processHighSpeedCircuitsAsync(msg: Inbound) { };
217
217
  }
@@ -1,99 +1,99 @@
1
- import { logger } from "../../logger/Logger";
2
- import { Inbound, Outbound } from "../../controller/comms/messages/Messages";
3
- import { conn } from "../../controller/comms/Comms";
4
-
5
- export class MockChlorinator {
6
- constructor(){}
7
-
8
- public process(inbound: Inbound){
9
- let response: Outbound = Outbound.create({
10
- portId: inbound.portId,
11
- protocol: inbound.protocol,
12
- dest: 0
13
- });
14
-
15
- switch (inbound.action){
16
- case 0: // Set control OCP->Chlorinator: [16,2,80,0][0][98,16,3]
17
- this.chlorSetControl(inbound, response);
18
- break;
19
- case 17: // OCP->Chlorinator set output. [16,2,80,17][15][130,16,3]
20
- this.chlorSetOutput(inbound, response);
21
- break;
22
- case 19: // iChlor keep alive(?) [16, 2, 80, 19][117, 16, 3]
23
- this.chlorKeepAlive(inbound, response);
24
- break;
25
- case 20: // OCP->Chlorinator Get model [16,2,80,20][0][118,16,3]
26
- this.chlorGetModel(inbound, response);
27
- break;
28
- default:
29
- logger.info(`No mock chlorinator response for ${inbound.toShortPacket()} `);
30
- }
31
- }
32
-
33
- public async chlorSetControl(inbound: Inbound, response: Outbound){
34
- /*
35
- {"port":0,"id":42633,"valid":true,"dir":"out","proto":"chlorinator","pkt":[[],[], [16,2,80,0], [0],[98,16,3]],"ts":"2022-07-19T21:45:59.959-0700"}
36
- {"port":0,"id":42634,"valid":true,"dir":"in","proto":"chlorinator","for":[42633],"pkt":[[],[],[16,2,0,1],[0,0],[19,16,3]],"ts": "2022-07-19T21:45:59.999-0700"} */
37
- try {
38
-
39
- response.action = 1;
40
- response.appendPayloadBytes(0, 2);
41
- await response.sendAsync()
42
- }
43
- catch (err){
44
- logger.error(`Error sending mock chlor packet ${response.toPacket}`);
45
- }
46
- }
47
- public chlorSetOutput(inbound: Inbound, response: Outbound){
48
- /*
49
- {"port":0,"id":42639,"valid":true,"dir":"out","proto":"chlorinator","pkt":[[],[], [16,2,80,17], [100],[215,16,3]],"ts":"2022-07-19T21:46:00.302-0700"}
50
- {"port":0,"id":42640,"valid":true,"dir":"in","proto":"chlorinator","for":[42639],"pkt":[[],[],[16,2,0,18],[78,128],[242,16,3]],"ts": "2022-07-19T21:46:00.341-0700"} */
51
- // Simulate a response from the chlorinator (inbound message)
52
- const payload = [Math.floor(this.random(90-56, true))+56, 128];
53
- const header = [16, 2, 0, 18];
54
- const term = [242, 16, 3];
55
- let responseMsg = new Inbound();
56
- responseMsg.protocol = inbound.protocol;
57
- responseMsg.portId = inbound.portId;
58
- responseMsg.header = header;
59
- responseMsg.payload = payload;
60
- responseMsg.term = term;
61
- // The Inbound class will parse header/payload/action/source/dest automatically
62
- setTimeout(() => {
63
- let port = conn.findPortById(inbound.portId);
64
- if (port) {
65
- port.pushIn(Buffer.from(responseMsg.toPacket()));
66
- }
67
- }, 50);
68
- }
69
- public chlorKeepAlive(inbound: Inbound, response: Outbound){
70
- /*
71
- {"port":0,"id":42647,"valid":true,"dir":"out","proto":"chlorinator","pkt":[[],[], [16,2,80,19],[117,16,3]],"ts":"2022-07-19T21:46:00.645-0700"}
72
- {"port":0,"id":42648,"valid":true,"dir":"in","proto":"chlorinator","for":[42647],"pkt":[[],[],[16,2,0,20],[0],[118,16,3]],"ts":"2022-07-19T21:46:00.700-0700"} */
73
- response.action = 20;
74
- response.appendPayloadBytes(0, 1);
75
- response.setPayloadByte(0, 0);
76
- conn.queueSendMessage(response);
77
- }
78
-
79
- public chlorGetModel(inbound: Inbound, response: Outbound){
80
- /*
81
- {"port":0,"id":42645,"valid":true,"dir":"out","proto":"chlorinator","pkt":[[],[], [16,2,80,20], [0],[118,16,3]],"ts":"2022-07-19T21:46:00.645-0700"}
82
- {"port":0,"id":42646,"valid":true,"dir":"in","proto":"chlorinator","for":[42645],"pkt":[[],[],[16,2,0,3],[0,73,110,116,101,108,108,105,99,104,108,111,114,45,45,54,48],[190,16,3]],"ts": "2022-07-19T21:46:00.700-0700"} */
83
- response.action = 3;
84
- response.appendPayloadBytes(0, 17);
85
- response.insertPayloadString(1, 'INTELLICHLOR--60');
86
- conn.queueSendMessage(response);
87
- }
88
-
89
- private random(bounds: number, onlyPositive: boolean = false){
90
- let rand = Math.random() * bounds;
91
- if (!onlyPositive) {
92
- if (Math.random()<=.5) rand = rand * -1;
93
- }
94
- return rand;
95
- }
96
-
97
- }
98
-
1
+ import { logger } from "../../logger/Logger";
2
+ import { Inbound, Outbound } from "../../controller/comms/messages/Messages";
3
+ import { conn } from "../../controller/comms/Comms";
4
+
5
+ export class MockChlorinator {
6
+ constructor(){}
7
+
8
+ public process(inbound: Inbound){
9
+ let response: Outbound = Outbound.create({
10
+ portId: inbound.portId,
11
+ protocol: inbound.protocol,
12
+ dest: 0
13
+ });
14
+
15
+ switch (inbound.action){
16
+ case 0: // Set control OCP->Chlorinator: [16,2,80,0][0][98,16,3]
17
+ this.chlorSetControl(inbound, response);
18
+ break;
19
+ case 17: // OCP->Chlorinator set output. [16,2,80,17][15][130,16,3]
20
+ this.chlorSetOutput(inbound, response);
21
+ break;
22
+ case 19: // iChlor keep alive(?) [16, 2, 80, 19][117, 16, 3]
23
+ this.chlorKeepAlive(inbound, response);
24
+ break;
25
+ case 20: // OCP->Chlorinator Get model [16,2,80,20][0][118,16,3]
26
+ this.chlorGetModel(inbound, response);
27
+ break;
28
+ default:
29
+ logger.info(`No mock chlorinator response for ${inbound.toShortPacket()} `);
30
+ }
31
+ }
32
+
33
+ public async chlorSetControl(inbound: Inbound, response: Outbound){
34
+ /*
35
+ {"port":0,"id":42633,"valid":true,"dir":"out","proto":"chlorinator","pkt":[[],[], [16,2,80,0], [0],[98,16,3]],"ts":"2022-07-19T21:45:59.959-0700"}
36
+ {"port":0,"id":42634,"valid":true,"dir":"in","proto":"chlorinator","for":[42633],"pkt":[[],[],[16,2,0,1],[0,0],[19,16,3]],"ts": "2022-07-19T21:45:59.999-0700"} */
37
+ try {
38
+
39
+ response.action = 1;
40
+ response.appendPayloadBytes(0, 2);
41
+ await response.sendAsync()
42
+ }
43
+ catch (err){
44
+ logger.error(`Error sending mock chlor packet ${response.toPacket}`);
45
+ }
46
+ }
47
+ public chlorSetOutput(inbound: Inbound, response: Outbound){
48
+ /*
49
+ {"port":0,"id":42639,"valid":true,"dir":"out","proto":"chlorinator","pkt":[[],[], [16,2,80,17], [100],[215,16,3]],"ts":"2022-07-19T21:46:00.302-0700"}
50
+ {"port":0,"id":42640,"valid":true,"dir":"in","proto":"chlorinator","for":[42639],"pkt":[[],[],[16,2,0,18],[78,128],[242,16,3]],"ts": "2022-07-19T21:46:00.341-0700"} */
51
+ // Simulate a response from the chlorinator (inbound message)
52
+ const payload = [Math.floor(this.random(90-56, true))+56, 128];
53
+ const header = [16, 2, 0, 18];
54
+ const term = [242, 16, 3];
55
+ let responseMsg = new Inbound();
56
+ responseMsg.protocol = inbound.protocol;
57
+ responseMsg.portId = inbound.portId;
58
+ responseMsg.header = header;
59
+ responseMsg.payload = payload;
60
+ responseMsg.term = term;
61
+ // The Inbound class will parse header/payload/action/source/dest automatically
62
+ setTimeout(() => {
63
+ let port = conn.findPortById(inbound.portId);
64
+ if (port) {
65
+ port.pushIn(Buffer.from(responseMsg.toPacket()));
66
+ }
67
+ }, 50);
68
+ }
69
+ public chlorKeepAlive(inbound: Inbound, response: Outbound){
70
+ /*
71
+ {"port":0,"id":42647,"valid":true,"dir":"out","proto":"chlorinator","pkt":[[],[], [16,2,80,19],[117,16,3]],"ts":"2022-07-19T21:46:00.645-0700"}
72
+ {"port":0,"id":42648,"valid":true,"dir":"in","proto":"chlorinator","for":[42647],"pkt":[[],[],[16,2,0,20],[0],[118,16,3]],"ts":"2022-07-19T21:46:00.700-0700"} */
73
+ response.action = 20;
74
+ response.appendPayloadBytes(0, 1);
75
+ response.setPayloadByte(0, 0);
76
+ conn.queueSendMessage(response);
77
+ }
78
+
79
+ public chlorGetModel(inbound: Inbound, response: Outbound){
80
+ /*
81
+ {"port":0,"id":42645,"valid":true,"dir":"out","proto":"chlorinator","pkt":[[],[], [16,2,80,20], [0],[118,16,3]],"ts":"2022-07-19T21:46:00.645-0700"}
82
+ {"port":0,"id":42646,"valid":true,"dir":"in","proto":"chlorinator","for":[42645],"pkt":[[],[],[16,2,0,3],[0,73,110,116,101,108,108,105,99,104,108,111,114,45,45,54,48],[190,16,3]],"ts": "2022-07-19T21:46:00.700-0700"} */
83
+ response.action = 3;
84
+ response.appendPayloadBytes(0, 17);
85
+ response.insertPayloadString(1, 'INTELLICHLOR--60');
86
+ conn.queueSendMessage(response);
87
+ }
88
+
89
+ private random(bounds: number, onlyPositive: boolean = false){
90
+ let rand = Math.random() * bounds;
91
+ if (!onlyPositive) {
92
+ if (Math.random()<=.5) rand = rand * -1;
93
+ }
94
+ return rand;
95
+ }
96
+
97
+ }
98
+
99
99
  export var mockChlor: MockChlorinator = new MockChlorinator();