nodejs-poolcontroller 7.5.1 → 7.7.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/1-bug-report.yml +84 -0
- package/.github/ISSUE_TEMPLATE/2-docs.md +12 -0
- package/.github/ISSUE_TEMPLATE/3-proposal.md +28 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/Changelog +19 -0
- package/Dockerfile +3 -3
- package/README.md +13 -8
- package/app.ts +1 -1
- package/config/Config.ts +38 -2
- package/config/VersionCheck.ts +27 -12
- package/controller/Constants.ts +2 -1
- package/controller/Equipment.ts +193 -9
- package/controller/Errors.ts +10 -0
- package/controller/Lockouts.ts +503 -0
- package/controller/State.ts +269 -64
- package/controller/boards/AquaLinkBoard.ts +1000 -0
- package/controller/boards/BoardFactory.ts +4 -0
- package/controller/boards/EasyTouchBoard.ts +468 -144
- package/controller/boards/IntelliCenterBoard.ts +466 -307
- package/controller/boards/IntelliTouchBoard.ts +37 -5
- package/controller/boards/NixieBoard.ts +671 -141
- package/controller/boards/SystemBoard.ts +1397 -641
- package/controller/comms/Comms.ts +462 -362
- package/controller/comms/messages/Messages.ts +174 -30
- package/controller/comms/messages/config/ChlorinatorMessage.ts +6 -3
- package/controller/comms/messages/config/CircuitMessage.ts +1 -0
- package/controller/comms/messages/config/ExternalMessage.ts +10 -8
- package/controller/comms/messages/config/HeaterMessage.ts +141 -29
- package/controller/comms/messages/config/OptionsMessage.ts +9 -2
- package/controller/comms/messages/config/PumpMessage.ts +53 -35
- package/controller/comms/messages/config/ScheduleMessage.ts +33 -25
- package/controller/comms/messages/config/ValveMessage.ts +2 -2
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +38 -86
- package/controller/comms/messages/status/EquipmentStateMessage.ts +59 -23
- package/controller/comms/messages/status/HeaterStateMessage.ts +57 -3
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +56 -8
- package/controller/comms/messages/status/PumpStateMessage.ts +23 -1
- package/controller/nixie/Nixie.ts +1 -1
- package/controller/nixie/bodies/Body.ts +3 -0
- package/controller/nixie/chemistry/ChemController.ts +164 -51
- package/controller/nixie/chemistry/Chlorinator.ts +137 -88
- package/controller/nixie/circuits/Circuit.ts +51 -19
- package/controller/nixie/heaters/Heater.ts +241 -31
- package/controller/nixie/pumps/Pump.ts +488 -206
- package/controller/nixie/schedules/Schedule.ts +91 -35
- package/controller/nixie/valves/Valve.ts +1 -1
- package/defaultConfig.json +20 -0
- package/package.json +21 -21
- package/web/Server.ts +94 -49
- package/web/bindings/aqualinkD.json +505 -0
- package/web/bindings/influxDB.json +71 -1
- package/web/bindings/mqtt.json +98 -39
- package/web/bindings/mqttAlt.json +59 -1
- package/web/interfaces/baseInterface.ts +1 -0
- package/web/interfaces/httpInterface.ts +23 -2
- package/web/interfaces/influxInterface.ts +45 -10
- package/web/interfaces/mqttInterface.ts +114 -54
- package/web/services/config/Config.ts +55 -132
- package/web/services/state/State.ts +81 -4
- package/web/services/state/StateSocket.ts +4 -4
- package/web/services/utilities/Utilities.ts +8 -6
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -52
- package/config copy.json +0 -300
- package/issue_template.md +0 -52
package/controller/Equipment.ts
CHANGED
|
@@ -70,6 +70,7 @@ interface IPoolSystem {
|
|
|
70
70
|
|
|
71
71
|
export class PoolSystem implements IPoolSystem {
|
|
72
72
|
public _hasChanged: boolean = false;
|
|
73
|
+
public isReady: boolean = false;
|
|
73
74
|
constructor() {
|
|
74
75
|
this.cfgPath = path.posix.join(process.cwd(), '/data/poolConfig.json');
|
|
75
76
|
}
|
|
@@ -142,6 +143,7 @@ export class PoolSystem implements IPoolSystem {
|
|
|
142
143
|
}
|
|
143
144
|
else
|
|
144
145
|
this.initNixieController();
|
|
146
|
+
this.isReady = true;
|
|
145
147
|
}
|
|
146
148
|
public init() {
|
|
147
149
|
let cfg = this.loadConfigFile(this.cfgPath, {});
|
|
@@ -202,7 +204,7 @@ export class PoolSystem implements IPoolSystem {
|
|
|
202
204
|
}
|
|
203
205
|
|
|
204
206
|
public resetSystem() {
|
|
205
|
-
conn.
|
|
207
|
+
conn.pauseAll();
|
|
206
208
|
this.resetData();
|
|
207
209
|
state.resetData();
|
|
208
210
|
this.data.controllerType === 'unknown';
|
|
@@ -210,7 +212,7 @@ export class PoolSystem implements IPoolSystem {
|
|
|
210
212
|
this.controllerType = ControllerType.Unknown;
|
|
211
213
|
state.status = 0;
|
|
212
214
|
this.board = BoardFactory.fromControllerType(ControllerType.Unknown, this);
|
|
213
|
-
setTimeout(function () { state.status = 0; conn.
|
|
215
|
+
setTimeout(function () { state.status = 0; conn.resumeAll(); }, 0);
|
|
214
216
|
}
|
|
215
217
|
public get controllerType(): ControllerType { return this.data.controllerType as ControllerType; }
|
|
216
218
|
public set controllerType(val: ControllerType) {
|
|
@@ -537,7 +539,7 @@ class EqItemCollection<T> implements IEqItemCollection {
|
|
|
537
539
|
return this.createItem(extend({}, { id: ndx + 1 }, data));
|
|
538
540
|
}
|
|
539
541
|
public getItemById(id: number | string, add?: boolean, data?: any): T {
|
|
540
|
-
let itm = this.find(elem =>
|
|
542
|
+
let itm = this.find(elem => { return typeof (elem as { id?}).id !== 'undefined' && (elem as { id?}).id === id });
|
|
541
543
|
if (typeof itm !== 'undefined') return itm;
|
|
542
544
|
if (typeof add !== 'undefined' && add) return this.add(extend(true, { id: id }, data));
|
|
543
545
|
return this.createItem(data || { id: id });
|
|
@@ -567,7 +569,7 @@ class EqItemCollection<T> implements IEqItemCollection {
|
|
|
567
569
|
this.data.splice(ndx, 1);
|
|
568
570
|
}
|
|
569
571
|
// Finds an item and returns undefined if it doesn't exist.
|
|
570
|
-
public find(f: (value:
|
|
572
|
+
public find(f: (value: T, index?: number, obj?: any) => boolean): T {
|
|
571
573
|
let itm = this.data.find(f);
|
|
572
574
|
if (typeof itm !== 'undefined') return this.createItem(itm);
|
|
573
575
|
}
|
|
@@ -612,7 +614,7 @@ class EqItemCollection<T> implements IEqItemCollection {
|
|
|
612
614
|
});
|
|
613
615
|
}
|
|
614
616
|
public sort(fn: (a, b) => number) { this.data.sort(fn); }
|
|
615
|
-
public count(fn: () => boolean): number { return this.data.filter(fn).length; }
|
|
617
|
+
public count(fn: (value: T, index?: any, array?: any[]) => boolean): number { return this.data.filter(fn).length; }
|
|
616
618
|
public getNextEquipmentId(range: EquipmentIdRange, exclude?: number[]): number {
|
|
617
619
|
for (let i = range.start; i <= range.end; i++) {
|
|
618
620
|
let eq = this.data.find(elem => elem.id === i);
|
|
@@ -724,6 +726,16 @@ export class Options extends EqItem {
|
|
|
724
726
|
if (typeof this.data.clockMode === 'undefined') this.data.clockMode = 12;
|
|
725
727
|
if (typeof this.data.adjustDST === 'undefined') this.data.adjustDST = true;
|
|
726
728
|
if (typeof this.data.freezeThreshold === 'undefined') this.data.freezeThreshold = 35;
|
|
729
|
+
if (typeof this.data.pumpDelay === 'undefined') this.data.pumpDelay = false;
|
|
730
|
+
if (typeof this.data.valveDelayTime === 'undefined') this.data.valveDelayTime = 30;
|
|
731
|
+
// RKS: 12-04-21 If you are reading this in a few months delete the line below.
|
|
732
|
+
if (this.data.valveDelayTime > 1000) this.data.valveDelayTime = this.data.valveDelayTime / 1000;
|
|
733
|
+
if (typeof this.data.heaterStartDelay === 'undefined') this.data.heaterStartDelay = true;
|
|
734
|
+
if (typeof this.data.cleanerStartDelay === 'undefined') this.data.cleanerStartDelay = true;
|
|
735
|
+
if (typeof this.data.cleanerSolarDelay === 'undefined') this.data.cleanerSolarDelay = true;
|
|
736
|
+
if (typeof this.data.heaterStartDelayTime === 'undefined') this.data.heaterStartDelayTime = 10;
|
|
737
|
+
if (typeof this.data.cleanerStartDelayTime === 'undefined') this.data.cleanerStartDelayTime = 300; // 5min
|
|
738
|
+
if (typeof this.data.cleanerSolarDelayTime === 'undefined') this.data.cleanerSolarDelayTime = 300; // 5min
|
|
727
739
|
}
|
|
728
740
|
public get clockMode(): number | any { return this.data.clockMode; }
|
|
729
741
|
public set clockMode(val: number | any) { this.setDataVal('clockMode', sys.board.valueMaps.clockModes.encode(val)); }
|
|
@@ -740,10 +752,25 @@ export class Options extends EqItem {
|
|
|
740
752
|
public set manualHeat(val: boolean) { this.setDataVal('manualHeat', val); }
|
|
741
753
|
public get pumpDelay(): boolean { return this.data.pumpDelay; }
|
|
742
754
|
public set pumpDelay(val: boolean) { this.setDataVal('pumpDelay', val); }
|
|
755
|
+
public get valveDelayTime(): number { return this.data.valveDelayTime; }
|
|
756
|
+
public set valveDelayTime(val: number) { this.setDataVal('valveDelayTime', val); }
|
|
743
757
|
public get cooldownDelay(): boolean { return this.data.cooldownDelay; }
|
|
744
758
|
public set cooldownDelay(val: boolean) { this.setDataVal('cooldownDelay', val); }
|
|
745
759
|
public get freezeThreshold(): number { return this.data.freezeThreshold; }
|
|
746
760
|
public set freezeThreshold(val: number) { this.setDataVal('freezeThreshold', val); }
|
|
761
|
+
public get heaterStartDelay(): boolean { return this.data.heaterStartDelay; }
|
|
762
|
+
public set heaterStartDelay(val: boolean) { this.setDataVal('heaterStartDelay', val); }
|
|
763
|
+
public get heaterStartDelayTime(): number { return this.data.heaterStartDelayTime; }
|
|
764
|
+
public set heaterStartDelayTime(val: number) { this.setDataVal('heaterStartDelayTime', val); }
|
|
765
|
+
|
|
766
|
+
public get cleanerStartDelay(): boolean { return this.data.cleanerStartDelay; }
|
|
767
|
+
public set cleanerStartDelay(val: boolean) { this.setDataVal('cleanerStartDelay', val); }
|
|
768
|
+
public get cleanerStartDelayTime(): number { return this.data.cleanerStartDelayTime; }
|
|
769
|
+
public set cleanerStartDelayTime(val: number) { this.setDataVal('cleanerStartDelayTime', val); }
|
|
770
|
+
public get cleanerSolarDelay(): boolean { return this.data.cleanerSolarDelay; }
|
|
771
|
+
public set cleanerSolarDelay(val: boolean) { this.setDataVal('cleanerSolarDelay', val); }
|
|
772
|
+
public get cleanerSolarDelayTime(): number { return this.data.cleanerSolarDelayTime; }
|
|
773
|
+
public set cleanerSolarDelayTime(val: number) { this.setDataVal('cleanerSolarDelayTime', val); }
|
|
747
774
|
|
|
748
775
|
//public get airTempAdj(): number { return typeof this.data.airTempAdj === 'undefined' ? 0 : this.data.airTempAdj; }
|
|
749
776
|
//public set airTempAdj(val: number) { this.setDataVal('airTempAdj', val); }
|
|
@@ -994,7 +1021,7 @@ export class BodyCollection extends EqItemCollection<Body> {
|
|
|
994
1021
|
let body = this.find(elem => {
|
|
995
1022
|
if (typeof obj.id !== 'undefined') return obj.id === elem.id;
|
|
996
1023
|
else if (typeof obj.circuit !== 'undefined') return obj.circuit === elem.circuit;
|
|
997
|
-
else if (typeof obj.name !== 'undefined') return obj.name ===
|
|
1024
|
+
else if (typeof obj.name !== 'undefined') return obj.name === elem.name;
|
|
998
1025
|
else return false;
|
|
999
1026
|
});
|
|
1000
1027
|
return body;
|
|
@@ -1004,6 +1031,7 @@ export class Body extends EqItem {
|
|
|
1004
1031
|
public dataName = 'bodyConfig';
|
|
1005
1032
|
public initData() {
|
|
1006
1033
|
if (typeof this.data.capacityUnits === 'undefined') this.data.capacityUnits = 1;
|
|
1034
|
+
if (typeof this.data.showInDashboard === 'undefined') this.data.showInDashboard = true;
|
|
1007
1035
|
}
|
|
1008
1036
|
public get id(): number { return this.data.id; }
|
|
1009
1037
|
public set id(val: number) { this.data.id = val; }
|
|
@@ -1029,6 +1057,8 @@ export class Body extends EqItem {
|
|
|
1029
1057
|
public set heatSetpoint(val: number) { this.setDataVal('setPoint', val); }
|
|
1030
1058
|
public get coolSetpoint(): number { return this.data.coolSetpoint; }
|
|
1031
1059
|
public set coolSetpoint(val: number) { this.setDataVal('coolSetpoint', val); }
|
|
1060
|
+
public get showInDashboard(): boolean { return this.data.showInDashboard; }
|
|
1061
|
+
public set showInDashboard(val: boolean) { this.setDataVal('showInDashboard', val); }
|
|
1032
1062
|
public get capacityUnits(): number | any { return this.data.capacityUnits; }
|
|
1033
1063
|
public set capacityUnits(val: number | any) { this.setDataVal('capacityUnits', sys.board.valueMaps.volumeUnits.encode(val)); }
|
|
1034
1064
|
public getHeatModes() { return sys.board.bodies.getHeatModes(this.id); }
|
|
@@ -1083,6 +1113,8 @@ export class Schedule extends EqItem {
|
|
|
1083
1113
|
public set coolSetpoint(val: number) { this.setDataVal('coolSetpoint', val); }
|
|
1084
1114
|
public get isActive(): boolean { return this.data.isActive; }
|
|
1085
1115
|
public set isActive(val: boolean) { this.setDataVal('isActive', val); }
|
|
1116
|
+
public get disabled(): boolean { return this.data.disabled; }
|
|
1117
|
+
public set disabled(val: boolean) { this.setDataVal('disabled', val); }
|
|
1086
1118
|
public get startMonth(): number { return this._startDate.getMonth() + 1; }
|
|
1087
1119
|
public set startMonth(val: number) { if (typeof this._startDate === 'undefined') this._startDate = new Date(); this._startDate.setMonth(val - 1); this._saveStartDate(); }
|
|
1088
1120
|
public get startDay(): number { if (typeof this._startDate === 'undefined') this._startDate = new Date(); return this._startDate.getDate(); }
|
|
@@ -1129,6 +1161,9 @@ export class EggTimer extends EqItem {
|
|
|
1129
1161
|
}
|
|
1130
1162
|
export class CircuitCollection extends EqItemCollection<Circuit> {
|
|
1131
1163
|
constructor(data: any, name?: string) { super(data, name || "circuits"); }
|
|
1164
|
+
public filter(f: (value: Circuit, index?: any, array?: any[]) => boolean): CircuitCollection {
|
|
1165
|
+
return new CircuitCollection({ circuits: this.data.filter(f) });
|
|
1166
|
+
}
|
|
1132
1167
|
public createItem(data: any): Circuit { return new Circuit(data); }
|
|
1133
1168
|
public add(obj: any): Circuit {
|
|
1134
1169
|
this.data.push(obj);
|
|
@@ -1185,7 +1220,35 @@ export class Circuit extends EqItem implements ICircuit {
|
|
|
1185
1220
|
public get deviceBinding(): string { return this.data.deviceBinding; }
|
|
1186
1221
|
public set deviceBinding(val: string) { this.setDataVal('deviceBinding', val); }
|
|
1187
1222
|
public get hasHeatSource() { return typeof sys.board.valueMaps.circuitFunctions.get(this.type || 0).hasHeatSource !== 'undefined' ? sys.board.valueMaps.circuitFunctions.get(this.type || 0).hasHeatSource : false };
|
|
1188
|
-
public getLightThemes() {
|
|
1223
|
+
public getLightThemes() {
|
|
1224
|
+
// Lets do this universally driven by the metadata.
|
|
1225
|
+
let cf = sys.board.valueMaps.circuitFunctions.transform(this.type);
|
|
1226
|
+
if (cf.isLight && typeof cf.theme !== 'undefined') {
|
|
1227
|
+
let arrThemes = sys.board.valueMaps.lightThemes.toArray();
|
|
1228
|
+
let themes = [];
|
|
1229
|
+
for (let i = 0; i < arrThemes.length; i++) {
|
|
1230
|
+
let thm = arrThemes[i];
|
|
1231
|
+
if (typeof thm.types !== 'undefined' && thm.types.length > 0 && thm.types.includes(cf.theme)) themes.push(thm);
|
|
1232
|
+
}
|
|
1233
|
+
return themes;
|
|
1234
|
+
}
|
|
1235
|
+
else return [];
|
|
1236
|
+
}
|
|
1237
|
+
public getLightCommands() {
|
|
1238
|
+
// Lets do this universally driven by the metadata.
|
|
1239
|
+
let cf = sys.board.valueMaps.circuitFunctions.transform(this.type);
|
|
1240
|
+
if (cf.isLight && typeof cf.theme !== 'undefined') {
|
|
1241
|
+
let arrCommands = sys.board.valueMaps.lightCommands.toArray();
|
|
1242
|
+
let cmds = [];
|
|
1243
|
+
for (let i = 0; i < arrCommands.length; i++) {
|
|
1244
|
+
let cmd = arrCommands[i];
|
|
1245
|
+
if (typeof cmd.types !== 'undefined' && cmd.types.length > 0 && cmd.types.includes(cf.theme)) cmds.push(cmd);
|
|
1246
|
+
}
|
|
1247
|
+
return cmds;
|
|
1248
|
+
}
|
|
1249
|
+
else return [];
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1189
1252
|
public static getIdName(id: number) {
|
|
1190
1253
|
// todo: adjust for intellitouch
|
|
1191
1254
|
let defName = "Aux" + (id + 1).toString();
|
|
@@ -1197,6 +1260,9 @@ export class Circuit extends EqItem implements ICircuit {
|
|
|
1197
1260
|
}
|
|
1198
1261
|
export class FeatureCollection extends EqItemCollection<Feature> {
|
|
1199
1262
|
constructor(data: any, name?: string) { super(data, name || "features"); }
|
|
1263
|
+
public filter(f: (value: Circuit, index?: any, array?: any[]) => boolean): FeatureCollection {
|
|
1264
|
+
return new FeatureCollection({ features: this.data.filter(f) });
|
|
1265
|
+
}
|
|
1200
1266
|
public createItem(data: any): Feature { return new Feature(data); }
|
|
1201
1267
|
}
|
|
1202
1268
|
export class Feature extends EqItem implements ICircuit {
|
|
@@ -1206,6 +1272,7 @@ export class Feature extends EqItem implements ICircuit {
|
|
|
1206
1272
|
if (typeof this.data.isActive === 'undefined') this.data.isActive = true;
|
|
1207
1273
|
if (typeof this.data.eggTimer === 'undefined') this.data.eggTimer = 720;
|
|
1208
1274
|
if (typeof this.data.showInFeatures === 'undefined') this.data.showInFeatures = true;
|
|
1275
|
+
if (typeof this.data.master === 'undefined') this.data.master = sys.board.equipmentMaster;
|
|
1209
1276
|
}
|
|
1210
1277
|
public dataName = 'featureConfig';
|
|
1211
1278
|
public get id(): number { return this.data.id; }
|
|
@@ -1246,6 +1313,7 @@ export interface ICircuit {
|
|
|
1246
1313
|
showInFeatures?: boolean;
|
|
1247
1314
|
macro?: boolean;
|
|
1248
1315
|
getLightThemes?: (type?: number) => {};
|
|
1316
|
+
getLightCommands?: (type?: number) => {};
|
|
1249
1317
|
get(copy?: boolean);
|
|
1250
1318
|
master: number;
|
|
1251
1319
|
}
|
|
@@ -1266,9 +1334,12 @@ export class Pump extends EqItem {
|
|
|
1266
1334
|
public dataName = 'pumpConfig';
|
|
1267
1335
|
public initData() {
|
|
1268
1336
|
if (typeof this.data.isVirtual !== 'undefined') delete this.data.isVirtual;
|
|
1337
|
+
if (typeof this.data.portId === 'undefined') this.data.portId = 0;
|
|
1269
1338
|
}
|
|
1270
1339
|
public get id(): number { return this.data.id; }
|
|
1271
1340
|
public set id(val: number) { this.setDataVal('id', val); }
|
|
1341
|
+
public get portId(): number { return this.data.portId; }
|
|
1342
|
+
public set portId(val: number) { this.setDataVal('portId', val); }
|
|
1272
1343
|
public get address(): number { return this.data.address || this.data.id + 95; }
|
|
1273
1344
|
public set address(val: number) { this.setDataVal('address', val); }
|
|
1274
1345
|
public get name(): string { return this.data.name; }
|
|
@@ -1412,6 +1483,13 @@ export class ChlorinatorCollection extends EqItemCollection<Chlorinator> {
|
|
|
1412
1483
|
body === 32 && elem.body <= 2 ||
|
|
1413
1484
|
elem.body === 32 && body <= 2);
|
|
1414
1485
|
}
|
|
1486
|
+
public getItemByPortId(portId: number, add?: boolean, data?: any): Chlorinator {
|
|
1487
|
+
let itm = this.find(elem => { return typeof (elem as { portId?}).portId !== 'undefined' && (elem as { portId?}).portId === portId });
|
|
1488
|
+
if (typeof itm !== 'undefined') return itm;
|
|
1489
|
+
if (typeof add !== 'undefined' && add) return this.add(extend(true, { portId: portId }, data));
|
|
1490
|
+
return this.createItem(extend(true, data, { portId: portId }));
|
|
1491
|
+
}
|
|
1492
|
+
public findItemByPortId(portId: number) { return this.find(elem => { return typeof (elem as { portId?}).portId !== 'undefined' && (elem as { portId?}).portId === portId }); }
|
|
1415
1493
|
}
|
|
1416
1494
|
export class Chlorinator extends EqItem {
|
|
1417
1495
|
public dataName = 'chlorinatorConfig';
|
|
@@ -1419,9 +1497,12 @@ export class Chlorinator extends EqItem {
|
|
|
1419
1497
|
if (typeof this.data.disabled === 'undefined') this.data.disabled = false;
|
|
1420
1498
|
if (typeof this.data.ignoreSaltReading === 'undefined') this.data.ignoreSaltReading = false;
|
|
1421
1499
|
if (typeof this.data.isVirtual !== 'undefined') delete this.data.isVirtual;
|
|
1500
|
+
if (typeof this.data.portId === 'undefined') this.data.portId = 0;
|
|
1422
1501
|
}
|
|
1423
1502
|
public get id(): number { return this.data.id; }
|
|
1424
1503
|
public set id(val: number) { this.setDataVal('id', val); }
|
|
1504
|
+
public get portId(): number { return this.data.portId; }
|
|
1505
|
+
public set portId(val: number) { this.setDataVal('portId', val); }
|
|
1425
1506
|
public get type(): number | any { return this.data.type; }
|
|
1426
1507
|
public set type(val: number | any) { this.setDataVal('type', sys.board.valueMaps.chlorinatorType.encode(val)); }
|
|
1427
1508
|
public get body(): number | any { return this.data.body; }
|
|
@@ -1454,6 +1535,22 @@ export class Chlorinator extends EqItem {
|
|
|
1454
1535
|
export class ValveCollection extends EqItemCollection<Valve> {
|
|
1455
1536
|
constructor(data: any, name?: string) { super(data, name || "valves"); }
|
|
1456
1537
|
public createItem(data: any): Valve { return new Valve(data); }
|
|
1538
|
+
public getIntake(): Valve[] {
|
|
1539
|
+
let valves = this.data.filter(x => x.isIntake === true);
|
|
1540
|
+
let ret = [];
|
|
1541
|
+
for (let i = 0; i < valves.length; i++) {
|
|
1542
|
+
ret.push(this.getItemById(valves[i].id));
|
|
1543
|
+
}
|
|
1544
|
+
return ret;
|
|
1545
|
+
}
|
|
1546
|
+
public getReturn(): Valve[] {
|
|
1547
|
+
let valves = this.data.filter(x => x.isReturn === true);
|
|
1548
|
+
let ret = [];
|
|
1549
|
+
for (let i = 0; i < valves.length; i++) {
|
|
1550
|
+
ret.push(this.getItemById(valves[i].id));
|
|
1551
|
+
}
|
|
1552
|
+
return ret;
|
|
1553
|
+
}
|
|
1457
1554
|
}
|
|
1458
1555
|
export class Valve extends EqItem {
|
|
1459
1556
|
public dataName = 'valveConfig';
|
|
@@ -1492,14 +1589,33 @@ export class HeaterCollection extends EqItemCollection<Heater> {
|
|
|
1492
1589
|
if (typeof add !== 'undefined' && add) return this.add(data || { id: this.data.length + 1, address: address });
|
|
1493
1590
|
return this.createItem(data || { id: this.data.length + 1, address: address });
|
|
1494
1591
|
}
|
|
1592
|
+
public filter(f: (value: Heater, index?: any, array?: any[]) => boolean): HeaterCollection {
|
|
1593
|
+
return new HeaterCollection({ heaters: this.data.filter(f) });
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
public getSolarHeaters(bodyId?: number): EqItemCollection<Heater> {
|
|
1597
|
+
let htype = sys.board.valueMaps.heaterTypes.getValue('solar');
|
|
1598
|
+
return new HeaterCollection(this.data.filter(x => {
|
|
1599
|
+
if (x.type === htype) {
|
|
1600
|
+
if (typeof bodyId !== 'undefined') {
|
|
1601
|
+
if (!x.isActive) return false;
|
|
1602
|
+
return (bodyId === x.body || (sys.equipment.shared && x.body === 32)) ? true : false;
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
return false;
|
|
1606
|
+
}));
|
|
1607
|
+
}
|
|
1495
1608
|
}
|
|
1496
1609
|
export class Heater extends EqItem {
|
|
1497
1610
|
public dataName = 'heaterConfig';
|
|
1498
1611
|
public initData() {
|
|
1499
1612
|
if (typeof this.data.isActive === 'undefined') this.data.isActive = true;
|
|
1613
|
+
if (typeof this.data.portId === 'undefined') this.data.portId = 0;
|
|
1500
1614
|
}
|
|
1501
1615
|
public get id(): number { return this.data.id; }
|
|
1502
1616
|
public set id(val: number) { this.setDataVal('id', val); }
|
|
1617
|
+
public get portId(): number { return this.data.portId; }
|
|
1618
|
+
public set portId(val: number) { this.setDataVal('portId', val); }
|
|
1503
1619
|
public get type(): number | any { return this.data.type; }
|
|
1504
1620
|
public set type(val: number | any) { this.setDataVal('type', sys.board.valueMaps.heaterTypes.encode(val)); }
|
|
1505
1621
|
public get name(): string { return this.data.name; }
|
|
@@ -1532,6 +1648,8 @@ export class Heater extends EqItem {
|
|
|
1532
1648
|
public set economyTime(val: number) { this.setDataVal('economyTime', val); }
|
|
1533
1649
|
public get connectionId(): string { return this.data.connectionId; }
|
|
1534
1650
|
public set connectionId(val: string) { this.setDataVal('connectionId', val); }
|
|
1651
|
+
public get minCycleTime(): number { return this.data.minCycleTime; }
|
|
1652
|
+
public set minCycleTime(val: number) { this.setDataVal('minCycleTime', val); }
|
|
1535
1653
|
public get deviceBinding(): string { return this.data.deviceBinding; }
|
|
1536
1654
|
public set deviceBinding(val: string) { this.setDataVal('deviceBinding', val); }
|
|
1537
1655
|
}
|
|
@@ -1664,7 +1782,61 @@ export class LightGroup extends EqItem implements ICircuitGroup, ICircuit {
|
|
|
1664
1782
|
public get lightingTheme(): number | any { return this.data.lightingTheme; }
|
|
1665
1783
|
public set lightingTheme(val: number | any) { this.setDataVal('lightingTheme', sys.board.valueMaps.lightThemes.encode(val)); }
|
|
1666
1784
|
public get circuits(): LightGroupCircuitCollection { return new LightGroupCircuitCollection(this.data, "circuits"); }
|
|
1667
|
-
public getLightThemes() {
|
|
1785
|
+
public getLightThemes() {
|
|
1786
|
+
// Go through the circuits and gather the themes.
|
|
1787
|
+
// This method first looks at the circuits to determine their type (function)
|
|
1788
|
+
// then it filters the list by the types associated with the circuits. It does this because
|
|
1789
|
+
// there can be combined ColorLogic and IntelliBrite lights. The themes array has
|
|
1790
|
+
// the circuit function.
|
|
1791
|
+
let arrThemes = [];
|
|
1792
|
+
for (let i = 0; i < this.circuits.length; i++) {
|
|
1793
|
+
let circ = this.circuits.getItemByIndex(i);
|
|
1794
|
+
let c = sys.circuits.getInterfaceById(circ.circuit);
|
|
1795
|
+
let cf = sys.board.valueMaps.circuitFunctions.transform(c.type);
|
|
1796
|
+
if (cf.isLight && typeof cf.theme !== 'undefined') {
|
|
1797
|
+
if (!arrThemes.includes(cf.theme)) arrThemes.push(cf.theme);
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
// Alright now we need to get a listing of the themes.
|
|
1801
|
+
let t = sys.board.valueMaps.lightThemes.toArray();
|
|
1802
|
+
let ret = [];
|
|
1803
|
+
for (let i = 0; i < t.length; i++) {
|
|
1804
|
+
let thm = t[i];
|
|
1805
|
+
if (typeof thm.types !== 'undefined' && thm.types.length > 0) {
|
|
1806
|
+
// Look in the themes array of the theme.
|
|
1807
|
+
if (arrThemes.some(x => thm.types.includes(x))) ret.push(thm);
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
return ret;
|
|
1811
|
+
}
|
|
1812
|
+
public getLightCommands() {
|
|
1813
|
+
// Go through the circuits and gather the themes.
|
|
1814
|
+
// This method first looks at the circuits to determine their type (function)
|
|
1815
|
+
// then it filters the list by the types associated with the circuits. It does this because
|
|
1816
|
+
// there can be combined ColorLogic and IntelliBrite lights. The themes array has
|
|
1817
|
+
// the circuit function.
|
|
1818
|
+
let arrThemes = [];
|
|
1819
|
+
for (let i = 0; i < this.circuits.length; i++) {
|
|
1820
|
+
let circ = this.circuits.getItemByIndex(i);
|
|
1821
|
+
let c = sys.circuits.getInterfaceById(circ.circuit);
|
|
1822
|
+
let cf = sys.board.valueMaps.circuitFunctions.transform(c.type);
|
|
1823
|
+
if (cf.isLight && typeof cf.theme !== 'undefined') {
|
|
1824
|
+
if (!arrThemes.includes(cf.theme)) arrThemes.push(cf.theme);
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1827
|
+
// Alright now we need to get a listing of the themes.
|
|
1828
|
+
let t = sys.board.valueMaps.lightGroupCommands.toArray();
|
|
1829
|
+
let ret = [];
|
|
1830
|
+
for (let i = 0; i < t.length; i++) {
|
|
1831
|
+
let cmd = t[i];
|
|
1832
|
+
if (typeof cmd.types !== 'undefined' && cmd.types.length > 0) {
|
|
1833
|
+
// Look in the themes array of the theme.
|
|
1834
|
+
if (arrThemes.some(x => cmd.types.includes(x))) ret.push(cmd);
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
return ret;
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1668
1840
|
public getExtended() {
|
|
1669
1841
|
let group = this.get(true);
|
|
1670
1842
|
group.type = sys.board.valueMaps.circuitGroupTypes.transform(group.type);
|
|
@@ -1993,7 +2165,7 @@ export class ChemController extends EqItem {
|
|
|
1993
2165
|
public getExtended() {
|
|
1994
2166
|
let chem = this.get(true);
|
|
1995
2167
|
chem.type = sys.board.valueMaps.chemControllerTypes.transform(this.type);
|
|
1996
|
-
chem.siCalcType = sys.board.valueMaps.siCalcTypes.transform(this.
|
|
2168
|
+
chem.siCalcType = sys.board.valueMaps.siCalcTypes.transform(this.siCalcType || 0);
|
|
1997
2169
|
chem.body = sys.board.valueMaps.bodies.transform(this.body);
|
|
1998
2170
|
chem.ph = this.ph.getExtended();
|
|
1999
2171
|
chem.orp = this.orp.getExtended();
|
|
@@ -2038,11 +2210,14 @@ export class Chemical extends ChildEqItem {
|
|
|
2038
2210
|
if (typeof this.data.flowReadingsOnly === 'undefined') this.data.flowReadingsOnly = true;
|
|
2039
2211
|
if (typeof this.data.flowOnlyMixing === 'undefined') this.data.flowOnlyMixing = true;
|
|
2040
2212
|
if (typeof this.data.maxDailyVolume === 'undefined') this.data.maxDailyVolume = 500;
|
|
2213
|
+
if (typeof this.data.disableOnFreeze === 'undefined') this.data.disableOnFreeze = true;
|
|
2041
2214
|
super.initData();
|
|
2042
2215
|
}
|
|
2043
2216
|
public get chemType(): string { return this.data.chemType; }
|
|
2044
2217
|
public get enabled(): boolean { return utils.makeBool(this.data.enabled); }
|
|
2045
2218
|
public set enabled(val: boolean) { this.setDataVal('enabled', val); }
|
|
2219
|
+
public get disableOnFreeze(): boolean { return utils.makeBool(this.data.disableOnFreeze); }
|
|
2220
|
+
public set disableOnFreeze(val: boolean) { this.setDataVal('disableOnFreeze', val); }
|
|
2046
2221
|
public get maxDosingTime(): number { return this.data.maxDosingTime; }
|
|
2047
2222
|
public set maxDosingTime(val: number) { this.setDataVal('maxDosingTime', val); }
|
|
2048
2223
|
public get maxDosingVolume(): number { return this.data.maxDosingVolume; }
|
|
@@ -2083,6 +2258,7 @@ export class ChemicalPh extends Chemical {
|
|
|
2083
2258
|
if (typeof this.data.acidType === 'undefined') this.data.acidType = 0;
|
|
2084
2259
|
if (typeof this.data.tolerance === 'undefined') this.data.tolerance = { low: 7.2, high: 7.6, enabled: true };
|
|
2085
2260
|
if (typeof this.data.dosePriority === 'undefined') this.data.dosePriority = true;
|
|
2261
|
+
if (typeof this.data.doserType === 'undefined') this.data.doserType = 0;
|
|
2086
2262
|
super.initData();
|
|
2087
2263
|
}
|
|
2088
2264
|
public get phSupply(): number | any { return this.data.phSupply; }
|
|
@@ -2091,11 +2267,14 @@ export class ChemicalPh extends Chemical {
|
|
|
2091
2267
|
public set acidType(val: number | any) { this.setDataVal('acidType', sys.board.valueMaps.acidTypes.encode(val)); }
|
|
2092
2268
|
public get dosePriority(): boolean { return this.data.dosePriority; }
|
|
2093
2269
|
public set dosePriority(val: boolean) { this.setDataVal('dosePriority', val); }
|
|
2270
|
+
public get doserType(): number | any { return this.data.doserType; }
|
|
2271
|
+
public set doserType(val: number | any) { this.setDataVal('doserType', sys.board.valueMaps.phDoserTypes.encode(val)); }
|
|
2094
2272
|
public get probe(): ChemicalPhProbe { return new ChemicalPhProbe(this.data, 'probe', this); }
|
|
2095
2273
|
public getExtended() {
|
|
2096
2274
|
let chem = super.getExtended();
|
|
2097
2275
|
chem.probe = this.probe.getExtended();
|
|
2098
2276
|
chem.phSupply = sys.board.valueMaps.phSupplyTypes.transform(this.phSupply);
|
|
2277
|
+
chem.doserType = sys.board.valueMaps.phDoserTypes.transform(this.doserType);
|
|
2099
2278
|
return chem;
|
|
2100
2279
|
}
|
|
2101
2280
|
}
|
|
@@ -2108,6 +2287,7 @@ export class ChemicalORP extends Chemical {
|
|
|
2108
2287
|
if (typeof this.data.probe === 'undefined') this.data.probe = {};
|
|
2109
2288
|
if (typeof this.data.tolerance === 'undefined') this.data.tolerance = { low: 650, high: 800, enabled: true };
|
|
2110
2289
|
if (typeof this.data.phLockout === 'undefined') this.data.phLockout = 7.8;
|
|
2290
|
+
if (typeof this.data.doserType === 'undefined') this.data.doserType = 0;
|
|
2111
2291
|
super.initData();
|
|
2112
2292
|
}
|
|
2113
2293
|
public get useChlorinator(): boolean { return utils.makeBool(this.data.useChlorinator); }
|
|
@@ -2117,9 +2297,13 @@ export class ChemicalORP extends Chemical {
|
|
|
2117
2297
|
public get probe(): ChemicalORPProbe { return new ChemicalORPProbe(this.data, 'probe', this); }
|
|
2118
2298
|
public get chlorDosingMethod(): number | any { return this.data.chlorDosingMethod; }
|
|
2119
2299
|
public set chlorDosingMethod(val: number | any) { this.setDataVal('chlorDosingMethod', sys.board.valueMaps.chemChlorDosingMethods.encode(val)); }
|
|
2300
|
+
public get doserType(): number | any { return this.data.doserType; }
|
|
2301
|
+
public set doserType(val: number | any) { this.setDataVal('doserType', sys.board.valueMaps.orpDoserTypes.encode(val)); }
|
|
2302
|
+
|
|
2120
2303
|
public getExtended() {
|
|
2121
2304
|
let chem = super.getExtended();
|
|
2122
2305
|
chem.probe = this.probe.getExtended();
|
|
2306
|
+
chem.doserType = sys.board.valueMaps.orpDoserTypes.transform(this.doserType);
|
|
2123
2307
|
return chem;
|
|
2124
2308
|
}
|
|
2125
2309
|
}
|
package/controller/Errors.ts
CHANGED
|
@@ -144,6 +144,16 @@ export class ParameterOutOfRangeError extends InvalidOperationError {
|
|
|
144
144
|
public value;
|
|
145
145
|
public parameter: string;
|
|
146
146
|
}
|
|
147
|
+
export class BoardProcessError extends ApiError {
|
|
148
|
+
constructor(message: string, process?: string) {
|
|
149
|
+
super(message, 300, 400);
|
|
150
|
+
this.name = 'ProcessingError';
|
|
151
|
+
this.process = process;
|
|
152
|
+
}
|
|
153
|
+
public process: string;
|
|
154
|
+
|
|
155
|
+
}
|
|
156
|
+
|
|
147
157
|
export class MessageError extends ApiError {
|
|
148
158
|
constructor(msg: Message, message: string, code?: number, httpCode?: number) {
|
|
149
159
|
super(message, code, httpCode);
|