nodejs-poolcontroller 7.6.1 → 8.0.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/.eslintrc.json +36 -45
- 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/CONTRIBUTING.md +74 -74
- package/Changelog +242 -215
- package/Dockerfile +17 -17
- package/Gruntfile.js +40 -40
- package/LICENSE +661 -661
- package/README.md +195 -191
- package/anslq25/MessagesMock.ts +218 -0
- package/anslq25/boards/MockBoardFactory.ts +50 -0
- package/anslq25/boards/MockEasyTouchBoard.ts +696 -0
- package/anslq25/boards/MockSystemBoard.ts +217 -0
- package/anslq25/chemistry/MockChlorinator.ts +75 -0
- package/anslq25/pumps/MockPump.ts +84 -0
- package/app.ts +10 -14
- package/config/Config.ts +26 -8
- package/config/VersionCheck.ts +8 -4
- package/controller/Constants.ts +59 -25
- package/controller/Equipment.ts +2667 -2459
- package/controller/Errors.ts +181 -180
- package/controller/Lockouts.ts +534 -436
- package/controller/State.ts +596 -77
- package/controller/boards/AquaLinkBoard.ts +1003 -0
- package/controller/boards/BoardFactory.ts +53 -45
- package/controller/boards/EasyTouchBoard.ts +3079 -2653
- package/controller/boards/IntelliCenterBoard.ts +3821 -4230
- package/controller/boards/IntelliComBoard.ts +69 -63
- package/controller/boards/IntelliTouchBoard.ts +384 -241
- package/controller/boards/NixieBoard.ts +1871 -1675
- package/controller/boards/SunTouchBoard.ts +393 -0
- package/controller/boards/SystemBoard.ts +5244 -4697
- package/controller/comms/Comms.ts +905 -541
- package/controller/comms/ScreenLogic.ts +1663 -0
- package/controller/comms/messages/Messages.ts +382 -54
- package/controller/comms/messages/config/ChlorinatorMessage.ts +8 -4
- package/controller/comms/messages/config/CircuitGroupMessage.ts +5 -2
- package/controller/comms/messages/config/CircuitMessage.ts +82 -13
- package/controller/comms/messages/config/ConfigMessage.ts +3 -1
- package/controller/comms/messages/config/CoverMessage.ts +2 -1
- package/controller/comms/messages/config/CustomNameMessage.ts +31 -30
- package/controller/comms/messages/config/EquipmentMessage.ts +5 -1
- package/controller/comms/messages/config/ExternalMessage.ts +33 -3
- package/controller/comms/messages/config/FeatureMessage.ts +2 -1
- package/controller/comms/messages/config/GeneralMessage.ts +2 -1
- package/controller/comms/messages/config/HeaterMessage.ts +145 -11
- package/controller/comms/messages/config/IntellichemMessage.ts +2 -1
- package/controller/comms/messages/config/OptionsMessage.ts +16 -27
- package/controller/comms/messages/config/PumpMessage.ts +62 -47
- package/controller/comms/messages/config/RemoteMessage.ts +80 -13
- package/controller/comms/messages/config/ScheduleMessage.ts +390 -347
- package/controller/comms/messages/config/SecurityMessage.ts +2 -1
- package/controller/comms/messages/config/ValveMessage.ts +44 -27
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +44 -91
- package/controller/comms/messages/status/EquipmentStateMessage.ts +139 -30
- package/controller/comms/messages/status/HeaterStateMessage.ts +135 -86
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +448 -445
- package/controller/comms/messages/status/IntelliValveStateMessage.ts +36 -35
- package/controller/comms/messages/status/PumpStateMessage.ts +92 -2
- package/controller/comms/messages/status/VersionMessage.ts +2 -1
- package/controller/nixie/Nixie.ts +173 -162
- package/controller/nixie/NixieEquipment.ts +104 -103
- package/controller/nixie/bodies/Body.ts +120 -120
- package/controller/nixie/bodies/Filter.ts +135 -135
- package/controller/nixie/chemistry/ChemController.ts +2682 -2498
- package/controller/nixie/chemistry/ChemDoser.ts +806 -0
- package/controller/nixie/chemistry/Chlorinator.ts +367 -314
- package/controller/nixie/circuits/Circuit.ts +402 -248
- package/controller/nixie/heaters/Heater.ts +815 -649
- package/controller/nixie/pumps/Pump.ts +934 -661
- package/controller/nixie/schedules/Schedule.ts +319 -257
- package/controller/nixie/valves/Valve.ts +170 -170
- package/defaultConfig.json +346 -286
- package/logger/DataLogger.ts +448 -448
- package/logger/Logger.ts +38 -9
- package/package.json +60 -56
- package/tsconfig.json +25 -25
- package/web/Server.ts +275 -117
- package/web/bindings/aqualinkD.json +560 -0
- package/web/bindings/homeassistant.json +437 -0
- package/web/bindings/influxDB.json +1066 -1021
- package/web/bindings/mqtt.json +721 -654
- package/web/bindings/mqttAlt.json +746 -684
- package/web/bindings/rulesManager.json +54 -54
- package/web/bindings/smartThings-Hubitat.json +31 -31
- package/web/bindings/valveRelays.json +20 -20
- package/web/bindings/vera.json +25 -25
- package/web/interfaces/baseInterface.ts +188 -136
- package/web/interfaces/httpInterface.ts +148 -124
- package/web/interfaces/influxInterface.ts +283 -245
- package/web/interfaces/mqttInterface.ts +695 -475
- package/web/interfaces/ruleInterface.ts +87 -0
- package/web/services/config/Config.ts +177 -49
- package/web/services/config/ConfigSocket.ts +2 -1
- package/web/services/state/State.ts +154 -3
- package/web/services/state/StateSocket.ts +69 -18
- package/web/services/utilities/Utilities.ts +232 -42
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -52
- package/config copy.json +0 -300
- package/issue_template.md +0 -52
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
import { logger } from "../../logger/Logger";
|
|
2
|
+
import { Inbound, Outbound, Protocol } from "../../controller/comms/messages/Messages";
|
|
3
|
+
import { MockSystemCommands, MockSystemBoard, MockCircuitCommands, MockScheduleCommands, MockHeaterCommands, MockValveCommands, MockRemoteCommands, MockPumpCommands } from "./MockSystemBoard";
|
|
4
|
+
import { BodyTempState, state } from "../../controller/State";
|
|
5
|
+
import { ControllerType, Heater, PoolSystem, PumpCircuit, sys } from "../../controller/Equipment";
|
|
6
|
+
import { byteValueMap } from "../../controller/boards/SystemBoard";
|
|
7
|
+
import { conn } from "../../controller/comms/Comms";
|
|
8
|
+
import { Timestamp, utils } from "../../controller/Constants";
|
|
9
|
+
export class MockEasyTouch extends MockSystemBoard {
|
|
10
|
+
constructor(system: PoolSystem) {
|
|
11
|
+
super(system);
|
|
12
|
+
this.valueMaps.expansionBoards = new byteValueMap([
|
|
13
|
+
[0, { name: 'ET28', part: 'ET2-8', desc: 'EasyTouch2 8', circuits: 8, shared: true }],
|
|
14
|
+
[1, { name: 'ET28P', part: 'ET2-8P', desc: 'EasyTouch2 8P', circuits: 8, single: true, shared: false }],
|
|
15
|
+
[2, { name: 'ET24', part: 'ET2-4', desc: 'EasyTouch2 4', circuits: 4, shared: true }],
|
|
16
|
+
[3, { name: 'ET24P', part: 'ET2-4P', desc: 'EasyTouch2 4P', circuits: 4, single: true, shared: false }],
|
|
17
|
+
[6, { name: 'ETPSL4', part: 'ET-PSL4', desc: 'EasyTouch PSL4', circuits: 4, features: 2, schedules: 4, pumps: 1, shared: true }],
|
|
18
|
+
[7, { name: 'ETPL4', part: 'ET-PL4', desc: 'EasyTouch PL4', circuits: 4, features: 2, schedules: 4, pumps: 1, single: true, shared: false }],
|
|
19
|
+
// EasyTouch 1 models all start at 128.
|
|
20
|
+
[128, { name: 'ET8', part: 'ET-8', desc: 'EasyTouch 8', circuits: 8, shared: true }],
|
|
21
|
+
[129, { name: 'ET8P', part: 'ET-8P', desc: 'EasyTouch 8', circuits: 8, single: true, shared: false }],
|
|
22
|
+
[130, { name: 'ET4', part: 'ET-4', desc: 'EasyTouch 4', circuits: 4, shared: true }],
|
|
23
|
+
[129, { name: 'ET4P', part: 'ET-4P', desc: 'EasyTouch 4P', circuits: 4, single: true, shared: false }]
|
|
24
|
+
]);
|
|
25
|
+
}
|
|
26
|
+
public system: EasyTouchMockSystemCommands = new EasyTouchMockSystemCommands(this);
|
|
27
|
+
public circuits: EasyTouchMockCircuitCommands = new EasyTouchMockCircuitCommands(this);
|
|
28
|
+
public schedules: EasyTouchMockScheduleCommands = new EasyTouchMockScheduleCommands(this);
|
|
29
|
+
public heaters: EasyTouchMockHeaterCommands = new EasyTouchMockHeaterCommands(this);
|
|
30
|
+
public valves: EasyTouchMockValveCommands = new EasyTouchMockValveCommands(this);
|
|
31
|
+
public remotes: EasyTouchMockRemoteCommands = new EasyTouchMockRemoteCommands(this);
|
|
32
|
+
public pumps: EasyTouchMockPumpCommands = new EasyTouchMockPumpCommands(this);
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
class EasyTouchMockSystemCommands extends MockSystemCommands {
|
|
37
|
+
public async processDateTimeAsync(msg: Inbound) {
|
|
38
|
+
try {
|
|
39
|
+
let response: Outbound = Outbound.create({
|
|
40
|
+
action: 5,
|
|
41
|
+
portId: msg.portId,
|
|
42
|
+
protocol: msg.protocol,
|
|
43
|
+
dest: msg.source,
|
|
44
|
+
source: 16 //msg.dest
|
|
45
|
+
});
|
|
46
|
+
response.appendPayloadBytes(0, 7);
|
|
47
|
+
response.setPayloadByte(0, state.time.hours);
|
|
48
|
+
response.setPayloadByte(1, state.time.minutes);
|
|
49
|
+
response.setPayloadByte(2, Timestamp.dayOfWeek(state.time));
|
|
50
|
+
response.setPayloadByte(3, state.time.date);
|
|
51
|
+
response.setPayloadByte(4, state.time.month);
|
|
52
|
+
response.setPayloadByte(5, state.time.year - 2000);
|
|
53
|
+
response.setPayloadByte(6, sys.general.options.adjustDST ? 1 : 0);
|
|
54
|
+
msg.isProcessed = true;
|
|
55
|
+
await sys.anslq25Board.sendAsync(response);
|
|
56
|
+
//conn.queueSendMessage(response);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
logger.error(`ANSLQ25 error processing date/time. ${err.message}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
public async processCustomNameAsync(msg: Inbound): Promise<void> {
|
|
63
|
+
try {
|
|
64
|
+
let response: Outbound = Outbound.create({
|
|
65
|
+
action: 10,
|
|
66
|
+
portId: msg.portId,
|
|
67
|
+
protocol: msg.protocol,
|
|
68
|
+
dest: msg.source,
|
|
69
|
+
source: 16 //msg.dest
|
|
70
|
+
});
|
|
71
|
+
response.appendPayloadByte(msg.payload[0]);
|
|
72
|
+
let cname = sys.customNames.getItemById(msg.payload[0]).name;
|
|
73
|
+
if (typeof cname === 'undefined') response.appendPayloadString(`CustomName${msg.payload[0]}`, 11);
|
|
74
|
+
else
|
|
75
|
+
response.appendPayloadString(cname, 11);
|
|
76
|
+
msg.isProcessed = true;
|
|
77
|
+
await sys.anslq25Board.sendAsync(response);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
logger.error(`ANSLQ25 error processing custom name ${msg.payload[0]}. ${err.message}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
public async processSettingsAsync(msg: Inbound): Promise<void> {
|
|
84
|
+
try {
|
|
85
|
+
// 40/168/232
|
|
86
|
+
let response: Outbound = Outbound.create({
|
|
87
|
+
action: 40,
|
|
88
|
+
portId: msg.portId,
|
|
89
|
+
protocol: msg.protocol,
|
|
90
|
+
dest: msg.source,
|
|
91
|
+
source: 16 //msg.dest
|
|
92
|
+
});
|
|
93
|
+
response.appendPayloadBytes(0, 10);
|
|
94
|
+
let chem = sys.chemControllers.getItemByAddress(144);
|
|
95
|
+
if (chem.isActive) response.setPayloadByte(3, 0x01, 0);
|
|
96
|
+
response.setPayloadByte(4, sys.general.options.manualHeat ? 1 : 0, 0);
|
|
97
|
+
response.setPayloadByte(5, sys.general.options.manualPriority ? 1 : 0, 0);
|
|
98
|
+
msg.isProcessed = true;
|
|
99
|
+
await sys.anslq25Board.sendAsync(response);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
logger.error(`ANSLQ25 error processing settings. ${err.message}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
public async sendAck(msg: Inbound) {
|
|
106
|
+
/*
|
|
107
|
+
* Per matching rules:
|
|
108
|
+
* if (msgIn.source === msgOut.dest && msgIn.payload[0] === msgOut.action) return true;
|
|
109
|
+
*/
|
|
110
|
+
let response: Outbound = Outbound.create({
|
|
111
|
+
action: 1,
|
|
112
|
+
portId: msg.portId,
|
|
113
|
+
protocol: msg.protocol,
|
|
114
|
+
dest: msg.source,
|
|
115
|
+
source: 16 //msg.dest
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
response.appendPayloadByte(msg.action);
|
|
119
|
+
msg.isProcessed = true;
|
|
120
|
+
await sys.anslq25Board.sendAsync(response);
|
|
121
|
+
// conn.queueSendMessage(response);
|
|
122
|
+
}
|
|
123
|
+
public async sendStatusAsync() {
|
|
124
|
+
try {
|
|
125
|
+
let msg = Outbound.create({
|
|
126
|
+
portId: sys.anslq25.portId,
|
|
127
|
+
protocol: Protocol.Broadcast,
|
|
128
|
+
dest: 16,
|
|
129
|
+
source: 15,
|
|
130
|
+
action: 2
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
console.log(`send status command`);
|
|
134
|
+
msg.appendPayloadBytes(0, 29);
|
|
135
|
+
// to do: reverse engineer logic for model types
|
|
136
|
+
// sys.equipment.model;
|
|
137
|
+
// let mod = sys.board.valueMaps.expansionBoards.get(sys.equipment.modules.getItemById(0).type);
|
|
138
|
+
let mt = sys.equipment.modules.getItemById(0);
|
|
139
|
+
let model1 = mt.type
|
|
140
|
+
msg.setPayloadByte(27, model1); // model1
|
|
141
|
+
msg.setPayloadByte(28, 13); // model2
|
|
142
|
+
|
|
143
|
+
// set time
|
|
144
|
+
msg.setPayloadByte(0, state.time.hours);
|
|
145
|
+
msg.setPayloadByte(1, state.time.minutes);
|
|
146
|
+
|
|
147
|
+
// set mode
|
|
148
|
+
msg.setPayloadByte(9, msg.setPayloadByte[9] | state.mode);
|
|
149
|
+
|
|
150
|
+
// set units
|
|
151
|
+
msg.setPayloadByte(9, msg[9] | state.temps.units);
|
|
152
|
+
|
|
153
|
+
// set valves
|
|
154
|
+
msg.setPayloadByte(10, state.valve);
|
|
155
|
+
|
|
156
|
+
// set delay
|
|
157
|
+
msg.setPayloadByte(12, msg[12] | (Math.max(state.delay, 0)));
|
|
158
|
+
|
|
159
|
+
// set freeze
|
|
160
|
+
if (state.freeze) msg.setPayloadByte(9, msg[9] | 0x08);
|
|
161
|
+
|
|
162
|
+
// set circuits
|
|
163
|
+
let circuits = state.circuits.get(true);
|
|
164
|
+
let circuitId = 0;
|
|
165
|
+
for (let i = 2; i <= circuits.length; i++) {
|
|
166
|
+
for (let j = 0; j < 8; j++) {
|
|
167
|
+
|
|
168
|
+
let circuit = circuits[circuitId];
|
|
169
|
+
if (circuit.isActive && circuit.isOn) {
|
|
170
|
+
msg.setPayloadByte(i, msg[i] & (1 >> j))
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
circuitId++;
|
|
174
|
+
}
|
|
175
|
+
// set temps
|
|
176
|
+
msg.setPayloadByte(14, state.temps.waterSensor1);
|
|
177
|
+
msg.setPayloadByte(18, state.temps.air);
|
|
178
|
+
let solar: Heater = sys.heaters.getItemById(2);
|
|
179
|
+
if (solar.isActive) msg.setPayloadByte(19, state.temps.solar);
|
|
180
|
+
if (sys.bodies.length > 2 || sys.equipment.dual) msg.setPayloadByte(15, state.temps.waterSensor2);
|
|
181
|
+
// set body attributes
|
|
182
|
+
if (sys.bodies.length > 0) {
|
|
183
|
+
const tbody: BodyTempState = state.temps.bodies.getItemById(1, true);
|
|
184
|
+
if (tbody.isOn) {
|
|
185
|
+
msg.setPayloadByte(2, msg[2] | 0x20);
|
|
186
|
+
if (tbody.heatMode > 0) {
|
|
187
|
+
let _heatStatus = sys.board.valueMaps.heatStatus.getName(tbody.heatStatus);
|
|
188
|
+
if (tbody.heaterOptions.hybrid > 0) {
|
|
189
|
+
|
|
190
|
+
if (_heatStatus === 'dual') msg.setPayloadByte(10, msg[10] | 0x14);
|
|
191
|
+
else if (_heatStatus === 'heater') msg.setPayloadByte(10, msg[10] | 0x10);
|
|
192
|
+
else if (_heatStatus === 'hpheat') msg.setPayloadByte(10, msg[10] | 0x04);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
if (_heatStatus === 'heater') msg.setPayloadByte(10, msg[10] | 0x04);
|
|
196
|
+
if (_heatStatus === 'cooling' || _heatStatus === 'solar') msg.setPayloadByte(10, msg[10] | 0x10);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
else msg.setPayloadByte(10, 0);
|
|
201
|
+
}
|
|
202
|
+
if (sys.bodies.length > 1) {
|
|
203
|
+
const tbody: BodyTempState = state.temps.bodies.getItemById(2, true);
|
|
204
|
+
// const cbody: Body = sys.bodies.getItemById(2);
|
|
205
|
+
let _heatStatus = sys.board.valueMaps.heatStatus.getName(tbody.heatStatus);
|
|
206
|
+
if (tbody.isOn) msg.setPayloadByte(2, msg[2] | 0x01);
|
|
207
|
+
msg.setPayloadByte(22, msg[22] | tbody.heatMode << 2);
|
|
208
|
+
if (tbody.isOn) {
|
|
209
|
+
if (tbody.heaterOptions.hybrid > 0) {
|
|
210
|
+
let _heatStatus = sys.board.valueMaps.heatStatus.getName(tbody.heatStatus);
|
|
211
|
+
if (tbody.heatMode > 0) {
|
|
212
|
+
if (_heatStatus === 'dual') msg.setPayloadByte(10, msg[10] | 0x28);
|
|
213
|
+
else if (_heatStatus === 'heater') msg.setPayloadByte(10, msg[10] | 0x20);
|
|
214
|
+
else if (_heatStatus === 'hpheat') msg.setPayloadByte(10, msg[10] | 0x08);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
if (_heatStatus === 'heater') msg.setPayloadByte(10, msg[10] | 0x28);
|
|
218
|
+
if (_heatStatus === 'cooling' || _heatStatus === 'solar') msg.setPayloadByte(10, msg[10] | 0x20);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else msg.setPayloadByte(10, msg[10], 0);
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// set temps -- 14 (water) and 15 (water2)
|
|
226
|
+
msg.setPayloadByte(14, state.temps.waterSensor1, 0);
|
|
227
|
+
if (sys.bodies.length > 2 || sys.equipment.dual) msg.setPayloadByte(15, state.temps.waterSensor2, 0);
|
|
228
|
+
msg.setPayloadByte(18, state.temps.air, 0);
|
|
229
|
+
msg.setPayloadByte(19, state.temps.solarSensor1, 0);
|
|
230
|
+
if (sys.bodies.length > 2 || sys.equipment.dual)
|
|
231
|
+
msg.setPayloadByte(17, state.temps.solarSensor2, 0);
|
|
232
|
+
if ((sys.bodies.length > 2))
|
|
233
|
+
msg.setPayloadByte(22, state.temps.solarSensor3, 0);
|
|
234
|
+
if ((sys.bodies.length > 3))
|
|
235
|
+
msg.setPayloadByte(23, state.temps.solarSensor4, 0);
|
|
236
|
+
|
|
237
|
+
await sys.anslq25Board.sendAsync(msg);
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
logger.error(`Error sending ANSLQ25 status packet: ${err.message}`);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
class EasyTouchMockCircuitCommands extends MockCircuitCommands {
|
|
246
|
+
public async processCircuitAsync(msg: Inbound) {
|
|
247
|
+
// example [255,0,255][165,33,16,34,139,5][17,14,209,0,0][2,120]
|
|
248
|
+
// set circuit 17 to function 14 and name 209
|
|
249
|
+
// response: [255,0,255][165,33,34,16,1,1][139][1,133]
|
|
250
|
+
// request for circuit 2: [165,33,16,33,203,1],[2],[1,197]]
|
|
251
|
+
|
|
252
|
+
try {
|
|
253
|
+
let response: Outbound = Outbound.create({
|
|
254
|
+
action: 11,
|
|
255
|
+
portId: msg.portId,
|
|
256
|
+
protocol: msg.protocol,
|
|
257
|
+
dest: msg.source,
|
|
258
|
+
source: 16 //msg.dest
|
|
259
|
+
});
|
|
260
|
+
let circuit = sys.circuits.getInterfaceById(msg.payload[0]);
|
|
261
|
+
response.appendPayloadBytes(0, 5);
|
|
262
|
+
response.setPayloadByte(0, circuit.id);
|
|
263
|
+
if (circuit.id === 1) {
|
|
264
|
+
response.setPayloadByte(1, 1 | (circuit.freeze ? 64 : 0), 0);
|
|
265
|
+
response.setPayloadByte(2, 72, 53);
|
|
266
|
+
|
|
267
|
+
}
|
|
268
|
+
else if (circuit.id === 6) {
|
|
269
|
+
response.setPayloadByte(1, 2 | (circuit.freeze ? 64 : 0), 0);
|
|
270
|
+
response.setPayloadByte(2, 61, 53);
|
|
271
|
+
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
response.setPayloadByte(1, circuit.type | (circuit.freeze ? 64 : 0), 0);
|
|
275
|
+
response.setPayloadByte(2, circuit.nameId, 53);
|
|
276
|
+
}
|
|
277
|
+
msg.isProcessed = true;
|
|
278
|
+
await sys.anslq25Board.sendAsync(response);
|
|
279
|
+
}
|
|
280
|
+
catch (err) {
|
|
281
|
+
logger.error(`ANSLQ25 error processing circuit ${msg.payload[0]}. ${err.message}`);
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
public async processLightGroupAsync(msg: Inbound) {
|
|
285
|
+
try {
|
|
286
|
+
// 39/167/231
|
|
287
|
+
// todo - when 25 packet length vs 32. May need to add.
|
|
288
|
+
let response: Outbound = Outbound.create({
|
|
289
|
+
action: 39,
|
|
290
|
+
portId: msg.portId,
|
|
291
|
+
protocol: msg.protocol,
|
|
292
|
+
dest: msg.source,
|
|
293
|
+
source: 16 //msg.dest
|
|
294
|
+
});
|
|
295
|
+
let lg = sys.lightGroups.getItemById(sys.board.equipmentIds.circuitGroups.start);
|
|
296
|
+
response.appendPayloadBytes(0, 32);
|
|
297
|
+
for (let byte = 0; byte <= 32; byte = byte + 4) {
|
|
298
|
+
let circuit = sys.circuits.getInterfaceById(byte);
|
|
299
|
+
response.setPayloadByte(byte, circuit.id, 0);
|
|
300
|
+
let pair = byte + 1;
|
|
301
|
+
const lgCircuit = lg.circuits.getItemByCircuitId(circuit.id);
|
|
302
|
+
response.setPayloadByte(pair, Math.max((lgCircuit.position - 1), 0), 0);
|
|
303
|
+
response.setPayloadByte(pair, response.payload[pair] | lgCircuit.color, 0);
|
|
304
|
+
response.setPayloadByte(byte + 2, lgCircuit.swimDelay << 1, 0);
|
|
305
|
+
}
|
|
306
|
+
msg.isProcessed = true;
|
|
307
|
+
await sys.anslq25Board.sendAsync(response);
|
|
308
|
+
}
|
|
309
|
+
catch (err) {
|
|
310
|
+
logger.error(`ANSLQ25 error processing circuit ${msg.payload[0]}. ${err.message}`);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export class EasyTouchMockScheduleCommands extends MockScheduleCommands {
|
|
316
|
+
public async processScheduleAsync(msg: Inbound) {
|
|
317
|
+
// Sample packet
|
|
318
|
+
// Request: 165,33,16,33,209,1,7,1,202
|
|
319
|
+
// Response: [165,33,15,16,17,7][6,12,25,0,6,30,0][1,76]
|
|
320
|
+
try {
|
|
321
|
+
let response: Outbound = Outbound.create({
|
|
322
|
+
action: 17,
|
|
323
|
+
portId: msg.portId,
|
|
324
|
+
protocol: msg.protocol,
|
|
325
|
+
dest: msg.source,
|
|
326
|
+
source: 16 //msg.dest
|
|
327
|
+
});
|
|
328
|
+
response.appendPayloadBytes(0, 7);
|
|
329
|
+
let eggTimer = sys.eggTimers.getItemById(msg.payload[0]);
|
|
330
|
+
let schedule = sys.schedules.getItemById(msg.payload[0]);
|
|
331
|
+
if (eggTimer.isActive) {
|
|
332
|
+
response.setPayloadByte(0, eggTimer.id);
|
|
333
|
+
response.setPayloadByte(1, eggTimer.circuit);
|
|
334
|
+
response.setPayloadByte(2, 25);
|
|
335
|
+
response.setPayloadByte(4, eggTimer.runTime === 27 ? 27 : Math.floor(eggTimer.runTime / 60));
|
|
336
|
+
response.setPayloadByte(5, eggTimer.runTime === 27 ? 0 : eggTimer.runTime - (Math.floor(eggTimer.runTime / 60) * 60));
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
response.setPayloadByte(0, schedule.id);
|
|
340
|
+
response.setPayloadByte(1, schedule.circuit, 0);
|
|
341
|
+
response.setPayloadByte(2, Math.floor(schedule.startTime / 60), 0);
|
|
342
|
+
response.setPayloadByte(3, Math.floor(schedule.startTime / 60) - (Math.floor(schedule.startTime / 60) * 60), 0);
|
|
343
|
+
response.setPayloadByte(4, schedule.scheduleType === 0 ? 0 : Math.floor(schedule.endTime / 60), 0);
|
|
344
|
+
response.setPayloadByte(5, Math.floor(schedule.endTime / 60) - (Math.floor(schedule.endTime / 60) * 60), 0);
|
|
345
|
+
response.setPayloadByte(6, schedule.scheduleDays, 0);
|
|
346
|
+
}
|
|
347
|
+
msg.isProcessed = true;
|
|
348
|
+
await sys.anslq25Board.sendAsync(response);
|
|
349
|
+
}
|
|
350
|
+
catch (err) {
|
|
351
|
+
logger.error(`ANSLQ25 error processing custom name ${msg.payload[0]}. ${err.message}`);
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export class EasyTouchMockHeaterCommands extends MockHeaterCommands {
|
|
357
|
+
public async processHeatModesAsync(msg: Inbound) {
|
|
358
|
+
// IntelliTouch only. Heat status
|
|
359
|
+
// [165,x,15,16,8,13],[75,75,64,87,101,11,0, 0 ,62 ,0 ,0 ,0 ,0] ,[2,190]
|
|
360
|
+
// Heat Modes
|
|
361
|
+
// 1 = Heater
|
|
362
|
+
// 2 = Solar Preferred
|
|
363
|
+
// 3 = Solar Only
|
|
364
|
+
//[81, 81, 82, 85, 97, 7, 0, 0, 0, 100, 100, 4, 0][3, 87]
|
|
365
|
+
// byte | val |
|
|
366
|
+
// 0 | 81 | Water sensor 1
|
|
367
|
+
// 1 | 81 | Unknown (Probably water sensor 2 on a D)
|
|
368
|
+
// 2 | 82 | Air sensor
|
|
369
|
+
// 3 | 85 | Body 1 setpoint
|
|
370
|
+
// 4 | 97 | Body 2 setpoint
|
|
371
|
+
// 5 | 7 | Body 1 & 2 heat mode. (0111) (Pool = 11 Solar only/Spa = 01 Heater)
|
|
372
|
+
// 6 | 0 | Unknown (Water Sensor 3)
|
|
373
|
+
// 7 | 0 | Unknown (Water Sensor 4)
|
|
374
|
+
// 8 | 0 | Unknown -- Reserved air sensor
|
|
375
|
+
// 9 | 100 | Unknown (Body 3 setpoint)
|
|
376
|
+
// 10 | 100 | Unknown (Body 4 setpoint)
|
|
377
|
+
// 11 | 4 | Unknown (Body 3 & 4 head mode. (0010) (Pool = 00 = Off/ 10 = Solar Preferred)
|
|
378
|
+
// 12 | 0 | Unknown
|
|
379
|
+
// There are two messages sent when the OCP tries to tse a heat mode in IntelliTouch. The first one on the action 136 is for the first 2 bodies and the second
|
|
380
|
+
// is for the remaining 2 bodies. The second half of this message mirrors the values for the second 136 message.
|
|
381
|
+
|
|
382
|
+
try {
|
|
383
|
+
let response: Outbound = Outbound.create({
|
|
384
|
+
action: 8,
|
|
385
|
+
portId: msg.portId,
|
|
386
|
+
protocol: msg.protocol,
|
|
387
|
+
dest: msg.source,
|
|
388
|
+
source: 16 //msg.dest
|
|
389
|
+
});
|
|
390
|
+
response.appendPayloadBytes(0, 13);
|
|
391
|
+
|
|
392
|
+
const tbody1: BodyTempState = state.temps.bodies.getItemById(1);
|
|
393
|
+
const tbody2: BodyTempState = state.temps.bodies.getItemById(2);
|
|
394
|
+
response.setPayloadByte(0, state.temps.waterSensor1, 0);
|
|
395
|
+
response.setPayloadByte(1, state.temps.waterSensor2, 0);
|
|
396
|
+
response.setPayloadByte(2, state.temps.air, 0);
|
|
397
|
+
response.setPayloadByte(3, tbody1.setPoint, 0);
|
|
398
|
+
response.setPayloadByte(4, tbody2.setPoint, 0);
|
|
399
|
+
const tbody: BodyTempState = state.temps.bodies.getItemById(1, true);
|
|
400
|
+
if (tbody.heaterOptions.hybrid > 0) {
|
|
401
|
+
response.setPayloadByte(5, tbody2.heatMode << 2 | tbody1.heatMode, 0);
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
response.setPayloadByte(5, tbody1.heatMode << 2 | tbody2.heatMode, 0);
|
|
405
|
+
}
|
|
406
|
+
response.setPayloadByte(9, tbody1.coolSetpoint, 0);
|
|
407
|
+
response.setPayloadByte(9, tbody2.coolSetpoint, 0);
|
|
408
|
+
msg.isProcessed = true;
|
|
409
|
+
await sys.anslq25Board.sendAsync(response);
|
|
410
|
+
}
|
|
411
|
+
catch (err) {
|
|
412
|
+
logger.error(`ANSLQ25 error processing heat modes. ${err.message}`);
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
public async processHeaterConfigAsync(msg: Inbound) {
|
|
418
|
+
// 34/162/226
|
|
419
|
+
|
|
420
|
+
try {
|
|
421
|
+
let response: Outbound = Outbound.create({
|
|
422
|
+
action: 34,
|
|
423
|
+
portId: msg.portId,
|
|
424
|
+
protocol: msg.protocol,
|
|
425
|
+
dest: msg.source,
|
|
426
|
+
source: 16 //msg.dest
|
|
427
|
+
});
|
|
428
|
+
response.appendPayloadBytes(0, 3);
|
|
429
|
+
const tbody: BodyTempState = state.temps.bodies.getItemById(1, true);
|
|
430
|
+
if (tbody.heaterOptions.hybrid > 0) {
|
|
431
|
+
response.setPayloadByte(1, 0x10);
|
|
432
|
+
}
|
|
433
|
+
else if (tbody.heaterOptions.heatpump > 0) {
|
|
434
|
+
response.setPayloadByte(1, 0x20);
|
|
435
|
+
let hpump = sys.heaters.getItemById(3);
|
|
436
|
+
if (hpump.heatingEnabled) response.setPayloadByte(1, response.payload[1] | 0x01);
|
|
437
|
+
if (hpump.coolingEnabled) response.setPayloadByte(1, response.payload[1] | 0x02);
|
|
438
|
+
}
|
|
439
|
+
else if (tbody.heaterOptions.solar > 0) {
|
|
440
|
+
response.setPayloadByte(0, 0x01);
|
|
441
|
+
let solar = sys.heaters.getItemById(2);
|
|
442
|
+
if (solar.freeze) response.setPayloadByte(1, response.payload[1] | 0x80);
|
|
443
|
+
if (solar.coolingEnabled) response.setPayloadByte(1, response.payload[1] | 0x20);
|
|
444
|
+
response.setPayloadByte(2, (solar.startTempDelta - 3) << 1);
|
|
445
|
+
response.setPayloadByte(2, response.payload[2] | (solar.stopTempDelta - 2) << 6);
|
|
446
|
+
|
|
447
|
+
}
|
|
448
|
+
msg.isProcessed = true;
|
|
449
|
+
await sys.anslq25Board.sendAsync(response);
|
|
450
|
+
}
|
|
451
|
+
catch (err) {
|
|
452
|
+
logger.error(`ANSLQ25 error processing heater config. ${err.message}`);
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export class EasyTouchMockValveCommands extends MockValveCommands {
|
|
458
|
+
public async processValveAssignmentsAsync(msg: Inbound) {
|
|
459
|
+
try {
|
|
460
|
+
// 29/157/221
|
|
461
|
+
let response: Outbound = Outbound.create({
|
|
462
|
+
action: 29,
|
|
463
|
+
portId: msg.portId,
|
|
464
|
+
protocol: msg.protocol,
|
|
465
|
+
dest: msg.source,
|
|
466
|
+
source: 16 //msg.dest
|
|
467
|
+
});
|
|
468
|
+
response.appendPayloadBytes(0, 24);
|
|
469
|
+
response.setPayloadByte(1, 2); //constant
|
|
470
|
+
for (let ndx = 4, id = 1; id <= sys.equipment.maxValves; ndx++) {
|
|
471
|
+
let valve = sys.valves.getItemById(id);
|
|
472
|
+
response.setPayloadByte(ndx, valve.circuit, 0);
|
|
473
|
+
id++;
|
|
474
|
+
}
|
|
475
|
+
msg.isProcessed = true;
|
|
476
|
+
await sys.anslq25Board.sendAsync(response);
|
|
477
|
+
}
|
|
478
|
+
catch (err) {
|
|
479
|
+
logger.error(`ANSLQ25 error processing valve assignment packet. ${err.message}`);
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
public async processValveOptionsAsync(msg: Inbound) {
|
|
483
|
+
try {
|
|
484
|
+
// 35/163/227
|
|
485
|
+
let response: Outbound = Outbound.create({
|
|
486
|
+
action: 35,
|
|
487
|
+
portId: msg.portId,
|
|
488
|
+
protocol: msg.protocol,
|
|
489
|
+
dest: msg.source,
|
|
490
|
+
source: 16 //msg.dest
|
|
491
|
+
});
|
|
492
|
+
response.appendPayloadBytes(0, 2);
|
|
493
|
+
response.setPayloadByte(0, (sys.general.options.pumpDelay ? 128 : 0) | 4, 4);
|
|
494
|
+
msg.isProcessed = true;
|
|
495
|
+
await sys.anslq25Board.sendAsync(response);
|
|
496
|
+
}
|
|
497
|
+
catch (err) {
|
|
498
|
+
logger.error(`ANSLQ25 error processing valve options packet. ${err.message}`);
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
export class EasyTouchMockRemoteCommands extends MockRemoteCommands {
|
|
504
|
+
public async processIS4IS10RemoteAsync(msg: Inbound) {
|
|
505
|
+
try {
|
|
506
|
+
// 32/160/224
|
|
507
|
+
let response: Outbound = Outbound.create({
|
|
508
|
+
action: 32,
|
|
509
|
+
portId: msg.portId,
|
|
510
|
+
protocol: msg.protocol,
|
|
511
|
+
dest: msg.source,
|
|
512
|
+
source: 16 //msg.dest
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
response.appendPayloadBytes(0, 11);
|
|
516
|
+
console.log(sys.remotes.length);
|
|
517
|
+
for (let i = 0; i < sys.remotes.length; i++) {
|
|
518
|
+
|
|
519
|
+
let remote = sys.remotes.getItemById(i + 1);
|
|
520
|
+
response.setPayloadByte(0, i);
|
|
521
|
+
response.setPayloadByte(1, remote.button1, 0);
|
|
522
|
+
response.setPayloadByte(2, remote.button2, 0);
|
|
523
|
+
response.setPayloadByte(3, remote.button3, 0);
|
|
524
|
+
response.setPayloadByte(4, remote.button4, 0);
|
|
525
|
+
response.setPayloadByte(5, remote.button5, 0);
|
|
526
|
+
response.setPayloadByte(6, remote.button6, 0);
|
|
527
|
+
response.setPayloadByte(7, remote.button7, 0);
|
|
528
|
+
response.setPayloadByte(8, remote.button8, 0);
|
|
529
|
+
response.setPayloadByte(9, remote.button9, 0);
|
|
530
|
+
response.setPayloadByte(10, remote.button10, 0);
|
|
531
|
+
}
|
|
532
|
+
msg.isProcessed = true;
|
|
533
|
+
await sys.anslq25Board.sendAsync(response);
|
|
534
|
+
}
|
|
535
|
+
catch (err) {
|
|
536
|
+
logger.error(`ANSLQ25 error processing IS4/IS10 packet. ${err.message}`);
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
public async processQuickTouchRemoteAsync(msg: Inbound) {
|
|
540
|
+
try {
|
|
541
|
+
// 33/161/225
|
|
542
|
+
let response: Outbound = Outbound.create({
|
|
543
|
+
action: 33,
|
|
544
|
+
portId: msg.portId,
|
|
545
|
+
protocol: msg.protocol,
|
|
546
|
+
dest: msg.source,
|
|
547
|
+
source: 16 //msg.dest
|
|
548
|
+
});
|
|
549
|
+
response.appendPayloadBytes(0, 4);
|
|
550
|
+
let remote = sys.remotes.getItemById(6);
|
|
551
|
+
response.setPayloadByte(0, remote.button1, 0);
|
|
552
|
+
response.setPayloadByte(1, remote.button2, 0);
|
|
553
|
+
response.setPayloadByte(2, remote.button3, 0);
|
|
554
|
+
response.setPayloadByte(3, remote.button4, 0);
|
|
555
|
+
msg.isProcessed = true;
|
|
556
|
+
await sys.anslq25Board.sendAsync(response);
|
|
557
|
+
}
|
|
558
|
+
catch (err) {
|
|
559
|
+
logger.error(`ANSLQ25 error processing quicktouch remote packet. ${err.message}`);
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
public async processSpaCommandRemoteAsync(msg: Inbound) {
|
|
563
|
+
try {
|
|
564
|
+
// 22/150/214
|
|
565
|
+
let response: Outbound = Outbound.create({
|
|
566
|
+
action: 22,
|
|
567
|
+
portId: msg.portId,
|
|
568
|
+
protocol: msg.protocol,
|
|
569
|
+
dest: msg.source,
|
|
570
|
+
source: 16 //msg.dest
|
|
571
|
+
});
|
|
572
|
+
response.appendPayloadBytes(0, 16);
|
|
573
|
+
let remote = sys.remotes.getItemById(7);
|
|
574
|
+
response.setPayloadByte(5, remote.pumpId, 0);
|
|
575
|
+
response.setPayloadByte(6, remote.stepSize, 0);
|
|
576
|
+
msg.isProcessed = true;
|
|
577
|
+
await sys.anslq25Board.sendAsync(response);
|
|
578
|
+
}
|
|
579
|
+
catch (err) {
|
|
580
|
+
logger.error(`ANSLQ25 error processing spa command remote packet. ${err.message}`);
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
export class EasyTouchMockPumpCommands extends MockPumpCommands {
|
|
586
|
+
public async processPumpConfigAsync(msg: Inbound) {
|
|
587
|
+
try {
|
|
588
|
+
// 24/152/212 and 27/155/215(?)
|
|
589
|
+
// [255, 0, 255], [165, 33, 15, 16, 27, 46], [2, 6, 15, 2, 0, 1, 29, 11, 35, 0, 30, 0, 30, 0, 30, 0, 30, 0, 30, 0, 30, 30, 55, 5, 10, 60, 5, 1, 50, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [3, 41]
|
|
590
|
+
let response: Outbound = Outbound.create({
|
|
591
|
+
action: 24,
|
|
592
|
+
portId: msg.portId,
|
|
593
|
+
protocol: msg.protocol,
|
|
594
|
+
dest: msg.source,
|
|
595
|
+
source: 16 //msg.dest
|
|
596
|
+
});
|
|
597
|
+
response.appendPayloadBytes(0, 46);
|
|
598
|
+
let pump = sys.pumps.getItemById(msg.payload[0]);
|
|
599
|
+
response.setPayloadByte(0, pump.id);
|
|
600
|
+
response.setPayloadByte(1, pump.type, 0);
|
|
601
|
+
switch (pump.type) {
|
|
602
|
+
case 0: //none
|
|
603
|
+
{
|
|
604
|
+
break;
|
|
605
|
+
}
|
|
606
|
+
case 1: // vf
|
|
607
|
+
{
|
|
608
|
+
let pumpCircuits = pump.circuits.get();
|
|
609
|
+
for (let circuitId = 1; circuitId <= sys.board.valueMaps.pumpTypes.get(pump.type).maxCircuits; circuitId++) {
|
|
610
|
+
let pumpCircuit: PumpCircuit = pumpCircuits[circuitId];
|
|
611
|
+
if (pumpCircuit.circuit > 0) {
|
|
612
|
+
response.setPayloadByte(circuitId * 2 + 3, pumpCircuit.circuit, 0);
|
|
613
|
+
response.setPayloadByte(circuitId * 2 + 4, pumpCircuit.flow, 30);
|
|
614
|
+
}
|
|
615
|
+
response.setPayloadByte(1, pump.backgroundCircuit, 0);
|
|
616
|
+
response.setPayloadByte(2, pump.filterSize / 1000, 0);
|
|
617
|
+
response.setPayloadByte(3, pump.turnovers, 0);
|
|
618
|
+
response.setPayloadByte(21, pump.manualFilterGPM, 0);
|
|
619
|
+
response.setPayloadByte(22, pump.primingSpeed, 0);
|
|
620
|
+
// response.setPayloadByte(23, pump.primingTime, 0);
|
|
621
|
+
response.setPayloadByte(23, pump.primingTime | (pump.maxSystemTime << 4), 0);
|
|
622
|
+
response.setPayloadByte(24, pump.maxPressureIncrease, 0);
|
|
623
|
+
response.setPayloadByte(25, pump.backwashFlow, 0);
|
|
624
|
+
response.setPayloadByte(26, pump.backwashTime, 0);
|
|
625
|
+
response.setPayloadByte(27, pump.rinseTime, 0);
|
|
626
|
+
response.setPayloadByte(28, pump.vacuumFlow, 0);
|
|
627
|
+
response.setPayloadByte(30, pump.vacuumTime, 0);
|
|
628
|
+
|
|
629
|
+
}
|
|
630
|
+
break;
|
|
631
|
+
}
|
|
632
|
+
case 64: // vsf
|
|
633
|
+
{
|
|
634
|
+
let pumpCircuits = pump.circuits.get();
|
|
635
|
+
for (let circuitId = 1; circuitId <= sys.board.valueMaps.pumpTypes.get(pump.type).maxCircuits; circuitId++) {
|
|
636
|
+
let pumpCircuit: PumpCircuit = pumpCircuits[circuitId];
|
|
637
|
+
if (pumpCircuit.circuit > 0) {
|
|
638
|
+
response.setPayloadByte(4, pumpCircuit.units << circuitId - 1 | response.payload[4], response.payload[4]);
|
|
639
|
+
if (pumpCircuit.units) {
|
|
640
|
+
response.setPayloadByte(circuitId * 2 + 4, pumpCircuit.flow, response.payload[4]);
|
|
641
|
+
|
|
642
|
+
}
|
|
643
|
+
else {
|
|
644
|
+
response.setPayloadByte(circuitId * 2 + 4, pumpCircuit.speed - (pumpCircuit.speed % 256) / 256, 0);
|
|
645
|
+
response.setPayloadByte(circuitId + 21, pumpCircuit.speed % 256, 0);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
break;
|
|
650
|
+
}
|
|
651
|
+
case 128: // vs
|
|
652
|
+
case 169: //vs+svrs
|
|
653
|
+
{
|
|
654
|
+
let pumpCircuits = pump.circuits.get();
|
|
655
|
+
for (let circuitId = 1; circuitId <= sys.board.valueMaps.pumpTypes.get(pump.type).maxCircuits; circuitId++) {
|
|
656
|
+
let pumpCircuit: PumpCircuit = pumpCircuits[circuitId];
|
|
657
|
+
if (pumpCircuit.circuit > 0) {
|
|
658
|
+
|
|
659
|
+
response.setPayloadByte(circuitId * 2 + 4, pumpCircuit.speed - (pumpCircuit.speed % 256) / 256, 0);
|
|
660
|
+
response.setPayloadByte(circuitId + 21, pumpCircuit.speed % 256, 0);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
break;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
msg.isProcessed = true;
|
|
667
|
+
await sys.anslq25Board.sendAsync(response);
|
|
668
|
+
}
|
|
669
|
+
catch (err) {
|
|
670
|
+
logger.error(`ANSLQ25 error processing spa command remote packet. ${err.message}`);
|
|
671
|
+
}
|
|
672
|
+
};
|
|
673
|
+
public async processHighSpeedCircuitsAsync(msg: Inbound) {
|
|
674
|
+
try {
|
|
675
|
+
// 30/158/222
|
|
676
|
+
let response: Outbound = Outbound.create({
|
|
677
|
+
action: 30,
|
|
678
|
+
portId: msg.portId,
|
|
679
|
+
protocol: msg.protocol,
|
|
680
|
+
dest: msg.source,
|
|
681
|
+
source: 16 //msg.dest
|
|
682
|
+
});
|
|
683
|
+
response.appendPayloadBytes(0, 16);
|
|
684
|
+
let pump = sys.pumps.getDualSpeed();
|
|
685
|
+
let pumpCircuits = pump.circuits.get();
|
|
686
|
+
for (let i = 1; i <= pumpCircuits.length; i++) {
|
|
687
|
+
response.setPayloadByte(i, pumpCircuits[i].circuit, 0);
|
|
688
|
+
}
|
|
689
|
+
msg.isProcessed = true;
|
|
690
|
+
await sys.anslq25Board.sendAsync(response);
|
|
691
|
+
}
|
|
692
|
+
catch (err) {
|
|
693
|
+
logger.error(`ANSLQ25 error processing spa command remote packet. ${err.message}`);
|
|
694
|
+
}
|
|
695
|
+
};
|
|
696
|
+
};
|