nodejs-poolcontroller 7.4.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 +3 -0
- package/README.md +2 -2
- package/app.ts +2 -0
- package/config/Config.ts +3 -0
- package/config/VersionCheck.ts +8 -4
- package/controller/Equipment.ts +89 -29
- package/controller/Errors.ts +14 -1
- package/controller/State.ts +75 -31
- package/controller/boards/EasyTouchBoard.ts +81 -36
- package/controller/boards/IntelliCenterBoard.ts +96 -32
- package/controller/boards/IntelliTouchBoard.ts +103 -29
- package/controller/boards/NixieBoard.ts +79 -27
- package/controller/boards/SystemBoard.ts +1552 -822
- package/controller/comms/Comms.ts +84 -9
- 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 +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 +10 -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 +2 -3
- package/controller/comms/messages/status/EquipmentStateMessage.ts +74 -22
- package/controller/comms/messages/status/HeaterStateMessage.ts +15 -6
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +37 -26
- package/controller/nixie/Nixie.ts +18 -16
- package/controller/nixie/chemistry/ChemController.ts +57 -37
- package/controller/nixie/chemistry/Chlorinator.ts +7 -8
- package/controller/nixie/circuits/Circuit.ts +17 -0
- package/controller/nixie/pumps/Pump.ts +49 -24
- package/controller/nixie/schedules/Schedule.ts +1 -1
- package/defaultConfig.json +15 -0
- package/issue_template.md +1 -1
- package/logger/DataLogger.ts +37 -22
- package/package.json +3 -1
- package/web/Server.ts +515 -27
- package/web/bindings/influxDB.json +35 -0
- package/web/bindings/mqtt.json +62 -3
- package/web/bindings/mqttAlt.json +57 -4
- package/web/interfaces/httpInterface.ts +2 -0
- package/web/interfaces/influxInterface.ts +3 -2
- package/web/interfaces/mqttInterface.ts +12 -1
- package/web/services/config/Config.ts +162 -37
- package/web/services/state/State.ts +47 -3
- package/web/services/state/StateSocket.ts +1 -1
package/controller/State.ts
CHANGED
|
@@ -36,6 +36,7 @@ export class State implements IState {
|
|
|
36
36
|
private _isDirty: boolean;
|
|
37
37
|
private _timerDirty: NodeJS.Timeout;
|
|
38
38
|
protected _dt: Timestamp;
|
|
39
|
+
protected _startTime: Timestamp;
|
|
39
40
|
protected _controllerType: ControllerType;
|
|
40
41
|
protected onchange = (obj, fn) => {
|
|
41
42
|
const handler = {
|
|
@@ -191,6 +192,8 @@ export class State implements IState {
|
|
|
191
192
|
public get controllerState() {
|
|
192
193
|
var self = this;
|
|
193
194
|
return {
|
|
195
|
+
systemUnits: sys.board.valueMaps.systemUnits.transform(sys.general.options.units),
|
|
196
|
+
startTime: self.data.startTime || '',
|
|
194
197
|
time: self.data.time || '',
|
|
195
198
|
// body: self.data.body || {},
|
|
196
199
|
valve: self.data.valve || 0,
|
|
@@ -305,7 +308,6 @@ export class State implements IState {
|
|
|
305
308
|
this.hasChanged = true;
|
|
306
309
|
}
|
|
307
310
|
}
|
|
308
|
-
|
|
309
311
|
}
|
|
310
312
|
public get valve(): number { return this.data.valve; }
|
|
311
313
|
public set valve(val: number) {
|
|
@@ -386,6 +388,7 @@ export class State implements IState {
|
|
|
386
388
|
this.comms = new CommsState();
|
|
387
389
|
this.heliotrope = new Heliotrope();
|
|
388
390
|
this.appVersion = new AppVersionState(this.data, 'appVersion');
|
|
391
|
+
this.data.startTime = Timestamp.toISOLocal(new Date());
|
|
389
392
|
versionCheck.checkGitLocal();
|
|
390
393
|
}
|
|
391
394
|
public resetData() {
|
|
@@ -876,6 +879,11 @@ export class PumpStateCollection extends EqStateCollection<PumpState> {
|
|
|
876
879
|
}
|
|
877
880
|
export class PumpState extends EqState {
|
|
878
881
|
public dataName: string = 'pump';
|
|
882
|
+
public initData() {
|
|
883
|
+
if (typeof this.data.status === 'undefined') {
|
|
884
|
+
this.data.status = { name: 'ok', desc: 'Ok', val: 0 };
|
|
885
|
+
}
|
|
886
|
+
}
|
|
879
887
|
private _threshold = 0.05;
|
|
880
888
|
private exceedsThreshold(origVal: number, newVal: number) {
|
|
881
889
|
return Math.abs((newVal - origVal) / origVal) > this._threshold;
|
|
@@ -909,7 +917,7 @@ export class PumpState extends EqState {
|
|
|
909
917
|
// quick fix for #172
|
|
910
918
|
if (this.status !== val) {
|
|
911
919
|
if (sys.board.valueMaps.pumpTypes.getName(this.type) === 'vsf' && val === 0) {
|
|
912
|
-
this.data.status = { name: 'ok', desc: 'Ok', val };
|
|
920
|
+
this.data.status = { name: 'ok', desc: 'Ok', val: 0 };
|
|
913
921
|
}
|
|
914
922
|
else this.data.status = sys.board.valueMaps.pumpStatus.transform(val);
|
|
915
923
|
this.hasChanged = true;
|
|
@@ -991,6 +999,7 @@ export class ScheduleState extends EqState {
|
|
|
991
999
|
public get startDate(): Date { return this._startDate; }
|
|
992
1000
|
public set startDate(val: Date) { this._startDate = val; this._saveStartDate(); }
|
|
993
1001
|
private _saveStartDate() {
|
|
1002
|
+
if (typeof this._startDate === 'undefined') this._startDate = new Date();
|
|
994
1003
|
this.startDate.setHours(0, 0, 0, 0);
|
|
995
1004
|
this.setDataVal('startDate', Timestamp.toISOLocal(this.startDate));
|
|
996
1005
|
}
|
|
@@ -1097,7 +1106,7 @@ export class CircuitGroupStateCollection extends EqStateCollection<CircuitGroupS
|
|
|
1097
1106
|
for (let i = this.data.length - 1; i >= 0; i--) {
|
|
1098
1107
|
if (isNaN(this.data[i].id)) this.data.splice(i, 1);
|
|
1099
1108
|
else {
|
|
1100
|
-
if (typeof sys.
|
|
1109
|
+
if (typeof sys.circuitGroups.find(elem => elem.id === this.data[i].id) === 'undefined') this.removeItemById(this.data[i].id);
|
|
1101
1110
|
}
|
|
1102
1111
|
}
|
|
1103
1112
|
let cfg = sys.circuitGroups.toArray();
|
|
@@ -1173,7 +1182,7 @@ export class LightGroupStateCollection extends EqStateCollection<LightGroupState
|
|
|
1173
1182
|
for (let i = this.data.length - 1; i >= 0; i--) {
|
|
1174
1183
|
if (isNaN(this.data[i].id)) this.data.splice(i, 1);
|
|
1175
1184
|
else {
|
|
1176
|
-
if (typeof sys.
|
|
1185
|
+
if (typeof sys.lightGroups.find(elem => elem.id === this.data[i].id) === 'undefined') this.removeItemById(this.data[i].id);
|
|
1177
1186
|
}
|
|
1178
1187
|
}
|
|
1179
1188
|
let cfg = sys.lightGroups.toArray();
|
|
@@ -1279,6 +1288,7 @@ export class BodyTempState extends EqState {
|
|
|
1279
1288
|
public dataName = 'bodyTempState';
|
|
1280
1289
|
public initData() {
|
|
1281
1290
|
if (typeof this.data.heaterOptions === 'undefined') this.data.heaterOptions = { total: 0 };
|
|
1291
|
+
if (typeof this.data.isCovered === 'undefined') this.data.isCovered = false;
|
|
1282
1292
|
}
|
|
1283
1293
|
public get id(): number { return this.data.id; }
|
|
1284
1294
|
public set id(val: number) { this.setDataVal('id', val); }
|
|
@@ -1317,6 +1327,8 @@ export class BodyTempState extends EqState {
|
|
|
1317
1327
|
public set coolSetpoint(val: number) { this.setDataVal('coolSetpoint', val); }
|
|
1318
1328
|
public get isOn(): boolean { return this.data.isOn; }
|
|
1319
1329
|
public set isOn(val: boolean) { this.setDataVal('isOn', val); }
|
|
1330
|
+
public get isCovered(): boolean { return this.data.isCovered; }
|
|
1331
|
+
public set isCovered(val: boolean) { this.setDataVal('isCovered', val); }
|
|
1320
1332
|
public emitData(name: string, data: any) { webApp.emitToClients('body', this.data); }
|
|
1321
1333
|
// RKS: This is a very interesting object because we have a varied object. Type safety rules should not apply
|
|
1322
1334
|
// here as the heater types are specific to the installed equipment. The reason is because it has no meaning without the body and the calculation of it should
|
|
@@ -1388,7 +1400,7 @@ export class HeaterStateCollection extends EqStateCollection<HeaterState> {
|
|
|
1388
1400
|
this.data.splice(i, 1);
|
|
1389
1401
|
}
|
|
1390
1402
|
else {
|
|
1391
|
-
if (typeof sys.
|
|
1403
|
+
if (typeof sys.heaters.find(elem => elem.id === this.data[i].id) === 'undefined') this.removeItemById(this.data[i].id);
|
|
1392
1404
|
}
|
|
1393
1405
|
}
|
|
1394
1406
|
let cfg = sys.heaters.toArray();
|
|
@@ -1435,7 +1447,7 @@ export class FeatureStateCollection extends EqStateCollection<FeatureState> {
|
|
|
1435
1447
|
for (let i = this.data.length - 1; i >= 0; i--) {
|
|
1436
1448
|
if (isNaN(this.data[i].id)) this.data.splice(i, 1);
|
|
1437
1449
|
else {
|
|
1438
|
-
if (typeof sys.
|
|
1450
|
+
if (typeof sys.features.find(elem => elem.id === this.data[i].id) === 'undefined') this.removeItemById(this.data[i].id);
|
|
1439
1451
|
}
|
|
1440
1452
|
}
|
|
1441
1453
|
let cfg = sys.features.toArray();
|
|
@@ -1532,7 +1544,7 @@ export class CircuitStateCollection extends EqStateCollection<CircuitState> {
|
|
|
1532
1544
|
for (let i = this.data.length - 1; i >= 0; i--) {
|
|
1533
1545
|
if (isNaN(this.data[i].id)) this.data.splice(i, 1);
|
|
1534
1546
|
else {
|
|
1535
|
-
if (typeof sys.
|
|
1547
|
+
if (typeof sys.circuits.find(elem => elem.id === this.data[i].id) === 'undefined') this.removeItemById(this.data[i].id);
|
|
1536
1548
|
}
|
|
1537
1549
|
}
|
|
1538
1550
|
let cfg = sys.circuits.toArray();
|
|
@@ -1569,10 +1581,12 @@ export class CircuitState extends EqState implements ICircuitState {
|
|
|
1569
1581
|
this.hasChanged = true;
|
|
1570
1582
|
}
|
|
1571
1583
|
}
|
|
1572
|
-
public get lightingTheme(): number { return typeof
|
|
1584
|
+
public get lightingTheme(): number { return typeof this.data.lightingTheme !== 'undefined' ? this.data.lightingTheme.val : 255; }
|
|
1573
1585
|
public set lightingTheme(val: number) {
|
|
1574
1586
|
if (this.lightingTheme !== val) {
|
|
1575
|
-
this
|
|
1587
|
+
// Force this to undefined when we are a circuit without a theme.
|
|
1588
|
+
if (typeof val === 'undefined') this.data.lightingTheme = undefined;
|
|
1589
|
+
else this.data.lightingTheme = sys.board.valueMaps.lightThemes.transform(val);
|
|
1576
1590
|
this.hasChanged = true;
|
|
1577
1591
|
}
|
|
1578
1592
|
}
|
|
@@ -1603,7 +1617,7 @@ export class ValveStateCollection extends EqStateCollection<ValveState> {
|
|
|
1603
1617
|
for (let i = this.data.length - 1; i >= 0; i--) {
|
|
1604
1618
|
if (isNaN(this.data[i].id)) this.data.splice(i, 1);
|
|
1605
1619
|
else {
|
|
1606
|
-
if (typeof sys.
|
|
1620
|
+
if (typeof sys.valves.find(elem => elem.id === this.data[i].id) === 'undefined') this.removeItemById(this.data[i].id);
|
|
1607
1621
|
}
|
|
1608
1622
|
}
|
|
1609
1623
|
let cfg = sys.valves.toArray();
|
|
@@ -1643,7 +1657,7 @@ export class ValveState extends EqState {
|
|
|
1643
1657
|
if (valve.circuit !== 256) vstate.circuit = state.circuits.getInterfaceById(valve.circuit).get(true);
|
|
1644
1658
|
vstate.isIntake = utils.makeBool(valve.isIntake);
|
|
1645
1659
|
vstate.isReturn = utils.makeBool(valve.isReturn);
|
|
1646
|
-
vstate.isVirtual = utils.makeBool(valve.isVirtual);
|
|
1660
|
+
// vstate.isVirtual = utils.makeBool(valve.isVirtual);
|
|
1647
1661
|
vstate.isActive = utils.makeBool(valve.isActive);
|
|
1648
1662
|
vstate.pinId = valve.pinId;
|
|
1649
1663
|
return vstate;
|
|
@@ -1661,12 +1675,15 @@ export class CoverStateCollection extends EqStateCollection<CoverState> {
|
|
|
1661
1675
|
}
|
|
1662
1676
|
export class CoverState extends EqState {
|
|
1663
1677
|
public dataName: string = 'cover';
|
|
1678
|
+
public initData() {
|
|
1679
|
+
if (typeof this.data.isClosed === 'undefined') this.data.isClosed = false;
|
|
1680
|
+
}
|
|
1664
1681
|
public get id(): number { return this.data.id; }
|
|
1665
1682
|
public set id(val: number) { this.data.id = val; }
|
|
1666
1683
|
public get name(): string { return this.data.name; }
|
|
1667
1684
|
public set name(val: string) { this.setDataVal('name', val); }
|
|
1668
|
-
public get
|
|
1669
|
-
public set
|
|
1685
|
+
public get isClosed(): boolean { return this.data.isClosed; }
|
|
1686
|
+
public set isClosed(val: boolean) { this.setDataVal('isClosed', val); }
|
|
1670
1687
|
}
|
|
1671
1688
|
export class ChlorinatorStateCollection extends EqStateCollection<ChlorinatorState> {
|
|
1672
1689
|
public createItem(data: any): ChlorinatorState { return new ChlorinatorState(data); }
|
|
@@ -1676,7 +1693,7 @@ export class ChlorinatorStateCollection extends EqStateCollection<ChlorinatorSta
|
|
|
1676
1693
|
for (let i = this.data.length - 1; i >= 0; i--) {
|
|
1677
1694
|
if (isNaN(this.data[i].id)) this.data.splice(i, 1);
|
|
1678
1695
|
else {
|
|
1679
|
-
if (typeof sys.
|
|
1696
|
+
if (typeof sys.chlorinators.find(elem => elem.id === this.data[i].id) === 'undefined') this.removeItemById(this.data[i].id);
|
|
1680
1697
|
}
|
|
1681
1698
|
}
|
|
1682
1699
|
let cfg = sys.chlorinators.toArray();
|
|
@@ -1730,16 +1747,6 @@ export class ChlorinatorState extends EqState {
|
|
|
1730
1747
|
this.hasChanged = true;
|
|
1731
1748
|
}
|
|
1732
1749
|
}
|
|
1733
|
-
//public get virtualControllerStatus(): number {
|
|
1734
|
-
// return typeof (this.data.virtualControllerStatus) !== 'undefined' ? this.data.virtualControllerStatus.val : -1;
|
|
1735
|
-
//}
|
|
1736
|
-
//public set virtualControllerStatus(val: number) {
|
|
1737
|
-
// if (this.virtualControllerStatus !== val) {
|
|
1738
|
-
// this.data.virtualControllerStatus = sys.board.valueMaps.virtualControllerStatus.transform(val);
|
|
1739
|
-
// this.hasChanged = true;
|
|
1740
|
-
|
|
1741
|
-
// }
|
|
1742
|
-
//}
|
|
1743
1750
|
public get type(): number { return typeof (this.data.type) !== 'undefined' ? this.data.type.val : -1; }
|
|
1744
1751
|
public set type(val: number) {
|
|
1745
1752
|
if (this.type !== val) {
|
|
@@ -1826,6 +1833,12 @@ export class ChlorinatorState extends EqState {
|
|
|
1826
1833
|
else
|
|
1827
1834
|
this.setDataVal('superChlor', false);
|
|
1828
1835
|
}
|
|
1836
|
+
public getExtended(): any {
|
|
1837
|
+
let schlor = this.get(true);
|
|
1838
|
+
let chlor = sys.chlorinators.getItemById(this.id, false);
|
|
1839
|
+
schlor.lockSetpoints = chlor.disabled || chlor.isDosing;
|
|
1840
|
+
return schlor;
|
|
1841
|
+
}
|
|
1829
1842
|
}
|
|
1830
1843
|
export class ChemControllerStateCollection extends EqStateCollection<ChemControllerState> {
|
|
1831
1844
|
public createItem(data: any): ChemControllerState { return new ChemControllerState(data); }
|
|
@@ -1833,7 +1846,7 @@ export class ChemControllerStateCollection extends EqStateCollection<ChemControl
|
|
|
1833
1846
|
for (let i = this.data.length - 1; i >= 0; i--) {
|
|
1834
1847
|
if (isNaN(this.data[i].id)) this.data.splice(i, 1);
|
|
1835
1848
|
else {
|
|
1836
|
-
if (typeof sys.
|
|
1849
|
+
if (typeof sys.chemControllers.find(elem => elem.id === this.data[i].id) === 'undefined') this.removeItemById(this.data[i].id);
|
|
1837
1850
|
}
|
|
1838
1851
|
}
|
|
1839
1852
|
// Make sure we have at least the items that exist in the config.
|
|
@@ -1874,7 +1887,7 @@ export class ChemControllerState extends EqState {
|
|
|
1874
1887
|
//var chemControllerState = {
|
|
1875
1888
|
// lastComm: 'number', // The unix time the chem controller sent its status.
|
|
1876
1889
|
// id: 'number', // Id of the chemController.
|
|
1877
|
-
// type: 'valueMap', // intellichem,
|
|
1890
|
+
// type: 'valueMap', // intellichem, rem.
|
|
1878
1891
|
// address: 'number', // Assigned address if IntelliChem.
|
|
1879
1892
|
// name: 'string', // Name assigned to the controller.
|
|
1880
1893
|
// status: 'valueMap', // ok, nocomms, setupError
|
|
@@ -2113,7 +2126,6 @@ export class ChemicalState extends ChildEqState {
|
|
|
2113
2126
|
if (typeof this.data.flowDelay === 'undefined') this.data.flowDelay = false;
|
|
2114
2127
|
if (typeof this.data.dosingStatus === 'undefined') this.dosingStatus = 2;
|
|
2115
2128
|
if (typeof this.data.enabled === 'undefined') this.data.enabled = true;
|
|
2116
|
-
if (typeof this.data.level === 'undefined') this.data.level = 0;
|
|
2117
2129
|
}
|
|
2118
2130
|
public getConfig(): Chemical { return; }
|
|
2119
2131
|
public calcDoseHistory(): number {
|
|
@@ -2277,7 +2289,7 @@ export class ChemicalState extends ChildEqState {
|
|
|
2277
2289
|
}
|
|
2278
2290
|
export class ChemicalPhState extends ChemicalState {
|
|
2279
2291
|
public initData() {
|
|
2280
|
-
if (typeof this.data.chemType === 'undefined') this.data.chemType === 'acid';
|
|
2292
|
+
// if (typeof this.data.chemType === 'undefined') this.data.chemType === 'acid'; // RSG 10-23-21 - Only a getter; don't need to set this.
|
|
2281
2293
|
super.initData();
|
|
2282
2294
|
}
|
|
2283
2295
|
public getConfig() {
|
|
@@ -2482,14 +2494,16 @@ export class ChemicalDoseState extends DataLoggerEntry {
|
|
|
2482
2494
|
public _isManual: boolean;
|
|
2483
2495
|
|
|
2484
2496
|
constructor(entry?: string | object) {
|
|
2485
|
-
super(
|
|
2497
|
+
super();
|
|
2498
|
+
if (typeof entry === 'object') entry = JSON.stringify(entry);
|
|
2499
|
+
if (typeof entry === 'string') this.parse(entry);
|
|
2486
2500
|
// Javascript is idiotic in that the initialization of variables
|
|
2487
2501
|
// do not happen before the assignment so some of the values can be undefined.
|
|
2488
2502
|
if (typeof this.volumeDosed === 'undefined' || !this.volumeDosed) this.volumeDosed = 0;
|
|
2489
2503
|
if (typeof this.volume === 'undefined' || !this.volume) this.volume = 0;
|
|
2490
2504
|
if (typeof this._isManual === 'undefined') this._isManual = this.method === 'manual';
|
|
2491
2505
|
if (typeof this.timeDosed === 'undefined' || !this.timeDosed) this.timeDosed = 0;
|
|
2492
|
-
if (typeof this._timeDosed === 'undefined') this.timeDosed * 1000;
|
|
2506
|
+
if (typeof this._timeDosed === 'undefined') this._timeDosed = this.timeDosed * 1000;
|
|
2493
2507
|
if (typeof this.time === 'undefined' || !this.time) this.time = 0;
|
|
2494
2508
|
}
|
|
2495
2509
|
public id: number;
|
|
@@ -2506,10 +2520,40 @@ export class ChemicalDoseState extends DataLoggerEntry {
|
|
|
2506
2520
|
public time: number;
|
|
2507
2521
|
public timeDosed: number;
|
|
2508
2522
|
|
|
2509
|
-
public createInstance(entry?: string): ChemicalDoseState { return new ChemicalDoseState(entry); }
|
|
2523
|
+
public static createInstance(entry?: string): ChemicalDoseState { return new ChemicalDoseState(entry); }
|
|
2510
2524
|
public save() { DataLogger.writeEnd(`chemDosage_${this.chem}.log`, this); }
|
|
2511
2525
|
public get timeRemaining(): number { return Math.floor(Math.max(0, this.time - (this._timeDosed / 1000))); }
|
|
2512
2526
|
public get volumeRemaining(): number { return Math.max(0, this.volume - this.volumeDosed); }
|
|
2527
|
+
public parse(entry: string) {
|
|
2528
|
+
// let obj = typeof entry !== 'undefined' ? JSON.parse(entry, this.dateParser) : {};
|
|
2529
|
+
let obj = typeof entry !== 'undefined' ? JSON.parse(entry) : {};
|
|
2530
|
+
for (const prop in obj) {obj[prop] = this.dateParser(prop, obj[prop])}
|
|
2531
|
+
if (typeof obj.setpoint !== 'undefined') this.setpoint = obj.setpoint;
|
|
2532
|
+
if (typeof obj.method !== 'undefined') this.method = obj.method;
|
|
2533
|
+
if (typeof obj.start !== 'undefined') this.start = obj.start;
|
|
2534
|
+
if (typeof obj.end !== 'undefined') this.end = obj.end;
|
|
2535
|
+
if (typeof obj.chem !== 'undefined') this.chem = obj.chem;
|
|
2536
|
+
if (typeof obj.demand !== 'undefined') this.demand = obj.demand;
|
|
2537
|
+
if (typeof obj.id !== 'undefined') this.id = obj.id;
|
|
2538
|
+
if (typeof obj.level !== 'undefined') this.level = obj.level;
|
|
2539
|
+
if (typeof obj.volume !== 'undefined') this.volume = obj.volume;
|
|
2540
|
+
if (typeof obj.status !== 'undefined') this.status = obj.status;
|
|
2541
|
+
if (typeof obj.volumeDosed !== 'undefined') this.volumeDosed = obj.volumeDosed;
|
|
2542
|
+
if (typeof obj.time !== 'undefined') this.time = obj.time;
|
|
2543
|
+
if (typeof obj.timeDosed !== 'undefined') this.timeDosed = obj.timeDosed;
|
|
2544
|
+
// this.setProperties(obj);
|
|
2545
|
+
}
|
|
2546
|
+
protected setProperties(data: any) {
|
|
2547
|
+
let op = Object.getOwnPropertyNames(Object.getPrototypeOf(this));
|
|
2548
|
+
for (let i in op) {
|
|
2549
|
+
let prop = op[i];
|
|
2550
|
+
if (typeof this[prop] === 'function') continue;
|
|
2551
|
+
if (typeof data[prop] !== 'undefined') {
|
|
2552
|
+
if (typeof this[prop] === null || typeof data[prop] === null) continue;
|
|
2553
|
+
this[prop] = data[prop];
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2513
2557
|
}
|
|
2514
2558
|
|
|
2515
2559
|
export class ChemicalDemandState extends ChildEqState {
|
|
@@ -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
|
}
|
|
@@ -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]);
|
|
@@ -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) {
|
|
@@ -1292,6 +1303,7 @@ export class TouchCircuitCommands extends CircuitCommands {
|
|
|
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;
|
|
1294
1305
|
cstate.isActive = circuit.isActive = true;
|
|
1306
|
+
circuit.master = 0;
|
|
1295
1307
|
let eggTimer = sys.eggTimers.find(elem => elem.circuit === parseInt(data.id, 10));
|
|
1296
1308
|
try {
|
|
1297
1309
|
if (circuit.eggTimer === 720) {
|
|
@@ -1657,28 +1669,26 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1657
1669
|
public async setChlorAsync(obj: any): Promise<ChlorinatorState> {
|
|
1658
1670
|
let id = parseInt(obj.id, 10);
|
|
1659
1671
|
let isAdd = false;
|
|
1660
|
-
let isVirtual = false;
|
|
1661
|
-
if (id <= 0 || isNaN(id)) id = 1;
|
|
1662
1672
|
let chlor = sys.chlorinators.getItemById(id);
|
|
1663
|
-
if (id
|
|
1673
|
+
if (id <= 0 || isNaN(id)) {
|
|
1664
1674
|
isAdd = true;
|
|
1665
|
-
chlor.master = utils.makeBool(obj.
|
|
1675
|
+
chlor.master = utils.makeBool(obj.master) ? 1 : 0;
|
|
1666
1676
|
// Calculate an id for the chlorinator. The messed up part is that if a chlorinator is not attached to the OCP, its address
|
|
1667
1677
|
// cannot be set by the MUX. This will have to wait.
|
|
1668
1678
|
id = 1;
|
|
1669
|
-
}
|
|
1670
|
-
//
|
|
1671
|
-
|
|
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);
|
|
1672
1682
|
// RKS: I am not even sure this can be done with Touch as the master on the RS485 bus.
|
|
1673
|
-
if (chlor.master ===
|
|
1683
|
+
if (typeof chlor.master === 'undefined') chlor.master = 0;
|
|
1674
1684
|
let name = obj.name || chlor.name || 'IntelliChlor' + id;
|
|
1675
|
-
let poolSetpoint = parseInt(obj.poolSetpoint, 10);
|
|
1676
|
-
let spaSetpoint = parseInt(obj.spaSetpoint, 10);
|
|
1677
1685
|
let superChlorHours = parseInt(obj.superChlorHours, 10);
|
|
1678
1686
|
if (typeof obj.superChlorinate !== 'undefined') obj.superChlor = utils.makeBool(obj.superChlorinate);
|
|
1679
1687
|
let superChlorinate = typeof obj.superChlor === 'undefined' ? undefined : utils.makeBool(obj.superChlor);
|
|
1680
|
-
let disabled = typeof obj.disabled !== 'undefined' ? utils.makeBool(obj.disabled) : chlor.disabled;
|
|
1681
1688
|
let isDosing = typeof obj.isDosing !== 'undefined' ? utils.makeBool(obj.isDosing) : chlor.isDosing;
|
|
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;
|
|
1682
1692
|
let model = typeof obj.model !== 'undefined' ? obj.model : chlor.model;
|
|
1683
1693
|
let chlorType = typeof obj.type !== 'undefined' ? sys.board.valueMaps.chlorinatorType.encode(obj.type) : chlor.type || 0;
|
|
1684
1694
|
if (isAdd) {
|
|
@@ -1705,6 +1715,7 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1705
1715
|
if (poolSetpoint > 100 || poolSetpoint < 0) return Promise.reject(new InvalidEquipmentDataError(`Chlorinator poolSetpoint is out of range: ${chlor.poolSetpoint}`, 'chlorinator', chlor.poolSetpoint));
|
|
1706
1716
|
if (spaSetpoint > 100 || spaSetpoint < 0) return Promise.reject(new InvalidEquipmentDataError(`Chlorinator spaSetpoint is out of range: ${chlor.poolSetpoint}`, 'chlorinator', chlor.spaSetpoint));
|
|
1707
1717
|
if (typeof obj.ignoreSaltReading !== 'undefined') chlor.ignoreSaltReading = utils.makeBool(obj.ignoreSaltReading);
|
|
1718
|
+
|
|
1708
1719
|
let _timeout: NodeJS.Timeout;
|
|
1709
1720
|
try {
|
|
1710
1721
|
let request153packet = new Promise<void>((resolve, reject) => {
|
|
@@ -1726,7 +1737,6 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1726
1737
|
reject = undefined;
|
|
1727
1738
|
}
|
|
1728
1739
|
else {
|
|
1729
|
-
logger.debug(`chlor response 153`);
|
|
1730
1740
|
resolve();
|
|
1731
1741
|
resolve = undefined;
|
|
1732
1742
|
}
|
|
@@ -1772,7 +1782,6 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1772
1782
|
reject(err);
|
|
1773
1783
|
}
|
|
1774
1784
|
else{
|
|
1775
|
-
logger.debug(`chlor resolve 217`);
|
|
1776
1785
|
resolve();
|
|
1777
1786
|
}
|
|
1778
1787
|
}
|
|
@@ -1793,7 +1802,9 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1793
1802
|
}
|
|
1794
1803
|
public async deleteChlorAsync(obj: any): Promise<ChlorinatorState> {
|
|
1795
1804
|
let id = parseInt(obj.id, 10);
|
|
1796
|
-
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);
|
|
1797
1808
|
return new Promise<ChlorinatorState>((resolve, reject) => {
|
|
1798
1809
|
let out = Outbound.create({
|
|
1799
1810
|
dest: 16,
|
|
@@ -1807,8 +1818,9 @@ class TouchChlorinatorCommands extends ChlorinatorCommands {
|
|
|
1807
1818
|
reject(err);
|
|
1808
1819
|
}
|
|
1809
1820
|
else {
|
|
1810
|
-
|
|
1811
|
-
let
|
|
1821
|
+
ncp.chlorinators.deleteChlorinatorAsync(id).then(()=>{});
|
|
1822
|
+
let cstate = state.chlorinators.getItemById(id, true);
|
|
1823
|
+
chlor = sys.chlorinators.getItemById(id, true);
|
|
1812
1824
|
chlor.isActive = cstate.isActive = false;
|
|
1813
1825
|
sys.chlorinators.removeItemById(id);
|
|
1814
1826
|
state.chlorinators.removeItemById(id);
|
|
@@ -1950,10 +1962,11 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
1950
1962
|
}
|
|
1951
1963
|
}
|
|
1952
1964
|
isAdd = true;
|
|
1965
|
+
pump = sys.pumps.getItemById(id, true);
|
|
1953
1966
|
}
|
|
1954
1967
|
else {
|
|
1955
1968
|
pump = sys.pumps.getItemById(id, false);
|
|
1956
|
-
if (data.master > 0 || pump.master > 0
|
|
1969
|
+
if (data.master > 0 || pump.master > 0) return await super.setPumpAsync(data);
|
|
1957
1970
|
ntype = typeof data.type === 'undefined' ? pump.type : parseInt(data.type, 10);
|
|
1958
1971
|
if (isNaN(ntype)) return Promise.reject(new InvalidEquipmentDataError(`Pump type ${data.type} is not valid`, 'Pump', data));
|
|
1959
1972
|
type = sys.board.valueMaps.pumpTypes.transform(ntype);
|
|
@@ -1984,7 +1997,6 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
1984
1997
|
if (type.name === 'ss') {
|
|
1985
1998
|
// The OCP doesn't deal with single speed pumps. Simply add it to the config.
|
|
1986
1999
|
data.circuits = [];
|
|
1987
|
-
pump = sys.pumps.getItemById(id, true);
|
|
1988
2000
|
pump.set(pump);
|
|
1989
2001
|
let spump = state.pumps.getItemById(id, true);
|
|
1990
2002
|
for (let prop in spump) {
|
|
@@ -2016,21 +2028,25 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
2016
2028
|
retries: 2,
|
|
2017
2029
|
response: Response.create({ action: 1, payload: [155] })
|
|
2018
2030
|
});
|
|
2019
|
-
outc.appendPayloadByte(typeof type.maxPrimingTime !== 'undefined' ? data.primingTime : 0, pump.primingTime | 0);
|
|
2020
2031
|
outc.appendPayloadBytes(0, 44);
|
|
2021
|
-
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);
|
|
2022
2037
|
let primingSpeed = typeof data.primingSpeed !== 'undefined' ? parseInt(data.primingSpeed, 10) : pump.primingSpeed || type.minSpeed;
|
|
2023
2038
|
outc.setPayloadByte(21, Math.floor(primingSpeed / 256));
|
|
2024
|
-
outc.setPayloadByte(30, primingSpeed
|
|
2039
|
+
outc.setPayloadByte(30, primingSpeed % 256);
|
|
2025
2040
|
}
|
|
2026
|
-
if (type.val
|
|
2041
|
+
if (type.val === 1) { // Any VF pump.
|
|
2027
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.
|
|
2028
2045
|
outc.setPayloadByte(3, parseInt(data.turnovers, 10), pump.turnovers || 2);
|
|
2029
2046
|
let body = sys.bodies.getItemById(1, sys.equipment.maxBodies >= 1);
|
|
2030
|
-
outc.setPayloadByte(2, body.capacity / 1000, 15);
|
|
2031
2047
|
outc.setPayloadByte(21, parseInt(data.manualFilterGPM, 10), pump.manualFilterGPM || 30);
|
|
2032
2048
|
outc.setPayloadByte(22, parseInt(data.primingSpeed, 10), pump.primingSpeed || 55);
|
|
2033
|
-
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;
|
|
2034
2050
|
let maxSystemTime = typeof data.maxSystemTime !== 'undefined' ? parseInt(data.maxSystemTime, 10) : pump.maxSystemTime;
|
|
2035
2051
|
outc.setPayloadByte(23, primingTime | maxSystemTime << 4, 5);
|
|
2036
2052
|
outc.setPayloadByte(24, parseInt(data.maxPressureIncrease, 10), pump.maxPressureIncrease || 10);
|
|
@@ -2038,7 +2054,7 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
2038
2054
|
outc.setPayloadByte(26, parseInt(data.backwashTime, 10), pump.backwashTime || 5);
|
|
2039
2055
|
outc.setPayloadByte(27, parseInt(data.rinseTime, 10), pump.rinseTime || 1);
|
|
2040
2056
|
outc.setPayloadByte(28, parseInt(data.vacuumFlow, 10), pump.vacuumFlow || 50);
|
|
2041
|
-
outc.setPayloadByte(
|
|
2057
|
+
outc.setPayloadByte(30, parseInt(data.vacuumTime, 10), pump.vacuumTime || 10);
|
|
2042
2058
|
}
|
|
2043
2059
|
if (typeof type.maxCircuits !== 'undefined' && type.maxCircuits > 0 && typeof data.circuits !== 'undefined') { // This pump type supports circuits
|
|
2044
2060
|
for (let i = 1; i <= data.circuits.length && i <= type.maxCircuits; i++) {
|
|
@@ -2051,7 +2067,7 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
2051
2067
|
c.units = parseInt(c.units, 10) || type.name === 'vf' ? sys.board.valueMaps.pumpUnits.getValue('gpm') : sys.board.valueMaps.pumpUnits.getValue('rpm');
|
|
2052
2068
|
if (typeof type.minSpeed !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('rpm')) {
|
|
2053
2069
|
outc.setPayloadByte(i * 2 + 4, Math.floor(speed / 256)); // Set to rpm
|
|
2054
|
-
outc.setPayloadByte(i + 21, speed
|
|
2070
|
+
outc.setPayloadByte(i + 21, speed % 256);
|
|
2055
2071
|
c.speed = speed;
|
|
2056
2072
|
}
|
|
2057
2073
|
else if (typeof type.minFlow !== 'undefined' && c.units === sys.board.valueMaps.pumpUnits.getValue('gpm')) {
|
|
@@ -2088,7 +2104,7 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
2088
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]
|
|
2089
2105
|
const setPumpConfig = Outbound.create({
|
|
2090
2106
|
action: 155,
|
|
2091
|
-
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],
|
|
2092
2108
|
retries: 2,
|
|
2093
2109
|
response: true
|
|
2094
2110
|
});
|
|
@@ -2164,6 +2180,34 @@ class TouchPumpCommands extends PumpCommands {
|
|
|
2164
2180
|
spump.type = pump.type;
|
|
2165
2181
|
spump.status = 0;
|
|
2166
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
|
+
}
|
|
2167
2211
|
}
|
|
2168
2212
|
class TouchHeaterCommands extends HeaterCommands {
|
|
2169
2213
|
public getInstalledHeaterTypes(body?: number): any {
|
|
@@ -2224,13 +2268,14 @@ class TouchHeaterCommands extends HeaterCommands {
|
|
|
2224
2268
|
}
|
|
2225
2269
|
// RKS: Not sure what to do with this as the heater data for Touch isn't actually processed anywhere.
|
|
2226
2270
|
public async setHeaterAsync(obj: any): Promise<Heater> {
|
|
2271
|
+
if (obj.master === 1 || parseInt(obj.id, 10) > 255) return super.setHeaterAsync(obj);
|
|
2227
2272
|
return new Promise<Heater>((resolve, reject) => {
|
|
2228
2273
|
let id = typeof obj.id === 'undefined' ? -1 : parseInt(obj.id, 10);
|
|
2229
2274
|
if (isNaN(id)) return reject(new InvalidEquipmentIdError('Heater Id is not valid.', obj.id, 'Heater'));
|
|
2230
2275
|
let heater: Heater;
|
|
2231
2276
|
if (id <= 0) {
|
|
2232
2277
|
// We are adding a heater. In this case all heaters are virtual.
|
|
2233
|
-
let heaters = sys.heaters.filter(h => h.
|
|
2278
|
+
let heaters = sys.heaters.filter(h => h.master === 1);
|
|
2234
2279
|
id = heaters.getMaxId() + 1;
|
|
2235
2280
|
}
|
|
2236
2281
|
heater = sys.heaters.getItemById(id, true);
|
|
@@ -2241,7 +2286,7 @@ class TouchHeaterCommands extends HeaterCommands {
|
|
|
2241
2286
|
}
|
|
2242
2287
|
}
|
|
2243
2288
|
let hstate = state.heaters.getItemById(id, true);
|
|
2244
|
-
|
|
2289
|
+
|
|
2245
2290
|
hstate.name = heater.name;
|
|
2246
2291
|
hstate.type = heater.type;
|
|
2247
2292
|
heater.master = 1;
|
|
@@ -2251,7 +2296,7 @@ class TouchHeaterCommands extends HeaterCommands {
|
|
|
2251
2296
|
});
|
|
2252
2297
|
}
|
|
2253
2298
|
public async deleteHeaterAsync(obj: any): Promise<Heater> {
|
|
2254
|
-
if (utils.makeBool(obj.
|
|
2299
|
+
if (utils.makeBool(obj.master === 1 || parseInt(obj.id, 10) > 255)) return super.deleteHeaterAsync(obj);
|
|
2255
2300
|
return new Promise<Heater>((resolve, reject) => {
|
|
2256
2301
|
let id = parseInt(obj.id, 10);
|
|
2257
2302
|
if (isNaN(id)) return reject(new InvalidEquipmentIdError('Cannot delete. Heater Id is not valid.', obj.id, 'Heater'));
|
|
@@ -2337,7 +2382,7 @@ class TouchChemControllerCommands extends ChemControllerCommands {
|
|
|
2337
2382
|
// Now lets do all our validation to the incoming chem controller data.
|
|
2338
2383
|
let name = typeof data.name !== 'undefined' ? data.name : chem.name || `IntelliChem - ${address - 143}`;
|
|
2339
2384
|
let type = sys.board.valueMaps.chemControllerTypes.transformByName('intellichem');
|
|
2340
|
-
// 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.
|
|
2341
2386
|
let calciumHardness = typeof data.calciumHardness !== 'undefined' ? parseInt(data.calciumHardness, 10) : chem.calciumHardness;
|
|
2342
2387
|
let cyanuricAcid = typeof data.cyanuricAcid !== 'undefined' ? parseInt(data.cyanuricAcid, 10) : chem.cyanuricAcid;
|
|
2343
2388
|
let alkalinity = typeof data.alkalinity !== 'undefined' ? parseInt(data.alkalinity, 10) : chem.alkalinity;
|