nodejs-poolcontroller 7.3.0 → 7.6.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/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/Changelog +23 -0
- package/README.md +5 -5
- package/app.ts +2 -0
- package/config/Config.ts +3 -0
- package/config/VersionCheck.ts +8 -4
- package/controller/Constants.ts +88 -0
- package/controller/Equipment.ts +246 -66
- package/controller/Errors.ts +24 -1
- package/controller/Lockouts.ts +423 -0
- package/controller/State.ts +314 -54
- package/controller/boards/EasyTouchBoard.ts +107 -59
- package/controller/boards/IntelliCenterBoard.ts +186 -125
- package/controller/boards/IntelliTouchBoard.ts +104 -30
- package/controller/boards/NixieBoard.ts +721 -159
- package/controller/boards/SystemBoard.ts +2370 -1108
- package/controller/comms/Comms.ts +85 -10
- package/controller/comms/messages/Messages.ts +10 -4
- package/controller/comms/messages/config/ChlorinatorMessage.ts +13 -4
- package/controller/comms/messages/config/CircuitGroupMessage.ts +6 -0
- 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 +44 -26
- 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 +13 -3
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +2 -3
- package/controller/comms/messages/status/EquipmentStateMessage.ts +78 -24
- package/controller/comms/messages/status/HeaterStateMessage.ts +42 -9
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +37 -26
- package/controller/nixie/Nixie.ts +18 -16
- package/controller/nixie/bodies/Body.ts +4 -1
- package/controller/nixie/chemistry/ChemController.ts +80 -77
- package/controller/nixie/chemistry/Chlorinator.ts +9 -8
- package/controller/nixie/circuits/Circuit.ts +55 -6
- package/controller/nixie/heaters/Heater.ts +192 -32
- package/controller/nixie/pumps/Pump.ts +146 -84
- package/controller/nixie/schedules/Schedule.ts +3 -2
- package/controller/nixie/valves/Valve.ts +1 -1
- 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 +520 -29
- package/web/bindings/influxDB.json +96 -8
- package/web/bindings/mqtt.json +151 -40
- package/web/bindings/mqttAlt.json +114 -4
- package/web/interfaces/httpInterface.ts +2 -0
- package/web/interfaces/influxInterface.ts +36 -19
- package/web/interfaces/mqttInterface.ts +14 -3
- package/web/services/config/Config.ts +171 -44
- package/web/services/state/State.ts +49 -5
- package/web/services/state/StateSocket.ts +18 -1
|
@@ -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 }],
|
|
@@ -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;
|
|
@@ -1243,18 +1253,20 @@ class TouchBodyCommands extends BodyCommands {
|
|
|
1243
1253
|
}
|
|
1244
1254
|
}
|
|
1245
1255
|
export class TouchCircuitCommands extends CircuitCommands {
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1256
|
+
// RKS: 12-01-2021 This has been deprecated we are now driving this through metadata on the valuemaps. This allows
|
|
1257
|
+
// for multiple types of standardized on/off sequences with nixie controllers.
|
|
1258
|
+
//public getLightThemes(type?: number): any[] {
|
|
1259
|
+
// let themes = sys.board.valueMaps.lightThemes.toArray();
|
|
1260
|
+
// if (typeof type === 'undefined') return themes;
|
|
1261
|
+
// switch (type) {
|
|
1262
|
+
// case 8: // Magicstream
|
|
1263
|
+
// return themes.filter(theme => theme.types.includes('magicstream'));
|
|
1264
|
+
// case 16: // Intellibrite
|
|
1265
|
+
// return themes.filter(theme => theme.types.includes('intellibrite'));
|
|
1266
|
+
// default:
|
|
1267
|
+
// return [];
|
|
1268
|
+
// }
|
|
1269
|
+
//}
|
|
1258
1270
|
public async setCircuitAsync(data: any): Promise<ICircuit> {
|
|
1259
1271
|
try {
|
|
1260
1272
|
// example [255,0,255][165,33,16,34,139,5][17,14,209,0,0][2,120]
|
|
@@ -1262,6 +1274,7 @@ export class TouchCircuitCommands extends CircuitCommands {
|
|
|
1262
1274
|
// response: [255,0,255][165,33,34,16,1,1][139][1,133]
|
|
1263
1275
|
let id = parseInt(data.id, 10);
|
|
1264
1276
|
if (isNaN(id)) return Promise.reject(new InvalidEquipmentIdError('Circuit Id is invalid', data.id, 'Feature'));
|
|
1277
|
+
if (id >= 255 || data.master === 1) return super.setCircuitAsync(data);
|
|
1265
1278
|
let circuit = sys.circuits.getInterfaceById(id);
|
|
1266
1279
|
// Alright check to see if we are adding a nixie circuit.
|
|
1267
1280
|
if (id === -1 || circuit.master !== 0) {
|
|
@@ -1291,6 +1304,8 @@ export class TouchCircuitCommands extends CircuitCommands {
|
|
|
1291
1304
|
circuit.type = cstate.type = typeByte;
|
|
1292
1305
|
circuit.eggTimer = typeof data.eggTimer !== 'undefined' ? parseInt(data.eggTimer, 10) : circuit.eggTimer || 720;
|
|
1293
1306
|
circuit.dontStop = (typeof data.dontStop !== 'undefined') ? utils.makeBool(data.dontStop) : circuit.eggTimer === 1620;
|
|
1307
|
+
cstate.isActive = circuit.isActive = true;
|
|
1308
|
+
circuit.master = 0;
|
|
1294
1309
|
let eggTimer = sys.eggTimers.find(elem => elem.circuit === parseInt(data.id, 10));
|
|
1295
1310
|
try {
|
|
1296
1311
|
if (circuit.eggTimer === 720) {
|
|
@@ -1323,7 +1338,7 @@ export class TouchCircuitCommands extends CircuitCommands {
|
|
|
1323
1338
|
data.functionId = sys.board.valueMaps.circuitFunctions.getValue('notused');
|
|
1324
1339
|
return this.setCircuitAsync(data);
|
|
1325
1340
|
}
|
|
1326
|
-
public async setCircuitStateAsync(id: number, val: boolean): Promise<ICircuitState> {
|
|
1341
|
+
public async setCircuitStateAsync(id: number, val: boolean, ignoreDelays?: boolean): Promise<ICircuitState> {
|
|
1327
1342
|
if (isNaN(id)) return Promise.reject(new InvalidEquipmentIdError('Circuit or Feature id not valid', id, 'Circuit'));
|
|
1328
1343
|
let c = sys.circuits.getInterfaceById(id);
|
|
1329
1344
|
if (c.master !== 0) return await super.setCircuitStateAsync(id, val);
|
|
@@ -1656,28 +1671,26 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1656
1671
|
public async setChlorAsync(obj: any): Promise<ChlorinatorState> {
|
|
1657
1672
|
let id = parseInt(obj.id, 10);
|
|
1658
1673
|
let isAdd = false;
|
|
1659
|
-
let isVirtual = false;
|
|
1660
|
-
if (id <= 0 || isNaN(id)) id = 1;
|
|
1661
1674
|
let chlor = sys.chlorinators.getItemById(id);
|
|
1662
|
-
if (id
|
|
1675
|
+
if (id <= 0 || isNaN(id)) {
|
|
1663
1676
|
isAdd = true;
|
|
1664
|
-
chlor.master = utils.makeBool(obj.
|
|
1677
|
+
chlor.master = utils.makeBool(obj.master) ? 1 : 0;
|
|
1665
1678
|
// Calculate an id for the chlorinator. The messed up part is that if a chlorinator is not attached to the OCP, its address
|
|
1666
1679
|
// cannot be set by the MUX. This will have to wait.
|
|
1667
1680
|
id = 1;
|
|
1668
|
-
}
|
|
1669
|
-
//
|
|
1670
|
-
|
|
1681
|
+
}
|
|
1682
|
+
// If this is a Nixie chlorinator then go to the base class and handle it from there.
|
|
1683
|
+
if (chlor.master === 1) return super.setChlorAsync(obj);
|
|
1671
1684
|
// RKS: I am not even sure this can be done with Touch as the master on the RS485 bus.
|
|
1672
|
-
if (chlor.master ===
|
|
1685
|
+
if (typeof chlor.master === 'undefined') chlor.master = 0;
|
|
1673
1686
|
let name = obj.name || chlor.name || 'IntelliChlor' + id;
|
|
1674
|
-
let poolSetpoint = parseInt(obj.poolSetpoint, 10);
|
|
1675
|
-
let spaSetpoint = parseInt(obj.spaSetpoint, 10);
|
|
1676
1687
|
let superChlorHours = parseInt(obj.superChlorHours, 10);
|
|
1677
1688
|
if (typeof obj.superChlorinate !== 'undefined') obj.superChlor = utils.makeBool(obj.superChlorinate);
|
|
1678
1689
|
let superChlorinate = typeof obj.superChlor === 'undefined' ? undefined : utils.makeBool(obj.superChlor);
|
|
1679
|
-
let disabled = typeof obj.disabled !== 'undefined' ? utils.makeBool(obj.disabled) : chlor.disabled;
|
|
1680
1690
|
let isDosing = typeof obj.isDosing !== 'undefined' ? utils.makeBool(obj.isDosing) : chlor.isDosing;
|
|
1691
|
+
let disabled = typeof obj.disabled !== 'undefined' ? utils.makeBool(obj.disabled) : chlor.disabled;
|
|
1692
|
+
let poolSetpoint = typeof obj.poolSetpoint !== 'undefined' ? parseInt(obj.poolSetpoint, 10) : chlor.poolSetpoint;
|
|
1693
|
+
let spaSetpoint = typeof obj.spaSetpoint !== 'undefined' ? parseInt(obj.spaSetpoint, 10) : chlor.spaSetpoint;
|
|
1681
1694
|
let model = typeof obj.model !== 'undefined' ? obj.model : chlor.model;
|
|
1682
1695
|
let chlorType = typeof obj.type !== 'undefined' ? sys.board.valueMaps.chlorinatorType.encode(obj.type) : chlor.type || 0;
|
|
1683
1696
|
if (isAdd) {
|
|
@@ -1704,20 +1717,15 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1704
1717
|
if (poolSetpoint > 100 || poolSetpoint < 0) return Promise.reject(new InvalidEquipmentDataError(`Chlorinator poolSetpoint is out of range: ${chlor.poolSetpoint}`, 'chlorinator', chlor.poolSetpoint));
|
|
1705
1718
|
if (spaSetpoint > 100 || spaSetpoint < 0) return Promise.reject(new InvalidEquipmentDataError(`Chlorinator spaSetpoint is out of range: ${chlor.poolSetpoint}`, 'chlorinator', chlor.spaSetpoint));
|
|
1706
1719
|
if (typeof obj.ignoreSaltReading !== 'undefined') chlor.ignoreSaltReading = utils.makeBool(obj.ignoreSaltReading);
|
|
1720
|
+
|
|
1707
1721
|
let _timeout: NodeJS.Timeout;
|
|
1708
1722
|
try {
|
|
1709
1723
|
let request153packet = new Promise<void>((resolve, reject) => {
|
|
1710
|
-
_timeout = setTimeout(()=>{
|
|
1711
|
-
if (typeof reject === 'undefined' || typeof resolve === 'undefined') return;
|
|
1712
|
-
reject(new EquipmentTimeoutError(`no chlor response in 7 seconds`, `chlorTimeOut`));
|
|
1713
|
-
reject = undefined;
|
|
1714
|
-
|
|
1715
|
-
}, 3000);
|
|
1716
1724
|
let out = Outbound.create({
|
|
1717
1725
|
dest: 16,
|
|
1718
1726
|
action: 153,
|
|
1719
1727
|
// removed disable ? 0 : (spaSetpoint << 1) + 1 because only deleteChlorAsync should remove it from the OCP
|
|
1720
|
-
payload: [(spaSetpoint << 1) + 1, disabled ? 0 : poolSetpoint,
|
|
1728
|
+
payload: [(disabled ? 0 : isDosing ? 100 << 1: spaSetpoint << 1) + 1, disabled ? 0 : isDosing ? 100 : poolSetpoint,
|
|
1721
1729
|
utils.makeBool(superChlorinate) && superChlorHours > 0 ? superChlorHours + 128 : 0, // We only want to set the superChlor when the user sends superChlor = true
|
|
1722
1730
|
0, 0, 0, 0, 0, 0, 0],
|
|
1723
1731
|
retries: 3,
|
|
@@ -1731,13 +1739,18 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1731
1739
|
reject = undefined;
|
|
1732
1740
|
}
|
|
1733
1741
|
else {
|
|
1734
|
-
logger.debug(`chlor response 153`);
|
|
1735
1742
|
resolve();
|
|
1736
1743
|
resolve = undefined;
|
|
1737
1744
|
}
|
|
1738
1745
|
}
|
|
1739
1746
|
});
|
|
1740
1747
|
conn.queueSendMessage(out);
|
|
1748
|
+
_timeout = setTimeout(()=>{
|
|
1749
|
+
if (typeof reject === 'undefined' || typeof resolve === 'undefined') return;
|
|
1750
|
+
reject(new EquipmentTimeoutError(`no chlor response in 7 seconds`, `chlorTimeOut`));
|
|
1751
|
+
reject = undefined;
|
|
1752
|
+
|
|
1753
|
+
}, 3000);
|
|
1741
1754
|
});
|
|
1742
1755
|
await request153packet;
|
|
1743
1756
|
let schlor = state.chlorinators.getItemById(id, true);
|
|
@@ -1771,7 +1784,6 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1771
1784
|
reject(err);
|
|
1772
1785
|
}
|
|
1773
1786
|
else{
|
|
1774
|
-
logger.debug(`chlor resolve 217`);
|
|
1775
1787
|
resolve();
|
|
1776
1788
|
}
|
|
1777
1789
|
}
|
|
@@ -1792,7 +1804,9 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1792
1804
|
}
|
|
1793
1805
|
public async deleteChlorAsync(obj: any): Promise<ChlorinatorState> {
|
|
1794
1806
|
let id = parseInt(obj.id, 10);
|
|
1795
|
-
if (isNaN(id)) obj.id
|
|
1807
|
+
if (isNaN(id)) return Promise.reject(new InvalidEquipmentDataError(`Chlorinator id is not valid: ${obj.id}`, 'chlorinator', obj.id));
|
|
1808
|
+
let chlor = sys.chlorinators.getItemById(id);
|
|
1809
|
+
if (chlor.master === 1) return await super.deleteChlorAsync(obj);
|
|
1796
1810
|
return new Promise<ChlorinatorState>((resolve, reject) => {
|
|
1797
1811
|
let out = Outbound.create({
|
|
1798
1812
|
dest: 16,
|
|
@@ -1806,8 +1820,9 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1806
1820
|
reject(err);
|
|
1807
1821
|
}
|
|
1808
1822
|
else {
|
|
1809
|
-
|
|
1810
|
-
let
|
|
1823
|
+
ncp.chlorinators.deleteChlorinatorAsync(id).then(()=>{});
|
|
1824
|
+
let cstate = state.chlorinators.getItemById(id, true);
|
|
1825
|
+
chlor = sys.chlorinators.getItemById(id, true);
|
|
1811
1826
|
chlor.isActive = cstate.isActive = false;
|
|
1812
1827
|
sys.chlorinators.removeItemById(id);
|
|
1813
1828
|
state.chlorinators.removeItemById(id);
|
|
@@ -1949,10 +1964,11 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
1949
1964
|
}
|
|
1950
1965
|
}
|
|
1951
1966
|
isAdd = true;
|
|
1967
|
+
pump = sys.pumps.getItemById(id, true);
|
|
1952
1968
|
}
|
|
1953
1969
|
else {
|
|
1954
1970
|
pump = sys.pumps.getItemById(id, false);
|
|
1955
|
-
if (data.master > 0 || pump.master > 0
|
|
1971
|
+
if (data.master > 0 || pump.master > 0) return await super.setPumpAsync(data);
|
|
1956
1972
|
ntype = typeof data.type === 'undefined' ? pump.type : parseInt(data.type, 10);
|
|
1957
1973
|
if (isNaN(ntype)) return Promise.reject(new InvalidEquipmentDataError(`Pump type ${data.type} is not valid`, 'Pump', data));
|
|
1958
1974
|
type = sys.board.valueMaps.pumpTypes.transform(ntype);
|
|
@@ -1983,7 +1999,6 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
1983
1999
|
if (type.name === 'ss') {
|
|
1984
2000
|
// The OCP doesn't deal with single speed pumps. Simply add it to the config.
|
|
1985
2001
|
data.circuits = [];
|
|
1986
|
-
pump = sys.pumps.getItemById(id, true);
|
|
1987
2002
|
pump.set(pump);
|
|
1988
2003
|
let spump = state.pumps.getItemById(id, true);
|
|
1989
2004
|
for (let prop in spump) {
|
|
@@ -2015,21 +2030,25 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
2015
2030
|
retries: 2,
|
|
2016
2031
|
response: Response.create({ action: 1, payload: [155] })
|
|
2017
2032
|
});
|
|
2018
|
-
outc.appendPayloadByte(typeof type.maxPrimingTime !== 'undefined' ? data.primingTime : 0, pump.primingTime | 0);
|
|
2019
2033
|
outc.appendPayloadBytes(0, 44);
|
|
2020
|
-
if (
|
|
2034
|
+
if (type.val === 128){
|
|
2035
|
+
outc.setPayloadByte(3, 2);
|
|
2036
|
+
}
|
|
2037
|
+
if (typeof type.maxPrimingTime !== 'undefined' && type.maxPrimingTime > 0 && type.val >=64) {
|
|
2038
|
+
outc.setPayloadByte(2, parseInt(data.primingTime, 10), pump.primingTime || 1);
|
|
2021
2039
|
let primingSpeed = typeof data.primingSpeed !== 'undefined' ? parseInt(data.primingSpeed, 10) : pump.primingSpeed || type.minSpeed;
|
|
2022
2040
|
outc.setPayloadByte(21, Math.floor(primingSpeed / 256));
|
|
2023
|
-
outc.setPayloadByte(30, primingSpeed
|
|
2041
|
+
outc.setPayloadByte(30, primingSpeed % 256);
|
|
2024
2042
|
}
|
|
2025
|
-
if (type.val
|
|
2043
|
+
if (type.val === 1) { // Any VF pump.
|
|
2026
2044
|
outc.setPayloadByte(1, parseInt(data.backgroundCircuit, 10), pump.backgroundCircuit || 6);
|
|
2045
|
+
outc.setPayloadByte(2, parseInt(data.filterSize, 10) / 1000, pump.filterSize / 1000 || 15);
|
|
2046
|
+
// outc.setPayloadByte(2, body.capacity / 1000, 15); RSG - This is filter size, which may or may not equal the body size.
|
|
2027
2047
|
outc.setPayloadByte(3, parseInt(data.turnovers, 10), pump.turnovers || 2);
|
|
2028
2048
|
let body = sys.bodies.getItemById(1, sys.equipment.maxBodies >= 1);
|
|
2029
|
-
outc.setPayloadByte(2, body.capacity / 1000, 15);
|
|
2030
2049
|
outc.setPayloadByte(21, parseInt(data.manualFilterGPM, 10), pump.manualFilterGPM || 30);
|
|
2031
2050
|
outc.setPayloadByte(22, parseInt(data.primingSpeed, 10), pump.primingSpeed || 55);
|
|
2032
|
-
let primingTime = typeof data.primingTime !== 'undefined' ? parseInt(data.primingTime, 10) : pump.primingTime;
|
|
2051
|
+
let primingTime = typeof data.primingTime !== 'undefined' ? parseInt(data.primingTime, 10) : pump.primingTime || 0;
|
|
2033
2052
|
let maxSystemTime = typeof data.maxSystemTime !== 'undefined' ? parseInt(data.maxSystemTime, 10) : pump.maxSystemTime;
|
|
2034
2053
|
outc.setPayloadByte(23, primingTime | maxSystemTime << 4, 5);
|
|
2035
2054
|
outc.setPayloadByte(24, parseInt(data.maxPressureIncrease, 10), pump.maxPressureIncrease || 10);
|
|
@@ -2037,7 +2056,7 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
2037
2056
|
outc.setPayloadByte(26, parseInt(data.backwashTime, 10), pump.backwashTime || 5);
|
|
2038
2057
|
outc.setPayloadByte(27, parseInt(data.rinseTime, 10), pump.rinseTime || 1);
|
|
2039
2058
|
outc.setPayloadByte(28, parseInt(data.vacuumFlow, 10), pump.vacuumFlow || 50);
|
|
2040
|
-
outc.setPayloadByte(
|
|
2059
|
+
outc.setPayloadByte(30, parseInt(data.vacuumTime, 10), pump.vacuumTime || 10);
|
|
2041
2060
|
}
|
|
2042
2061
|
if (typeof type.maxCircuits !== 'undefined' && type.maxCircuits > 0 && typeof data.circuits !== 'undefined') { // This pump type supports circuits
|
|
2043
2062
|
for (let i = 1; i <= data.circuits.length && i <= type.maxCircuits; i++) {
|
|
@@ -2050,7 +2069,7 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
2050
2069
|
c.units = parseInt(c.units, 10) || type.name === 'vf' ? sys.board.valueMaps.pumpUnits.getValue('gpm') : sys.board.valueMaps.pumpUnits.getValue('rpm');
|
|
2051
2070
|
if (typeof type.minSpeed !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('rpm')) {
|
|
2052
2071
|
outc.setPayloadByte(i * 2 + 4, Math.floor(speed / 256)); // Set to rpm
|
|
2053
|
-
outc.setPayloadByte(i + 21, speed
|
|
2072
|
+
outc.setPayloadByte(i + 21, speed % 256);
|
|
2054
2073
|
c.speed = speed;
|
|
2055
2074
|
}
|
|
2056
2075
|
else if (typeof type.minFlow !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('gpm')) {
|
|
@@ -2087,7 +2106,7 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
2087
2106
|
// [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]
|
|
2088
2107
|
const setPumpConfig = Outbound.create({
|
|
2089
2108
|
action: 155,
|
|
2090
|
-
payload: [pump.id, pump.type, 0,
|
|
2109
|
+
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],
|
|
2091
2110
|
retries: 2,
|
|
2092
2111
|
response: true
|
|
2093
2112
|
});
|
|
@@ -2163,6 +2182,34 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
2163
2182
|
spump.type = pump.type;
|
|
2164
2183
|
spump.status = 0;
|
|
2165
2184
|
}
|
|
2185
|
+
public async deletePumpAsync(pump: Pump):Promise<Pump>{
|
|
2186
|
+
let id = pump.id;
|
|
2187
|
+
if (isNaN(id)) return Promise.reject(new InvalidEquipmentIdError(`DeletePumpAsync: Pump ${id} is not valid.`, 0, `pump`))
|
|
2188
|
+
const outc = Outbound.create({
|
|
2189
|
+
action: 155,
|
|
2190
|
+
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],
|
|
2191
|
+
retries: 2,
|
|
2192
|
+
response: true
|
|
2193
|
+
});
|
|
2194
|
+
return new Promise<Pump>((resolve, reject) => {
|
|
2195
|
+
outc.onComplete = (err, msg) => {
|
|
2196
|
+
if (err) reject(err);
|
|
2197
|
+
else {
|
|
2198
|
+
sys.pumps.removeItemById(id);
|
|
2199
|
+
state.pumps.removeItemById(id);
|
|
2200
|
+
resolve(sys.pumps.getItemById(id,false));
|
|
2201
|
+
const pumpConfigRequest = Outbound.create({
|
|
2202
|
+
action: 216,
|
|
2203
|
+
payload: [id],
|
|
2204
|
+
retries: 2,
|
|
2205
|
+
response: true
|
|
2206
|
+
});
|
|
2207
|
+
conn.queueSendMessage(pumpConfigRequest);
|
|
2208
|
+
}
|
|
2209
|
+
};
|
|
2210
|
+
conn.queueSendMessage(outc);
|
|
2211
|
+
});
|
|
2212
|
+
}
|
|
2166
2213
|
}
|
|
2167
2214
|
class TouchHeaterCommands extends HeaterCommands {
|
|
2168
2215
|
public getInstalledHeaterTypes(body?: number): any {
|
|
@@ -2223,13 +2270,14 @@ class TouchHeaterCommands extends HeaterCommands {
|
|
|
2223
2270
|
}
|
|
2224
2271
|
// RKS: Not sure what to do with this as the heater data for Touch isn't actually processed anywhere.
|
|
2225
2272
|
public async setHeaterAsync(obj: any): Promise<Heater> {
|
|
2273
|
+
if (obj.master === 1 || parseInt(obj.id, 10) > 255) return super.setHeaterAsync(obj);
|
|
2226
2274
|
return new Promise<Heater>((resolve, reject) => {
|
|
2227
2275
|
let id = typeof obj.id === 'undefined' ? -1 : parseInt(obj.id, 10);
|
|
2228
2276
|
if (isNaN(id)) return reject(new InvalidEquipmentIdError('Heater Id is not valid.', obj.id, 'Heater'));
|
|
2229
2277
|
let heater: Heater;
|
|
2230
2278
|
if (id <= 0) {
|
|
2231
2279
|
// We are adding a heater. In this case all heaters are virtual.
|
|
2232
|
-
let heaters = sys.heaters.filter(h => h.
|
|
2280
|
+
let heaters = sys.heaters.filter(h => h.master === 1);
|
|
2233
2281
|
id = heaters.getMaxId() + 1;
|
|
2234
2282
|
}
|
|
2235
2283
|
heater = sys.heaters.getItemById(id, true);
|
|
@@ -2240,7 +2288,7 @@ class TouchHeaterCommands extends HeaterCommands {
|
|
|
2240
2288
|
}
|
|
2241
2289
|
}
|
|
2242
2290
|
let hstate = state.heaters.getItemById(id, true);
|
|
2243
|
-
|
|
2291
|
+
|
|
2244
2292
|
hstate.name = heater.name;
|
|
2245
2293
|
hstate.type = heater.type;
|
|
2246
2294
|
heater.master = 1;
|
|
@@ -2250,7 +2298,7 @@ class TouchHeaterCommands extends HeaterCommands {
|
|
|
2250
2298
|
});
|
|
2251
2299
|
}
|
|
2252
2300
|
public async deleteHeaterAsync(obj: any): Promise<Heater> {
|
|
2253
|
-
if (utils.makeBool(obj.
|
|
2301
|
+
if (utils.makeBool(obj.master === 1 || parseInt(obj.id, 10) > 255)) return super.deleteHeaterAsync(obj);
|
|
2254
2302
|
return new Promise<Heater>((resolve, reject) => {
|
|
2255
2303
|
let id = parseInt(obj.id, 10);
|
|
2256
2304
|
if (isNaN(id)) return reject(new InvalidEquipmentIdError('Cannot delete. Heater Id is not valid.', obj.id, 'Heater'));
|
|
@@ -2336,7 +2384,7 @@ class TouchChemControllerCommands extends ChemControllerCommands {
|
|
|
2336
2384
|
// Now lets do all our validation to the incoming chem controller data.
|
|
2337
2385
|
let name = typeof data.name !== 'undefined' ? data.name : chem.name || `IntelliChem - ${address - 143}`;
|
|
2338
2386
|
let type = sys.board.valueMaps.chemControllerTypes.transformByName('intellichem');
|
|
2339
|
-
// So now we are down to the nitty gritty setting the data for the REM
|
|
2387
|
+
// So now we are down to the nitty gritty setting the data for the REM Chem controller.
|
|
2340
2388
|
let calciumHardness = typeof data.calciumHardness !== 'undefined' ? parseInt(data.calciumHardness, 10) : chem.calciumHardness;
|
|
2341
2389
|
let cyanuricAcid = typeof data.cyanuricAcid !== 'undefined' ? parseInt(data.cyanuricAcid, 10) : chem.cyanuricAcid;
|
|
2342
2390
|
let alkalinity = typeof data.alkalinity !== 'undefined' ? parseInt(data.alkalinity, 10) : chem.alkalinity;
|