nodejs-poolcontroller 7.2.0 → 7.5.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.
- package/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/Changelog +13 -0
- package/Dockerfile +1 -0
- package/README.md +5 -5
- package/app.ts +11 -0
- package/config/Config.ts +3 -0
- package/config/VersionCheck.ts +8 -4
- package/controller/Constants.ts +165 -9
- package/controller/Equipment.ts +186 -65
- package/controller/Errors.ts +22 -1
- package/controller/State.ts +273 -57
- package/controller/boards/EasyTouchBoard.ts +194 -95
- package/controller/boards/IntelliCenterBoard.ts +115 -42
- package/controller/boards/IntelliTouchBoard.ts +104 -30
- package/controller/boards/NixieBoard.ts +155 -53
- package/controller/boards/SystemBoard.ts +1529 -514
- package/controller/comms/Comms.ts +219 -42
- package/controller/comms/messages/Messages.ts +16 -4
- package/controller/comms/messages/config/ChlorinatorMessage.ts +13 -3
- package/controller/comms/messages/config/CircuitGroupMessage.ts +6 -0
- package/controller/comms/messages/config/CircuitMessage.ts +1 -1
- package/controller/comms/messages/config/CoverMessage.ts +1 -0
- package/controller/comms/messages/config/EquipmentMessage.ts +4 -0
- package/controller/comms/messages/config/ExternalMessage.ts +43 -25
- package/controller/comms/messages/config/FeatureMessage.ts +8 -1
- package/controller/comms/messages/config/GeneralMessage.ts +8 -0
- package/controller/comms/messages/config/HeaterMessage.ts +15 -9
- package/controller/comms/messages/config/IntellichemMessage.ts +4 -1
- package/controller/comms/messages/config/OptionsMessage.ts +13 -1
- package/controller/comms/messages/config/PumpMessage.ts +4 -20
- package/controller/comms/messages/config/RemoteMessage.ts +4 -0
- package/controller/comms/messages/config/ScheduleMessage.ts +11 -0
- package/controller/comms/messages/config/SecurityMessage.ts +1 -0
- package/controller/comms/messages/config/ValveMessage.ts +12 -2
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +14 -6
- package/controller/comms/messages/status/EquipmentStateMessage.ts +78 -24
- package/controller/comms/messages/status/HeaterStateMessage.ts +25 -5
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +55 -26
- package/controller/nixie/Nixie.ts +18 -16
- package/controller/nixie/NixieEquipment.ts +6 -6
- package/controller/nixie/bodies/Body.ts +7 -4
- package/controller/nixie/bodies/Filter.ts +7 -4
- package/controller/nixie/chemistry/ChemController.ts +800 -283
- package/controller/nixie/chemistry/Chlorinator.ts +22 -14
- package/controller/nixie/circuits/Circuit.ts +42 -7
- package/controller/nixie/heaters/Heater.ts +303 -30
- package/controller/nixie/pumps/Pump.ts +57 -30
- package/controller/nixie/schedules/Schedule.ts +10 -7
- package/controller/nixie/valves/Valve.ts +7 -5
- package/defaultConfig.json +32 -1
- package/issue_template.md +1 -1
- package/logger/DataLogger.ts +37 -22
- package/package.json +20 -18
- package/web/Server.ts +529 -31
- package/web/bindings/influxDB.json +157 -5
- package/web/bindings/mqtt.json +112 -13
- package/web/bindings/mqttAlt.json +109 -11
- package/web/interfaces/baseInterface.ts +2 -1
- package/web/interfaces/httpInterface.ts +2 -0
- package/web/interfaces/influxInterface.ts +103 -54
- package/web/interfaces/mqttInterface.ts +16 -5
- package/web/services/config/Config.ts +179 -43
- package/web/services/state/State.ts +51 -5
- package/web/services/state/StateSocket.ts +19 -2
|
@@ -15,15 +15,15 @@ You should have received a copy of the GNU Affero General Public License
|
|
|
15
15
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
16
|
*/
|
|
17
17
|
import * as extend from 'extend';
|
|
18
|
-
import { SystemBoard, byteValueMap, ConfigQueue, ConfigRequest, BodyCommands, PumpCommands, HeaterCommands, SystemCommands, CircuitCommands, FeatureCommands, ChlorinatorCommands, EquipmentIdRange, ScheduleCommands, ChemControllerCommands } from './SystemBoard';
|
|
19
|
-
import { PoolSystem, Body, Pump, sys, ConfigVersion, Heater, Schedule, EggTimer, ICircuit, CustomNameCollection, CustomName, LightGroup, LightGroupCircuit, Feature, ChemController, Circuit, ScheduleCollection } from '../Equipment';
|
|
20
|
-
import { Protocol, Outbound, Message, Response } from '../comms/messages/Messages';
|
|
21
|
-
import { state, ChlorinatorState, CommsState, State, ICircuitState, ICircuitGroupState, LightGroupState, BodyTempState, FilterState, ScheduleState } from '../State';
|
|
22
18
|
import { logger } from '../../logger/Logger';
|
|
23
19
|
import { conn } from '../comms/Comms';
|
|
24
|
-
import {
|
|
20
|
+
import { Message, Outbound, Protocol, Response } from '../comms/messages/Messages';
|
|
25
21
|
import { utils } from '../Constants';
|
|
22
|
+
import { Body, ChemController, ConfigVersion, CustomName, EggTimer, Feature, Heater, ICircuit, LightGroup, LightGroupCircuit, PoolSystem, Pump, Schedule, sys } from '../Equipment';
|
|
23
|
+
import { EquipmentTimeoutError, InvalidEquipmentDataError, InvalidEquipmentIdError } from '../Errors';
|
|
26
24
|
import { ncp } from "../nixie/Nixie";
|
|
25
|
+
import { BodyTempState, ChlorinatorState, ICircuitGroupState, ICircuitState, LightGroupState, state } from '../State';
|
|
26
|
+
import { BodyCommands, byteValueMap, ChemControllerCommands, ChlorinatorCommands, CircuitCommands, ConfigQueue, ConfigRequest, EquipmentIdRange, FeatureCommands, HeaterCommands, PumpCommands, ScheduleCommands, SystemBoard, SystemCommands } from './SystemBoard';
|
|
27
27
|
|
|
28
28
|
export class EasyTouchBoard extends SystemBoard {
|
|
29
29
|
public needsConfigChanges: boolean = false;
|
|
@@ -162,10 +162,10 @@ export class EasyTouchBoard extends SystemBoard {
|
|
|
162
162
|
// We need this because there is a no-pump thing in *Touch.
|
|
163
163
|
// RKS: 05-04-21 The no-pump item was removed as this was only required for -webClient. deletePumpAsync should remove the pump from operation.
|
|
164
164
|
this.valueMaps.pumpTypes = new byteValueMap([
|
|
165
|
-
[1, { name: 'vf', desc: 'Intelliflo VF', minFlow: 15, maxFlow: 130, flowStepSize: 1, maxCircuits: 8, hasAddress: true }],
|
|
165
|
+
[1, { name: 'vf', desc: 'Intelliflo VF', maxPrimingTime: 6, minFlow: 15, maxFlow: 130, flowStepSize: 1, maxCircuits: 8, hasAddress: true }],
|
|
166
166
|
[64, { name: 'vsf', desc: 'Intelliflo VSF', minSpeed: 450, maxSpeed: 3450, speedStepSize: 10, minFlow: 15, maxFlow: 130, flowStepSize: 1, maxCircuits: 8, hasAddress: true }],
|
|
167
167
|
[65, { name: 'ds', desc: 'Two-Speed', maxCircuits: 40, hasAddress: false, hasBody: true }],
|
|
168
|
-
[128, { name: 'vs', desc: 'Intelliflo VS', maxPrimingTime:
|
|
168
|
+
[128, { name: 'vs', desc: 'Intelliflo VS', maxPrimingTime: 10, minSpeed: 450, maxSpeed: 3450, speedStepSize: 10, maxCircuits: 8, hasAddress: true }],
|
|
169
169
|
[169, { name: 'vssvrs', desc: 'IntelliFlo VS+SVRS', maxPrimingTime: 6, minSpeed: 450, maxSpeed: 3450, speedStepSize: 10, maxCircuits: 8, hasAddress: true }],
|
|
170
170
|
[257, { name: 'ss', desc: 'Single Speed', maxCircuits: 0, hasAddress: false, hasBody: true, equipmentMaster: 1 }],
|
|
171
171
|
[256, { name: 'sf', desc: 'SuperFlo VS', hasAddress: false, maxCircuits: 8, maxRelays: 4, equipmentMaster: 1 }]
|
|
@@ -306,6 +306,14 @@ export class EasyTouchBoard extends SystemBoard {
|
|
|
306
306
|
return extend(true, {}, { val: byte, desc: customName.name, name: customName.name });
|
|
307
307
|
}
|
|
308
308
|
};
|
|
309
|
+
this.valueMaps.panelModes = new byteValueMap([
|
|
310
|
+
[0, { val: 0, name: 'auto', desc: 'Auto' }],
|
|
311
|
+
[1, { val: 1, name: 'service', desc: 'Service' }],
|
|
312
|
+
[8, { val: 8, name: 'freeze', desc: 'Freeze' }],
|
|
313
|
+
[128, { val: 128, name: 'timeout', desc: 'Timeout' }],
|
|
314
|
+
[129, { val: 129, name: 'service-timeout', desc: 'Service/Timeout' }],
|
|
315
|
+
[255, { name: 'error', desc: 'System Error' }]
|
|
316
|
+
]);
|
|
309
317
|
this.valueMaps.expansionBoards = new byteValueMap([
|
|
310
318
|
[0, { name: 'ET28', part: 'ET2-8', desc: 'EasyTouch2 8', circuits: 8, shared: true }],
|
|
311
319
|
[1, { name: 'ET28P', part: 'ET2-8P', desc: 'EasyTouch2 8P', circuits: 8, shared: false }],
|
|
@@ -328,7 +336,7 @@ export class EasyTouchBoard extends SystemBoard {
|
|
|
328
336
|
let sheater = state.heaters.getItemById(1, true);
|
|
329
337
|
sheater.type = heater.type;
|
|
330
338
|
sheater.name = heater.name;
|
|
331
|
-
sheater.isVirtual = heater.isVirtual = false;
|
|
339
|
+
//sheater.isVirtual = heater.isVirtual = false;
|
|
332
340
|
sys.equipment.shared ? heater.body = 32 : heater.body = 0;
|
|
333
341
|
}
|
|
334
342
|
public initBodyDefaults() {
|
|
@@ -337,15 +345,16 @@ export class EasyTouchBoard extends SystemBoard {
|
|
|
337
345
|
// Add in the bodies for the configuration. These need to be set.
|
|
338
346
|
let cbody = sys.bodies.getItemById(i, true);
|
|
339
347
|
let tbody = state.temps.bodies.getItemById(i, true);
|
|
340
|
-
// If the body doesn't represent a spa then we set the type.
|
|
341
|
-
tbody.type = cbody.type = i > 1 && !sys.equipment.shared ? 1 : 0;
|
|
342
348
|
cbody.isActive = true;
|
|
349
|
+
// If the body doesn't represent a spa then we set the type.
|
|
350
|
+
// RSG - 10-5-21: If a single body IT (i5+3s/i9+3s) the bodies are the same; set to pool
|
|
351
|
+
tbody.type = cbody.type = i > 1 && !sys.equipment.shared && sys.equipment.intakeReturnValves ? 1 : 0;
|
|
343
352
|
if (typeof cbody.name === 'undefined') {
|
|
344
353
|
let bt = sys.board.valueMaps.bodyTypes.transform(cbody.type);
|
|
345
354
|
tbody.name = cbody.name = bt.name;
|
|
346
355
|
}
|
|
347
356
|
}
|
|
348
|
-
if (!sys.equipment.shared && !sys.equipment.dual) {
|
|
357
|
+
if (!sys.equipment.shared && !sys.equipment.dual && state.equipment.controllerType !== 'intellitouch') {
|
|
349
358
|
sys.bodies.removeItemById(2);
|
|
350
359
|
state.temps.bodies.removeItemById(2);
|
|
351
360
|
}
|
|
@@ -374,7 +383,7 @@ export class EasyTouchBoard extends SystemBoard {
|
|
|
374
383
|
let md = mod.get();
|
|
375
384
|
eq.maxBodies = md.bodies = typeof mt.bodies !== 'undefined' ? mt.bodies : mt.shared ? 2 : 1;
|
|
376
385
|
eq.maxCircuits = md.circuits = typeof mt.circuits !== 'undefined' ? mt.circuits : 8;
|
|
377
|
-
eq.maxFeatures = md.features = typeof mt.features !== 'undefined' ? mt.features :
|
|
386
|
+
eq.maxFeatures = md.features = typeof mt.features !== 'undefined' ? mt.features : 8;
|
|
378
387
|
eq.maxValves = md.valves = typeof mt.valves !== 'undefined' ? mt.valves : mt.shared ? 4 : 2;
|
|
379
388
|
eq.maxPumps = md.maxPumps = typeof mt.pumps !== 'undefined' ? mt.pumps : 2;
|
|
380
389
|
eq.shared = mt.shared;
|
|
@@ -382,6 +391,7 @@ export class EasyTouchBoard extends SystemBoard {
|
|
|
382
391
|
eq.maxChlorinators = md.chlorinators = 1;
|
|
383
392
|
eq.maxChemControllers = md.chemControllers = 1;
|
|
384
393
|
eq.maxCustomNames = 10;
|
|
394
|
+
eq.intakeReturnValves = md.intakeReturnValves = typeof mt.intakeReturnValves !== 'undefined' ? mt.intakeReturnValves : false;
|
|
385
395
|
// Calculate out the invalid ids.
|
|
386
396
|
sys.board.equipmentIds.invalidIds.set([]);
|
|
387
397
|
if (!eq.shared) sys.board.equipmentIds.invalidIds.merge([1]);
|
|
@@ -454,8 +464,8 @@ export class TouchConfigRequest extends ConfigRequest {
|
|
|
454
464
|
if (typeof items !== 'undefined') this.items.push(...items);
|
|
455
465
|
this.oncomplete = oncomplete;
|
|
456
466
|
}
|
|
457
|
-
|
|
458
|
-
|
|
467
|
+
declare category: TouchConfigCategories;
|
|
468
|
+
declare setcategory: GetTouchConfigCategories;
|
|
459
469
|
}
|
|
460
470
|
export class TouchConfigQueue extends ConfigQueue {
|
|
461
471
|
//protected _configQueueTimer: NodeJS.Timeout;
|
|
@@ -543,7 +553,7 @@ export class TouchConfigQueue extends ConfigQueue {
|
|
|
543
553
|
action: this.curr.setcategory,
|
|
544
554
|
payload: [itm],
|
|
545
555
|
retries: 3,
|
|
546
|
-
response: Response.create({response: true, callback: () => {self.processNext(out);}})
|
|
556
|
+
response: Response.create({ response: true, callback: () => { self.processNext(out); } })
|
|
547
557
|
// response: true,
|
|
548
558
|
// onResponseProcessed: function () { self.processNext(out); }
|
|
549
559
|
});
|
|
@@ -985,7 +995,7 @@ class TouchSystemCommands extends SystemCommands {
|
|
|
985
995
|
if (circ.nameId === data.id + 200) {
|
|
986
996
|
let cstate = state.circuits.getItemById(circ.id);
|
|
987
997
|
cstate.name = circ.name = data.name;
|
|
988
|
-
for (let j = 0; j < state.schedules.length; j++){
|
|
998
|
+
for (let j = 0; j < state.schedules.length; j++) {
|
|
989
999
|
let ssched = state.schedules.getItemByIndex(j);
|
|
990
1000
|
if (ssched.circuit === cstate.id) {
|
|
991
1001
|
ssched.hasChanged = true;
|
|
@@ -999,7 +1009,7 @@ class TouchSystemCommands extends SystemCommands {
|
|
|
999
1009
|
if (cg.nameId === data.id + 200) {
|
|
1000
1010
|
let cgstate = state.circuitGroups.getItemById(cg.id);
|
|
1001
1011
|
cgstate.name = cg.name = data.name;
|
|
1002
|
-
for (let j = 0; j < state.schedules.length; j++){
|
|
1012
|
+
for (let j = 0; j < state.schedules.length; j++) {
|
|
1003
1013
|
let ssched = state.schedules.getItemByIndex(j);
|
|
1004
1014
|
if (ssched.circuit === cgstate.id) {
|
|
1005
1015
|
ssched.hasChanged = true;
|
|
@@ -1013,7 +1023,7 @@ class TouchSystemCommands extends SystemCommands {
|
|
|
1013
1023
|
if (lg.nameId === data.id + 200) {
|
|
1014
1024
|
let lgstate = state.lightGroups.getItemById(lg.id);
|
|
1015
1025
|
lgstate.name = lg.name = data.name;
|
|
1016
|
-
for (let j = 0; j < state.schedules.length; j++){
|
|
1026
|
+
for (let j = 0; j < state.schedules.length; j++) {
|
|
1017
1027
|
let ssched = state.schedules.getItemByIndex(j);
|
|
1018
1028
|
if (ssched.circuit === lgstate.id) {
|
|
1019
1029
|
ssched.hasChanged = true;
|
|
@@ -1027,7 +1037,7 @@ class TouchSystemCommands extends SystemCommands {
|
|
|
1027
1037
|
if (f.nameId === data.id + 200) {
|
|
1028
1038
|
let fstate = state.features.getItemById(f.id);
|
|
1029
1039
|
fstate.name = f.name = data.name;
|
|
1030
|
-
for (let j = 0; j < state.schedules.length; j++){
|
|
1040
|
+
for (let j = 0; j < state.schedules.length; j++) {
|
|
1031
1041
|
let ssched = state.schedules.getItemByIndex(j);
|
|
1032
1042
|
if (ssched.circuit === fstate.id) {
|
|
1033
1043
|
ssched.hasChanged = true;
|
|
@@ -1262,6 +1272,7 @@ export class TouchCircuitCommands extends CircuitCommands {
|
|
|
1262
1272
|
// response: [255,0,255][165,33,34,16,1,1][139][1,133]
|
|
1263
1273
|
let id = parseInt(data.id, 10);
|
|
1264
1274
|
if (isNaN(id)) return Promise.reject(new InvalidEquipmentIdError('Circuit Id is invalid', data.id, 'Feature'));
|
|
1275
|
+
if (id >= 255 || data.master === 1) return super.setCircuitAsync(data);
|
|
1265
1276
|
let circuit = sys.circuits.getInterfaceById(id);
|
|
1266
1277
|
// Alright check to see if we are adding a nixie circuit.
|
|
1267
1278
|
if (id === -1 || circuit.master !== 0) {
|
|
@@ -1291,6 +1302,8 @@ export class TouchCircuitCommands extends CircuitCommands {
|
|
|
1291
1302
|
circuit.type = cstate.type = typeByte;
|
|
1292
1303
|
circuit.eggTimer = typeof data.eggTimer !== 'undefined' ? parseInt(data.eggTimer, 10) : circuit.eggTimer || 720;
|
|
1293
1304
|
circuit.dontStop = (typeof data.dontStop !== 'undefined') ? utils.makeBool(data.dontStop) : circuit.eggTimer === 1620;
|
|
1305
|
+
cstate.isActive = circuit.isActive = true;
|
|
1306
|
+
circuit.master = 0;
|
|
1294
1307
|
let eggTimer = sys.eggTimers.find(elem => elem.circuit === parseInt(data.id, 10));
|
|
1295
1308
|
try {
|
|
1296
1309
|
if (circuit.eggTimer === 720) {
|
|
@@ -1329,6 +1342,15 @@ export class TouchCircuitCommands extends CircuitCommands {
|
|
|
1329
1342
|
if (c.master !== 0) return await super.setCircuitStateAsync(id, val);
|
|
1330
1343
|
if (id === 192 || c.type === 3) return await sys.board.circuits.setLightGroupThemeAsync(id - 191, val ? 1 : 0);
|
|
1331
1344
|
if (id >= 192) return await sys.board.circuits.setCircuitGroupStateAsync(id, val);
|
|
1345
|
+
|
|
1346
|
+
// for some dumb reason, if the spa is on and the pool circuit is desired to be on,
|
|
1347
|
+
// it will ignore the packet.
|
|
1348
|
+
// We can override that by emulating a click to turn off the spa instead of turning
|
|
1349
|
+
// on the pool
|
|
1350
|
+
if (sys.equipment.maxBodies > 1 && id === 6 && val && state.circuits.getItemById(1).isOn) {
|
|
1351
|
+
id = 1;
|
|
1352
|
+
val = false;
|
|
1353
|
+
}
|
|
1332
1354
|
return new Promise<ICircuitState>((resolve, reject) => {
|
|
1333
1355
|
let cstate = state.circuits.getInterfaceById(id);
|
|
1334
1356
|
let out = Outbound.create({
|
|
@@ -1349,6 +1371,7 @@ export class TouchCircuitCommands extends CircuitCommands {
|
|
|
1349
1371
|
});
|
|
1350
1372
|
conn.queueSendMessage(out);
|
|
1351
1373
|
});
|
|
1374
|
+
|
|
1352
1375
|
}
|
|
1353
1376
|
public async setLightGroupStateAsync(id: number, val: boolean): Promise<ICircuitGroupState> { return this.setCircuitGroupStateAsync(id, val); }
|
|
1354
1377
|
public async toggleCircuitStateAsync(id: number) {
|
|
@@ -1529,7 +1552,7 @@ export class TouchCircuitCommands extends CircuitCommands {
|
|
|
1529
1552
|
else if (!cstate.isOn && sys.board.valueMaps.lightThemes.getName(theme) !== 'off') await sys.board.circuits.setCircuitStateAsync(c.circuit, true);
|
|
1530
1553
|
}
|
|
1531
1554
|
let isOn = sys.board.valueMaps.lightThemes.getName(theme) === 'off' ? false : true;
|
|
1532
|
-
sys.board.circuits.setEndTime(grp, sgrp, isOn);
|
|
1555
|
+
sys.board.circuits.setEndTime(grp, sgrp, isOn);
|
|
1533
1556
|
sgrp.isOn = isOn;
|
|
1534
1557
|
switch (theme) {
|
|
1535
1558
|
case 0: // off
|
|
@@ -1643,30 +1666,31 @@ class TouchFeatureCommands extends FeatureCommands {
|
|
|
1643
1666
|
|
|
1644
1667
|
}
|
|
1645
1668
|
class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
1646
|
-
public setChlorAsync(obj: any): Promise<ChlorinatorState> {
|
|
1669
|
+
public async setChlorAsync(obj: any): Promise<ChlorinatorState> {
|
|
1647
1670
|
let id = parseInt(obj.id, 10);
|
|
1648
1671
|
let isAdd = false;
|
|
1649
|
-
let isVirtual = false;
|
|
1650
|
-
if (id <= 0 || isNaN(id)) id = 1;
|
|
1651
1672
|
let chlor = sys.chlorinators.getItemById(id);
|
|
1652
|
-
if (id
|
|
1673
|
+
if (id <= 0 || isNaN(id)) {
|
|
1653
1674
|
isAdd = true;
|
|
1654
|
-
chlor.master = utils.makeBool(obj.
|
|
1675
|
+
chlor.master = utils.makeBool(obj.master) ? 1 : 0;
|
|
1655
1676
|
// Calculate an id for the chlorinator. The messed up part is that if a chlorinator is not attached to the OCP, its address
|
|
1656
1677
|
// cannot be set by the MUX. This will have to wait.
|
|
1657
1678
|
id = 1;
|
|
1658
|
-
}
|
|
1659
|
-
//
|
|
1660
|
-
|
|
1679
|
+
}
|
|
1680
|
+
// If this is a Nixie chlorinator then go to the base class and handle it from there.
|
|
1681
|
+
if (chlor.master === 1) return super.setChlorAsync(obj);
|
|
1661
1682
|
// RKS: I am not even sure this can be done with Touch as the master on the RS485 bus.
|
|
1662
|
-
if (chlor.master ===
|
|
1663
|
-
let name = obj.name || 'IntelliChlor' + id;
|
|
1664
|
-
let poolSetpoint = parseInt(obj.poolSetpoint, 10);
|
|
1665
|
-
let spaSetpoint = parseInt(obj.spaSetpoint, 10);
|
|
1683
|
+
if (typeof chlor.master === 'undefined') chlor.master = 0;
|
|
1684
|
+
let name = obj.name || chlor.name || 'IntelliChlor' + id;
|
|
1666
1685
|
let superChlorHours = parseInt(obj.superChlorHours, 10);
|
|
1667
1686
|
if (typeof obj.superChlorinate !== 'undefined') obj.superChlor = utils.makeBool(obj.superChlorinate);
|
|
1668
1687
|
let superChlorinate = typeof obj.superChlor === 'undefined' ? undefined : utils.makeBool(obj.superChlor);
|
|
1688
|
+
let isDosing = typeof obj.isDosing !== 'undefined' ? utils.makeBool(obj.isDosing) : chlor.isDosing;
|
|
1669
1689
|
let disabled = typeof obj.disabled !== 'undefined' ? utils.makeBool(obj.disabled) : chlor.disabled;
|
|
1690
|
+
let poolSetpoint = typeof obj.poolSetpoint !== 'undefined' ? parseInt(obj.poolSetpoint, 10) : chlor.poolSetpoint;
|
|
1691
|
+
let spaSetpoint = typeof obj.spaSetpoint !== 'undefined' ? parseInt(obj.spaSetpoint, 10) : chlor.spaSetpoint;
|
|
1692
|
+
let model = typeof obj.model !== 'undefined' ? obj.model : chlor.model;
|
|
1693
|
+
let chlorType = typeof obj.type !== 'undefined' ? sys.board.valueMaps.chlorinatorType.encode(obj.type) : chlor.type || 0;
|
|
1670
1694
|
if (isAdd) {
|
|
1671
1695
|
if (isNaN(poolSetpoint)) poolSetpoint = 50;
|
|
1672
1696
|
if (isNaN(spaSetpoint)) spaSetpoint = 10;
|
|
@@ -1674,8 +1698,8 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1674
1698
|
if (typeof superChlorinate === 'undefined') superChlorinate = false;
|
|
1675
1699
|
}
|
|
1676
1700
|
else {
|
|
1677
|
-
if (isNaN(poolSetpoint)) poolSetpoint = chlor.poolSetpoint;
|
|
1678
|
-
if (isNaN(spaSetpoint)) spaSetpoint = chlor.spaSetpoint;
|
|
1701
|
+
if (isNaN(poolSetpoint)) poolSetpoint = chlor.poolSetpoint || 0;
|
|
1702
|
+
if (isNaN(spaSetpoint)) spaSetpoint = chlor.spaSetpoint || 0;
|
|
1679
1703
|
if (isNaN(superChlorHours)) superChlorHours = chlor.superChlorHours;
|
|
1680
1704
|
if (typeof superChlorinate === 'undefined') superChlorinate = utils.makeBool(chlor.superChlor);
|
|
1681
1705
|
}
|
|
@@ -1691,55 +1715,96 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1691
1715
|
if (poolSetpoint > 100 || poolSetpoint < 0) return Promise.reject(new InvalidEquipmentDataError(`Chlorinator poolSetpoint is out of range: ${chlor.poolSetpoint}`, 'chlorinator', chlor.poolSetpoint));
|
|
1692
1716
|
if (spaSetpoint > 100 || spaSetpoint < 0) return Promise.reject(new InvalidEquipmentDataError(`Chlorinator spaSetpoint is out of range: ${chlor.poolSetpoint}`, 'chlorinator', chlor.spaSetpoint));
|
|
1693
1717
|
if (typeof obj.ignoreSaltReading !== 'undefined') chlor.ignoreSaltReading = utils.makeBool(obj.ignoreSaltReading);
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1718
|
+
|
|
1719
|
+
let _timeout: NodeJS.Timeout;
|
|
1720
|
+
try {
|
|
1721
|
+
let request153packet = new Promise<void>((resolve, reject) => {
|
|
1722
|
+
let out = Outbound.create({
|
|
1723
|
+
dest: 16,
|
|
1724
|
+
action: 153,
|
|
1725
|
+
// removed disable ? 0 : (spaSetpoint << 1) + 1 because only deleteChlorAsync should remove it from the OCP
|
|
1726
|
+
payload: [(disabled ? 0 : isDosing ? 100 << 1: spaSetpoint << 1) + 1, disabled ? 0 : isDosing ? 100 : poolSetpoint,
|
|
1727
|
+
utils.makeBool(superChlorinate) && superChlorHours > 0 ? superChlorHours + 128 : 0, // We only want to set the superChlor when the user sends superChlor = true
|
|
1728
|
+
0, 0, 0, 0, 0, 0, 0],
|
|
1729
|
+
retries: 3,
|
|
1730
|
+
response: true,
|
|
1731
|
+
// scope: Math.random(),
|
|
1732
|
+
onComplete: (err)=>{
|
|
1733
|
+
if (err) {
|
|
1734
|
+
logger.error(`Error setting Chlorinator values: ${err.message}`);
|
|
1735
|
+
// in case of race condition
|
|
1736
|
+
if (typeof reject !== 'undefined') reject(err);
|
|
1737
|
+
reject = undefined;
|
|
1738
|
+
}
|
|
1739
|
+
else {
|
|
1740
|
+
resolve();
|
|
1741
|
+
resolve = undefined;
|
|
1742
|
+
}
|
|
1707
1743
|
}
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1744
|
+
});
|
|
1745
|
+
conn.queueSendMessage(out);
|
|
1746
|
+
_timeout = setTimeout(()=>{
|
|
1747
|
+
if (typeof reject === 'undefined' || typeof resolve === 'undefined') return;
|
|
1748
|
+
reject(new EquipmentTimeoutError(`no chlor response in 7 seconds`, `chlorTimeOut`));
|
|
1749
|
+
reject = undefined;
|
|
1750
|
+
|
|
1751
|
+
}, 3000);
|
|
1752
|
+
});
|
|
1753
|
+
await request153packet;
|
|
1754
|
+
let schlor = state.chlorinators.getItemById(id, true);
|
|
1755
|
+
chlor.disabled = disabled;
|
|
1756
|
+
schlor.isActive = chlor.isActive = true;
|
|
1757
|
+
schlor.superChlor = chlor.superChlor = superChlorinate;
|
|
1758
|
+
schlor.poolSetpoint = chlor.poolSetpoint = poolSetpoint;
|
|
1759
|
+
schlor.spaSetpoint = chlor.spaSetpoint = spaSetpoint;
|
|
1760
|
+
schlor.superChlorHours = chlor.superChlorHours = superChlorHours;
|
|
1761
|
+
schlor.body = chlor.body = body;
|
|
1762
|
+
chlor.address = 79 + id;
|
|
1763
|
+
chlor.name = schlor.name = name;
|
|
1764
|
+
chlor.model = model;
|
|
1765
|
+
schlor.type = chlor.type = chlorType;
|
|
1766
|
+
chlor.isDosing = isDosing;
|
|
1717
1767
|
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1768
|
+
let request217Packet = new Promise<void>((resolve, reject) => {
|
|
1769
|
+
let out = Outbound.create({
|
|
1770
|
+
dest: 16,
|
|
1771
|
+
action: 217,
|
|
1772
|
+
payload: [0],
|
|
1773
|
+
retries: 3,
|
|
1774
|
+
// scope: Math.random(),
|
|
1775
|
+
response: true,
|
|
1776
|
+
onComplete: (err) => {
|
|
1777
|
+
// if (typeof reject === 'undefined') {
|
|
1778
|
+
// logger.error(`reject chlor already called.`)
|
|
1779
|
+
// }
|
|
1780
|
+
if (err) {
|
|
1781
|
+
logger.error(`Error requesting chlor status: ${err.message}`);
|
|
1782
|
+
reject(err);
|
|
1732
1783
|
}
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1784
|
+
else{
|
|
1785
|
+
resolve();
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
})
|
|
1789
|
+
conn.queueSendMessage(out);
|
|
1736
1790
|
});
|
|
1737
|
-
|
|
1738
|
-
|
|
1791
|
+
await request217Packet;
|
|
1792
|
+
if (typeof _timeout !== 'undefined'){
|
|
1793
|
+
clearTimeout(_timeout);
|
|
1794
|
+
_timeout = undefined;
|
|
1795
|
+
}
|
|
1796
|
+
state.emitEquipmentChanges();
|
|
1797
|
+
return state.chlorinators.getItemById(id);
|
|
1798
|
+
} catch (err) {
|
|
1799
|
+
logger.error(`*Touch setChlorAsync Error: ${err.message}`);
|
|
1800
|
+
return Promise.reject(err);
|
|
1801
|
+
}
|
|
1739
1802
|
}
|
|
1740
1803
|
public async deleteChlorAsync(obj: any): Promise<ChlorinatorState> {
|
|
1741
1804
|
let id = parseInt(obj.id, 10);
|
|
1742
|
-
if (isNaN(id)) obj.id
|
|
1805
|
+
if (isNaN(id)) return Promise.reject(new InvalidEquipmentDataError(`Chlorinator id is not valid: ${obj.id}`, 'chlorinator', obj.id));
|
|
1806
|
+
let chlor = sys.chlorinators.getItemById(id);
|
|
1807
|
+
if (chlor.master === 1) return await super.deleteChlorAsync(obj);
|
|
1743
1808
|
return new Promise<ChlorinatorState>((resolve, reject) => {
|
|
1744
1809
|
let out = Outbound.create({
|
|
1745
1810
|
dest: 16,
|
|
@@ -1753,8 +1818,9 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1753
1818
|
reject(err);
|
|
1754
1819
|
}
|
|
1755
1820
|
else {
|
|
1756
|
-
|
|
1757
|
-
let
|
|
1821
|
+
ncp.chlorinators.deleteChlorinatorAsync(id).then(()=>{});
|
|
1822
|
+
let cstate = state.chlorinators.getItemById(id, true);
|
|
1823
|
+
chlor = sys.chlorinators.getItemById(id, true);
|
|
1758
1824
|
chlor.isActive = cstate.isActive = false;
|
|
1759
1825
|
sys.chlorinators.removeItemById(id);
|
|
1760
1826
|
state.chlorinators.removeItemById(id);
|
|
@@ -1896,10 +1962,11 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
1896
1962
|
}
|
|
1897
1963
|
}
|
|
1898
1964
|
isAdd = true;
|
|
1965
|
+
pump = sys.pumps.getItemById(id, true);
|
|
1899
1966
|
}
|
|
1900
1967
|
else {
|
|
1901
1968
|
pump = sys.pumps.getItemById(id, false);
|
|
1902
|
-
if (data.master > 0 || pump.master > 0
|
|
1969
|
+
if (data.master > 0 || pump.master > 0) return await super.setPumpAsync(data);
|
|
1903
1970
|
ntype = typeof data.type === 'undefined' ? pump.type : parseInt(data.type, 10);
|
|
1904
1971
|
if (isNaN(ntype)) return Promise.reject(new InvalidEquipmentDataError(`Pump type ${data.type} is not valid`, 'Pump', data));
|
|
1905
1972
|
type = sys.board.valueMaps.pumpTypes.transform(ntype);
|
|
@@ -1930,7 +1997,6 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
1930
1997
|
if (type.name === 'ss') {
|
|
1931
1998
|
// The OCP doesn't deal with single speed pumps. Simply add it to the config.
|
|
1932
1999
|
data.circuits = [];
|
|
1933
|
-
pump = sys.pumps.getItemById(id, true);
|
|
1934
2000
|
pump.set(pump);
|
|
1935
2001
|
let spump = state.pumps.getItemById(id, true);
|
|
1936
2002
|
for (let prop in spump) {
|
|
@@ -1962,21 +2028,25 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
1962
2028
|
retries: 2,
|
|
1963
2029
|
response: Response.create({ action: 1, payload: [155] })
|
|
1964
2030
|
});
|
|
1965
|
-
outc.appendPayloadByte(typeof type.maxPrimingTime !== 'undefined' ? data.primingTime : 0, pump.primingTime | 0);
|
|
1966
2031
|
outc.appendPayloadBytes(0, 44);
|
|
1967
|
-
if (
|
|
2032
|
+
if (type.val === 128){
|
|
2033
|
+
outc.setPayloadByte(3, 2);
|
|
2034
|
+
}
|
|
2035
|
+
if (typeof type.maxPrimingTime !== 'undefined' && type.maxPrimingTime > 0 && type.val >=64) {
|
|
2036
|
+
outc.setPayloadByte(2, parseInt(data.primingTime, 10), pump.primingTime || 1);
|
|
1968
2037
|
let primingSpeed = typeof data.primingSpeed !== 'undefined' ? parseInt(data.primingSpeed, 10) : pump.primingSpeed || type.minSpeed;
|
|
1969
2038
|
outc.setPayloadByte(21, Math.floor(primingSpeed / 256));
|
|
1970
|
-
outc.setPayloadByte(30, primingSpeed
|
|
2039
|
+
outc.setPayloadByte(30, primingSpeed % 256);
|
|
1971
2040
|
}
|
|
1972
|
-
if (type.val
|
|
2041
|
+
if (type.val === 1) { // Any VF pump.
|
|
1973
2042
|
outc.setPayloadByte(1, parseInt(data.backgroundCircuit, 10), pump.backgroundCircuit || 6);
|
|
2043
|
+
outc.setPayloadByte(2, parseInt(data.filterSize, 10) / 1000, pump.filterSize / 1000 || 15);
|
|
2044
|
+
// outc.setPayloadByte(2, body.capacity / 1000, 15); RSG - This is filter size, which may or may not equal the body size.
|
|
1974
2045
|
outc.setPayloadByte(3, parseInt(data.turnovers, 10), pump.turnovers || 2);
|
|
1975
2046
|
let body = sys.bodies.getItemById(1, sys.equipment.maxBodies >= 1);
|
|
1976
|
-
outc.setPayloadByte(2, body.capacity / 1000, 15);
|
|
1977
2047
|
outc.setPayloadByte(21, parseInt(data.manualFilterGPM, 10), pump.manualFilterGPM || 30);
|
|
1978
2048
|
outc.setPayloadByte(22, parseInt(data.primingSpeed, 10), pump.primingSpeed || 55);
|
|
1979
|
-
let primingTime = typeof data.primingTime !== 'undefined' ? parseInt(data.primingTime, 10) : pump.primingTime;
|
|
2049
|
+
let primingTime = typeof data.primingTime !== 'undefined' ? parseInt(data.primingTime, 10) : pump.primingTime || 0;
|
|
1980
2050
|
let maxSystemTime = typeof data.maxSystemTime !== 'undefined' ? parseInt(data.maxSystemTime, 10) : pump.maxSystemTime;
|
|
1981
2051
|
outc.setPayloadByte(23, primingTime | maxSystemTime << 4, 5);
|
|
1982
2052
|
outc.setPayloadByte(24, parseInt(data.maxPressureIncrease, 10), pump.maxPressureIncrease || 10);
|
|
@@ -1984,7 +2054,7 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
1984
2054
|
outc.setPayloadByte(26, parseInt(data.backwashTime, 10), pump.backwashTime || 5);
|
|
1985
2055
|
outc.setPayloadByte(27, parseInt(data.rinseTime, 10), pump.rinseTime || 1);
|
|
1986
2056
|
outc.setPayloadByte(28, parseInt(data.vacuumFlow, 10), pump.vacuumFlow || 50);
|
|
1987
|
-
outc.setPayloadByte(
|
|
2057
|
+
outc.setPayloadByte(30, parseInt(data.vacuumTime, 10), pump.vacuumTime || 10);
|
|
1988
2058
|
}
|
|
1989
2059
|
if (typeof type.maxCircuits !== 'undefined' && type.maxCircuits > 0 && typeof data.circuits !== 'undefined') { // This pump type supports circuits
|
|
1990
2060
|
for (let i = 1; i <= data.circuits.length && i <= type.maxCircuits; i++) {
|
|
@@ -1997,7 +2067,7 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
1997
2067
|
c.units = parseInt(c.units, 10) || type.name === 'vf' ? sys.board.valueMaps.pumpUnits.getValue('gpm') : sys.board.valueMaps.pumpUnits.getValue('rpm');
|
|
1998
2068
|
if (typeof type.minSpeed !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('rpm')) {
|
|
1999
2069
|
outc.setPayloadByte(i * 2 + 4, Math.floor(speed / 256)); // Set to rpm
|
|
2000
|
-
outc.setPayloadByte(i + 21, speed
|
|
2070
|
+
outc.setPayloadByte(i + 21, speed % 256);
|
|
2001
2071
|
c.speed = speed;
|
|
2002
2072
|
}
|
|
2003
2073
|
else if (typeof type.minFlow !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('gpm')) {
|
|
@@ -2034,7 +2104,7 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
2034
2104
|
// [165,33,16,34,155,46],[1,128,0,2,0,16,12,6,7,1,9,4,11,11,3,128,8,0,2,18,2,3,128,8,196,184,232,152,188,238,232,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[9,75]
|
|
2035
2105
|
const setPumpConfig = Outbound.create({
|
|
2036
2106
|
action: 155,
|
|
2037
|
-
payload: [pump.id, pump.type, 0,
|
|
2107
|
+
payload: [pump.id, pump.type, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
2038
2108
|
retries: 2,
|
|
2039
2109
|
response: true
|
|
2040
2110
|
});
|
|
@@ -2110,6 +2180,34 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
2110
2180
|
spump.type = pump.type;
|
|
2111
2181
|
spump.status = 0;
|
|
2112
2182
|
}
|
|
2183
|
+
public async deletePumpAsync(pump: Pump):Promise<Pump>{
|
|
2184
|
+
let id = pump.id;
|
|
2185
|
+
if (isNaN(id)) return Promise.reject(new InvalidEquipmentIdError(`DeletePumpAsync: Pump ${id} is not valid.`, 0, `pump`))
|
|
2186
|
+
const outc = Outbound.create({
|
|
2187
|
+
action: 155,
|
|
2188
|
+
payload: [id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
2189
|
+
retries: 2,
|
|
2190
|
+
response: true
|
|
2191
|
+
});
|
|
2192
|
+
return new Promise<Pump>((resolve, reject) => {
|
|
2193
|
+
outc.onComplete = (err, msg) => {
|
|
2194
|
+
if (err) reject(err);
|
|
2195
|
+
else {
|
|
2196
|
+
sys.pumps.removeItemById(id);
|
|
2197
|
+
state.pumps.removeItemById(id);
|
|
2198
|
+
resolve(sys.pumps.getItemById(id,false));
|
|
2199
|
+
const pumpConfigRequest = Outbound.create({
|
|
2200
|
+
action: 216,
|
|
2201
|
+
payload: [id],
|
|
2202
|
+
retries: 2,
|
|
2203
|
+
response: true
|
|
2204
|
+
});
|
|
2205
|
+
conn.queueSendMessage(pumpConfigRequest);
|
|
2206
|
+
}
|
|
2207
|
+
};
|
|
2208
|
+
conn.queueSendMessage(outc);
|
|
2209
|
+
});
|
|
2210
|
+
}
|
|
2113
2211
|
}
|
|
2114
2212
|
class TouchHeaterCommands extends HeaterCommands {
|
|
2115
2213
|
public getInstalledHeaterTypes(body?: number): any {
|
|
@@ -2170,13 +2268,14 @@ class TouchHeaterCommands extends HeaterCommands {
|
|
|
2170
2268
|
}
|
|
2171
2269
|
// RKS: Not sure what to do with this as the heater data for Touch isn't actually processed anywhere.
|
|
2172
2270
|
public async setHeaterAsync(obj: any): Promise<Heater> {
|
|
2271
|
+
if (obj.master === 1 || parseInt(obj.id, 10) > 255) return super.setHeaterAsync(obj);
|
|
2173
2272
|
return new Promise<Heater>((resolve, reject) => {
|
|
2174
2273
|
let id = typeof obj.id === 'undefined' ? -1 : parseInt(obj.id, 10);
|
|
2175
2274
|
if (isNaN(id)) return reject(new InvalidEquipmentIdError('Heater Id is not valid.', obj.id, 'Heater'));
|
|
2176
2275
|
let heater: Heater;
|
|
2177
2276
|
if (id <= 0) {
|
|
2178
2277
|
// We are adding a heater. In this case all heaters are virtual.
|
|
2179
|
-
let heaters = sys.heaters.filter(h => h.
|
|
2278
|
+
let heaters = sys.heaters.filter(h => h.master === 1);
|
|
2180
2279
|
id = heaters.getMaxId() + 1;
|
|
2181
2280
|
}
|
|
2182
2281
|
heater = sys.heaters.getItemById(id, true);
|
|
@@ -2187,7 +2286,7 @@ class TouchHeaterCommands extends HeaterCommands {
|
|
|
2187
2286
|
}
|
|
2188
2287
|
}
|
|
2189
2288
|
let hstate = state.heaters.getItemById(id, true);
|
|
2190
|
-
|
|
2289
|
+
|
|
2191
2290
|
hstate.name = heater.name;
|
|
2192
2291
|
hstate.type = heater.type;
|
|
2193
2292
|
heater.master = 1;
|
|
@@ -2197,7 +2296,7 @@ class TouchHeaterCommands extends HeaterCommands {
|
|
|
2197
2296
|
});
|
|
2198
2297
|
}
|
|
2199
2298
|
public async deleteHeaterAsync(obj: any): Promise<Heater> {
|
|
2200
|
-
if (utils.makeBool(obj.
|
|
2299
|
+
if (utils.makeBool(obj.master === 1 || parseInt(obj.id, 10) > 255)) return super.deleteHeaterAsync(obj);
|
|
2201
2300
|
return new Promise<Heater>((resolve, reject) => {
|
|
2202
2301
|
let id = parseInt(obj.id, 10);
|
|
2203
2302
|
if (isNaN(id)) return reject(new InvalidEquipmentIdError('Cannot delete. Heater Id is not valid.', obj.id, 'Heater'));
|
|
@@ -2283,7 +2382,7 @@ class TouchChemControllerCommands extends ChemControllerCommands {
|
|
|
2283
2382
|
// Now lets do all our validation to the incoming chem controller data.
|
|
2284
2383
|
let name = typeof data.name !== 'undefined' ? data.name : chem.name || `IntelliChem - ${address - 143}`;
|
|
2285
2384
|
let type = sys.board.valueMaps.chemControllerTypes.transformByName('intellichem');
|
|
2286
|
-
// So now we are down to the nitty gritty setting the data for the REM
|
|
2385
|
+
// So now we are down to the nitty gritty setting the data for the REM Chem controller.
|
|
2287
2386
|
let calciumHardness = typeof data.calciumHardness !== 'undefined' ? parseInt(data.calciumHardness, 10) : chem.calciumHardness;
|
|
2288
2387
|
let cyanuricAcid = typeof data.cyanuricAcid !== 'undefined' ? parseInt(data.cyanuricAcid, 10) : chem.cyanuricAcid;
|
|
2289
2388
|
let alkalinity = typeof data.alkalinity !== 'undefined' ? parseInt(data.alkalinity, 10) : chem.alkalinity;
|
|
@@ -2336,7 +2435,7 @@ class TouchChemControllerCommands extends ChemControllerCommands {
|
|
|
2336
2435
|
action: 211,
|
|
2337
2436
|
payload: [],
|
|
2338
2437
|
retries: 3, // We are going to try 4 times.
|
|
2339
|
-
response: Response.create({ protocol: Protocol.IntelliChem, action: 1, payload:[211] }),
|
|
2438
|
+
response: Response.create({ protocol: Protocol.IntelliChem, action: 1, payload: [211] }),
|
|
2340
2439
|
onAbort: () => { },
|
|
2341
2440
|
onComplete: (err) => {
|
|
2342
2441
|
if (err) reject(err);
|
|
@@ -2364,7 +2463,7 @@ class TouchChemControllerCommands extends ChemControllerCommands {
|
|
|
2364
2463
|
chem.orp.tolerance.high = orpTolerance.high;
|
|
2365
2464
|
chem.ph.setpoint = pHSetpoint;
|
|
2366
2465
|
chem.orp.setpoint = orpSetpoint;
|
|
2367
|
-
chem.siCalcType = siCalcType;
|
|
2466
|
+
schem.siCalcType = chem.siCalcType = siCalcType;
|
|
2368
2467
|
chem.address = schem.address = address;
|
|
2369
2468
|
chem.name = schem.name = name;
|
|
2370
2469
|
chem.flowSensor.enabled = false;
|