nodejs-poolcontroller 7.7.0 → 8.0.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/.eslintrc.json +26 -35
- package/Changelog +22 -0
- package/README.md +7 -3
- package/anslq25/MessagesMock.ts +218 -0
- package/anslq25/boards/MockBoardFactory.ts +50 -0
- package/anslq25/boards/MockEasyTouchBoard.ts +696 -0
- package/anslq25/boards/MockSystemBoard.ts +217 -0
- package/anslq25/chemistry/MockChlorinator.ts +75 -0
- package/anslq25/pumps/MockPump.ts +84 -0
- package/app.ts +10 -14
- package/config/Config.ts +13 -9
- package/config/VersionCheck.ts +6 -2
- package/controller/Constants.ts +58 -25
- package/controller/Equipment.ts +225 -41
- package/controller/Errors.ts +2 -1
- package/controller/Lockouts.ts +34 -2
- package/controller/State.ts +491 -48
- package/controller/boards/AquaLinkBoard.ts +6 -3
- package/controller/boards/BoardFactory.ts +5 -1
- package/controller/boards/EasyTouchBoard.ts +1971 -1751
- package/controller/boards/IntelliCenterBoard.ts +1311 -1688
- package/controller/boards/IntelliComBoard.ts +7 -1
- package/controller/boards/IntelliTouchBoard.ts +153 -42
- package/controller/boards/NixieBoard.ts +209 -66
- package/controller/boards/SunTouchBoard.ts +393 -0
- package/controller/boards/SystemBoard.ts +1862 -1543
- package/controller/comms/Comms.ts +539 -138
- package/controller/comms/ScreenLogic.ts +1663 -0
- package/controller/comms/messages/Messages.ts +242 -60
- package/controller/comms/messages/config/ChlorinatorMessage.ts +4 -3
- package/controller/comms/messages/config/CircuitGroupMessage.ts +5 -2
- package/controller/comms/messages/config/CircuitMessage.ts +81 -13
- package/controller/comms/messages/config/ConfigMessage.ts +3 -1
- package/controller/comms/messages/config/CoverMessage.ts +2 -1
- package/controller/comms/messages/config/CustomNameMessage.ts +2 -1
- package/controller/comms/messages/config/EquipmentMessage.ts +5 -1
- package/controller/comms/messages/config/ExternalMessage.ts +33 -3
- package/controller/comms/messages/config/FeatureMessage.ts +2 -1
- package/controller/comms/messages/config/GeneralMessage.ts +2 -1
- package/controller/comms/messages/config/HeaterMessage.ts +3 -1
- package/controller/comms/messages/config/IntellichemMessage.ts +2 -1
- package/controller/comms/messages/config/OptionsMessage.ts +12 -6
- package/controller/comms/messages/config/PumpMessage.ts +9 -12
- package/controller/comms/messages/config/RemoteMessage.ts +80 -13
- package/controller/comms/messages/config/ScheduleMessage.ts +43 -3
- package/controller/comms/messages/config/SecurityMessage.ts +2 -1
- package/controller/comms/messages/config/ValveMessage.ts +43 -26
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +8 -7
- package/controller/comms/messages/status/EquipmentStateMessage.ts +93 -20
- package/controller/comms/messages/status/HeaterStateMessage.ts +24 -5
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +7 -4
- package/controller/comms/messages/status/IntelliValveStateMessage.ts +2 -1
- package/controller/comms/messages/status/PumpStateMessage.ts +72 -4
- package/controller/comms/messages/status/VersionMessage.ts +2 -1
- package/controller/nixie/Nixie.ts +15 -4
- package/controller/nixie/NixieEquipment.ts +1 -0
- package/controller/nixie/chemistry/ChemController.ts +300 -129
- package/controller/nixie/chemistry/ChemDoser.ts +806 -0
- package/controller/nixie/chemistry/Chlorinator.ts +133 -129
- package/controller/nixie/circuits/Circuit.ts +171 -30
- package/controller/nixie/heaters/Heater.ts +337 -173
- package/controller/nixie/pumps/Pump.ts +264 -236
- package/controller/nixie/schedules/Schedule.ts +9 -3
- package/defaultConfig.json +46 -5
- package/logger/Logger.ts +38 -9
- package/package.json +13 -9
- package/web/Server.ts +235 -122
- package/web/bindings/aqualinkD.json +114 -59
- package/web/bindings/homeassistant.json +437 -0
- package/web/bindings/influxDB.json +15 -0
- package/web/bindings/mqtt.json +28 -9
- package/web/bindings/mqttAlt.json +15 -0
- package/web/interfaces/baseInterface.ts +58 -7
- package/web/interfaces/httpInterface.ts +5 -2
- package/web/interfaces/influxInterface.ts +9 -2
- package/web/interfaces/mqttInterface.ts +234 -74
- package/web/interfaces/ruleInterface.ts +87 -0
- package/web/services/config/Config.ts +140 -33
- package/web/services/config/ConfigSocket.ts +2 -1
- package/web/services/state/State.ts +144 -3
- package/web/services/state/StateSocket.ts +65 -14
- package/web/services/utilities/Utilities.ts +189 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* nodejs-poolController. An application to control pool equipment.
|
|
2
|
-
Copyright (C) 2016, 2017, 2018, 2019, 2020
|
|
2
|
+
Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021, 2022.
|
|
3
|
+
Russell Goldin, tagyoureit. russ.goldin@gmail.com
|
|
3
4
|
|
|
4
5
|
This program is free software: you can redistribute it and/or modify
|
|
5
6
|
it under the terms of the GNU Affero General Public License as
|
|
@@ -15,11 +16,11 @@ You should have received a copy of the GNU Affero General Public License
|
|
|
15
16
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
17
|
*/
|
|
17
18
|
import * as fs from "fs";
|
|
19
|
+
import * as path from "path";
|
|
18
20
|
import * as express from "express";
|
|
19
21
|
import * as extend from 'extend';
|
|
20
22
|
import * as multer from 'multer';
|
|
21
|
-
import
|
|
22
|
-
import { sys, LightGroup, ControllerType, Pump, Valve, Body, General, Circuit, ICircuit, Feature, CircuitGroup, CustomNameCollection, Schedule, Chlorinator, Heater } from "../../../controller/Equipment";
|
|
23
|
+
import { sys, LightGroup, ControllerType, Pump, Valve, Body, General, Circuit, ICircuit, Feature, CircuitGroup, CustomNameCollection, Schedule, Chlorinator, Heater, Screenlogic } from "../../../controller/Equipment";
|
|
23
24
|
import { config } from "../../../config/Config";
|
|
24
25
|
import { logger } from "../../../logger/Logger";
|
|
25
26
|
import { utils } from "../../../controller/Constants";
|
|
@@ -29,6 +30,8 @@ import { stopPacketCaptureAsync, startPacketCapture } from '../../../app';
|
|
|
29
30
|
import { conn } from "../../../controller/comms/Comms";
|
|
30
31
|
import { webApp, BackupFile, RestoreFile } from "../../Server";
|
|
31
32
|
import { release } from "os";
|
|
33
|
+
import { ScreenLogicComms, sl } from "../../../controller/comms/ScreenLogic";
|
|
34
|
+
import { screenlogic } from "node-screenlogic";
|
|
32
35
|
|
|
33
36
|
export class ConfigRoute {
|
|
34
37
|
public static initRoutes(app: express.Application) {
|
|
@@ -64,20 +67,48 @@ export class ConfigRoute {
|
|
|
64
67
|
});
|
|
65
68
|
app.get('/config/options/rs485', async (req, res, next) => {
|
|
66
69
|
try {
|
|
67
|
-
let opts = { ports: [], local: [] }
|
|
70
|
+
let opts = { ports: [], local: [], screenlogic: {} }
|
|
68
71
|
let cfg = config.getSection('controller');
|
|
69
72
|
for (let section in cfg) {
|
|
70
73
|
if (section.startsWith('comms')) {
|
|
71
|
-
let cport = extend(true, { enabled: false, netConnect: false }, cfg[section]);
|
|
74
|
+
let cport = extend(true, { enabled: false, netConnect: false, mock: false }, cfg[section]);
|
|
72
75
|
let port = conn.findPortById(cport.portId || 0);
|
|
76
|
+
if (typeof cport.type === 'undefined'){
|
|
77
|
+
cport.type = cport.netConnect ? 'netConnect' : cport.mockPort || cport.mock ? 'mock' : 'local'
|
|
78
|
+
}
|
|
73
79
|
if (typeof port !== 'undefined') cport.stats = port.stats;
|
|
80
|
+
if (port.portId === 0 && port.type === 'screenlogic') {
|
|
81
|
+
cport.screenlogic.stats = sl.stats;
|
|
82
|
+
}
|
|
74
83
|
opts.ports.push(cport);
|
|
75
84
|
}
|
|
85
|
+
// if (section.startsWith('screenlogic')){
|
|
86
|
+
// let screenlogic = cfg[section];
|
|
87
|
+
// screenlogic.types = [{ val: 'local', name: 'Local', desc: 'Local Screenlogic' }, { val: 'remote', name: 'Remote', desc: 'Remote Screenlogic' }];
|
|
88
|
+
// screenlogic.stats = sl.stats;
|
|
89
|
+
// opts.screenlogic = screenlogic;
|
|
90
|
+
// }
|
|
76
91
|
}
|
|
77
92
|
opts.local = await conn.getLocalPortsAsync() || [];
|
|
78
93
|
return res.status(200).send(opts);
|
|
79
94
|
} catch (err) { next(err); }
|
|
80
95
|
});
|
|
96
|
+
// app.get('/config/options/screenlogic', async (req, res, next) => {
|
|
97
|
+
// try {
|
|
98
|
+
// let cfg = config.getSection('controller.screenlogic');
|
|
99
|
+
// let data = {
|
|
100
|
+
// cfg,
|
|
101
|
+
// types: [{ val: 'local', name: 'Local', desc: 'Local Screenlogic' }, { val: 'remote', name: 'Remote', desc: 'Remote Screenlogic' }]
|
|
102
|
+
// }
|
|
103
|
+
// return res.status(200).send(data);
|
|
104
|
+
// } catch (err) { next(err); }
|
|
105
|
+
// });
|
|
106
|
+
app.get('/config/options/screenlogic/search', async (req, res, next) => {
|
|
107
|
+
try {
|
|
108
|
+
let localUnits = await ScreenLogicComms.searchAsync();
|
|
109
|
+
return res.status(200).send(localUnits);
|
|
110
|
+
} catch (err) { next(err); }
|
|
111
|
+
});
|
|
81
112
|
app.get('/config/options/circuits', async (req, res, next) => {
|
|
82
113
|
try {
|
|
83
114
|
let opts = {
|
|
@@ -269,12 +300,34 @@ export class ConfigRoute {
|
|
|
269
300
|
warnings,
|
|
270
301
|
// waterFlow: sys.board.valueMaps.chemControllerWaterFlow.toArray(), // remove
|
|
271
302
|
controllers: sys.chemControllers.get(),
|
|
272
|
-
maxChemControllers: sys.equipment.maxChemControllers
|
|
303
|
+
maxChemControllers: sys.equipment.maxChemControllers,
|
|
304
|
+
doserTypes: sys.board.valueMaps.chemDoserTypes.toArray()
|
|
273
305
|
};
|
|
274
306
|
return res.status(200).send(opts);
|
|
275
307
|
}
|
|
276
308
|
catch (err) { next(err); }
|
|
277
309
|
});
|
|
310
|
+
app.get('/config/options/chemDosers', async (req, res, next) => {
|
|
311
|
+
try {
|
|
312
|
+
let remServers = await sys.ncp.getREMServers();
|
|
313
|
+
let opts = {
|
|
314
|
+
bodies: sys.board.bodies.getBodyAssociations(),
|
|
315
|
+
tempUnits: sys.board.valueMaps.tempUnits.toArray(),
|
|
316
|
+
status: sys.board.valueMaps.chemDoserStatus.toArray(),
|
|
317
|
+
pumpTypes: sys.board.valueMaps.chemPumpTypes.toArray(),
|
|
318
|
+
volumeUnits: sys.board.valueMaps.volumeUnits.toArray(),
|
|
319
|
+
flowSensorTypes: sys.board.valueMaps.flowSensorTypes.toArray(),
|
|
320
|
+
remServers,
|
|
321
|
+
dosingStatus: sys.board.valueMaps.chemDoserDosingStatus.toArray(),
|
|
322
|
+
dosers: sys.chemDosers.get(),
|
|
323
|
+
doserTypes: sys.board.valueMaps.chemDoserTypes.toArray(),
|
|
324
|
+
maxChemDosers: sys.equipment.maxChemDosers
|
|
325
|
+
};
|
|
326
|
+
return res.status(200).send(opts);
|
|
327
|
+
}
|
|
328
|
+
catch (err) { next(err); }
|
|
329
|
+
});
|
|
330
|
+
|
|
278
331
|
app.get('/config/options/rem', async (req, res, next) => {
|
|
279
332
|
try {
|
|
280
333
|
let opts = {
|
|
@@ -294,6 +347,19 @@ export class ConfigRoute {
|
|
|
294
347
|
return res.status(200).send(opts);
|
|
295
348
|
} catch (err) { next(err); }
|
|
296
349
|
});
|
|
350
|
+
app.get('/config/options/anslq25ControllerType', async (req, res, next) => {
|
|
351
|
+
try {
|
|
352
|
+
let opts = {
|
|
353
|
+
// controllerType: typeof sys.anslq25.controllerType === 'undefined' ? '' : sys.anslq25.controllerType,
|
|
354
|
+
// model: typeof sys.anslq25.model === 'undefined' ? '' : sys.anslq25.model,
|
|
355
|
+
// equipment: sys.equipment.get(),
|
|
356
|
+
...sys.anslq25.get(true),
|
|
357
|
+
controllerTypes: sys.getAvailableControllerTypes(['easytouch', 'intellitouch', 'intellicenter']),
|
|
358
|
+
rs485ports: await conn.listInstalledPorts()
|
|
359
|
+
}
|
|
360
|
+
return res.status(200).send(opts);
|
|
361
|
+
} catch (err) { next(err); }
|
|
362
|
+
});
|
|
297
363
|
app.get('/config/options/chlorinators', async (req, res, next) => {
|
|
298
364
|
try {
|
|
299
365
|
let opts = {
|
|
@@ -324,25 +390,6 @@ export class ConfigRoute {
|
|
|
324
390
|
let opts = config.getSection();
|
|
325
391
|
return res.status(200).send(opts);
|
|
326
392
|
});
|
|
327
|
-
app.get('/app/options/interfaces', (req, res) => {
|
|
328
|
-
// todo: move bytevaluemaps out to a proper location; add additional definitions
|
|
329
|
-
let opts = {
|
|
330
|
-
interfaces: config.getSection('web.interfaces'),
|
|
331
|
-
types: [
|
|
332
|
-
{ name: 'rest', desc: 'Rest' },
|
|
333
|
-
{ name: 'http', desc: 'Http' },
|
|
334
|
-
{ name: 'rem', desc: 'Relay Equipment Manager' },
|
|
335
|
-
{ name: 'mqtt', desc: 'MQTT' },
|
|
336
|
-
{ name: 'influx', desc: 'InfluxDB' }
|
|
337
|
-
],
|
|
338
|
-
protocols: [
|
|
339
|
-
{ val: 0, name: 'http://', desc: 'http://' },
|
|
340
|
-
{ val: 1, name: 'https://', desc: 'https://' },
|
|
341
|
-
{ val: 2, name: 'mqtt://', desc: 'mqtt://' }
|
|
342
|
-
]
|
|
343
|
-
}
|
|
344
|
-
return res.status(200).send(opts);
|
|
345
|
-
});
|
|
346
393
|
app.get('/config/options/tempSensors', (req, res) => {
|
|
347
394
|
let opts = {
|
|
348
395
|
tempUnits: sys.board.valueMaps.tempUnits.toArray(),
|
|
@@ -400,6 +447,13 @@ export class ConfigRoute {
|
|
|
400
447
|
return res.status(200).send(controller.get(true));
|
|
401
448
|
} catch (err) { next(err); }
|
|
402
449
|
});
|
|
450
|
+
app.put('/config/anslq25ControllerType', async (req, res, next) => {
|
|
451
|
+
try {
|
|
452
|
+
// sys.anslq25ControllerType
|
|
453
|
+
await sys.anslq25Board.setAnslq25Async(req.body);
|
|
454
|
+
return res.status(200).send(sys.anslq25.get(true));
|
|
455
|
+
} catch (err) { next(err); }
|
|
456
|
+
});
|
|
403
457
|
app.delete('/config/filter', async (req, res, next) => {
|
|
404
458
|
try {
|
|
405
459
|
let sfilter = await sys.board.filters.deleteFilterAsync(req.body);
|
|
@@ -521,6 +575,18 @@ export class ConfigRoute {
|
|
|
521
575
|
}
|
|
522
576
|
catch (err) { next(err); }
|
|
523
577
|
});
|
|
578
|
+
// RKS: 05-20-22 This is a remnant of the old web ui. It is not called and the setType method needed to go away.
|
|
579
|
+
//app.delete('/config/pump/:pumpId', async (req, res, next) => {
|
|
580
|
+
// try {
|
|
581
|
+
// let pump = sys.pumps.getItemById(parseInt(req.params.pumpId, 10));
|
|
582
|
+
// await sys.board.pumps.deletePumpAsync()
|
|
583
|
+
// if (pump.type === 0) {
|
|
584
|
+
// return res.status(500).send(`Pump ${pump.id} not active`);
|
|
585
|
+
// }
|
|
586
|
+
// pump.setType(0);
|
|
587
|
+
// return res.status(200).send('OK');
|
|
588
|
+
// } catch (err) { next(err); }
|
|
589
|
+
//});
|
|
524
590
|
app.delete('/config/pump', async (req, res, next) => {
|
|
525
591
|
try {
|
|
526
592
|
let pump = await sys.board.pumps.deletePumpAsync(req.body);
|
|
@@ -638,14 +704,6 @@ export class ConfigRoute {
|
|
|
638
704
|
next(err);
|
|
639
705
|
}
|
|
640
706
|
});
|
|
641
|
-
app.delete('/config/pump/:pumpId', (req, res) => {
|
|
642
|
-
let pump = sys.pumps.getItemById(parseInt(req.params.pumpId, 10));
|
|
643
|
-
if (pump.type === 0) {
|
|
644
|
-
return res.status(500).send(`Pump ${pump.id} not active`);
|
|
645
|
-
}
|
|
646
|
-
pump.setType(0);
|
|
647
|
-
return res.status(200).send('OK');
|
|
648
|
-
});
|
|
649
707
|
app.put('/config/dateTime', async (req, res, next) => {
|
|
650
708
|
try {
|
|
651
709
|
let time = await sys.updateControllerDateTimeAsync(req.body);
|
|
@@ -706,6 +764,28 @@ export class ConfigRoute {
|
|
|
706
764
|
}
|
|
707
765
|
catch (err) { next(err); }
|
|
708
766
|
});
|
|
767
|
+
app.put('/config/chemDoser', async (req, res, next) => {
|
|
768
|
+
try {
|
|
769
|
+
let doser = await sys.board.chemDosers.setChemDoserAsync(req.body);
|
|
770
|
+
return res.status(200).send(doser.get());
|
|
771
|
+
}
|
|
772
|
+
catch (err) { next(err); }
|
|
773
|
+
|
|
774
|
+
});
|
|
775
|
+
app.put('/config/chemController/calibrateDose', async (req, res, next) => {
|
|
776
|
+
try {
|
|
777
|
+
let schem = await sys.board.chemControllers.calibrateDoseAsync(req.body);
|
|
778
|
+
return res.status(200).send(schem.getExtended());
|
|
779
|
+
}
|
|
780
|
+
catch (err) { next(err); }
|
|
781
|
+
});
|
|
782
|
+
app.put('/config/chemDoser/calibrateDose', async (req, res, next) => {
|
|
783
|
+
try {
|
|
784
|
+
let schem = await sys.board.chemDosers.calibrateDoseAsync(req.body);
|
|
785
|
+
return res.status(200).send(schem.getExtended());
|
|
786
|
+
}
|
|
787
|
+
catch (err) { next(err); }
|
|
788
|
+
});
|
|
709
789
|
app.put('/config/chemController/feed', async (req, res, next) => {
|
|
710
790
|
try {
|
|
711
791
|
let chem = await sys.board.chemControllers.setChemControllerAsync(req.body);
|
|
@@ -719,8 +799,16 @@ export class ConfigRoute {
|
|
|
719
799
|
return res.status(200).send(chem.get());
|
|
720
800
|
}
|
|
721
801
|
catch (err) { next(err); }
|
|
802
|
+
});
|
|
803
|
+
app.delete('/config/chemDoser', async (req, res, next) => {
|
|
804
|
+
try {
|
|
805
|
+
let doser = await sys.board.chemDosers.deleteChemDoserAsync(req.body);
|
|
806
|
+
return res.status(200).send(doser.get());
|
|
807
|
+
}
|
|
808
|
+
catch (err) { next(err); }
|
|
722
809
|
|
|
723
810
|
});
|
|
811
|
+
|
|
724
812
|
/* app.get('/config/intellibrite', (req, res) => {
|
|
725
813
|
return res.status(200).send(sys.intellibrite.getExtended());
|
|
726
814
|
});
|
|
@@ -770,6 +858,13 @@ export class ConfigRoute {
|
|
|
770
858
|
}
|
|
771
859
|
catch (err) { next(err); }
|
|
772
860
|
});
|
|
861
|
+
// app.put('/app/screenlogic', async (req, res, next) => {
|
|
862
|
+
// try {
|
|
863
|
+
// let screenlogic = await sl.setScreenlogicAsync(req.body);
|
|
864
|
+
// return res.status(200).send(screenlogic);
|
|
865
|
+
// }
|
|
866
|
+
// catch (err) { next(err); }
|
|
867
|
+
// });
|
|
773
868
|
app.delete('/app/rs485Port', async (req, res, next) => {
|
|
774
869
|
try {
|
|
775
870
|
let port = await conn.deleteAuxPort(req.body);
|
|
@@ -909,5 +1004,17 @@ export class ConfigRoute {
|
|
|
909
1004
|
return res.status(200).send(results);
|
|
910
1005
|
} catch (err) { next(err); }
|
|
911
1006
|
});
|
|
1007
|
+
app.put('/app/anslq25', async(req, res, next) => {
|
|
1008
|
+
try {
|
|
1009
|
+
await sys.anslq25Board.setAnslq25Async(req.body);
|
|
1010
|
+
return res.status(200).send(sys.anslq25.get(true));
|
|
1011
|
+
} catch (err) { next(err); }
|
|
1012
|
+
});
|
|
1013
|
+
app.delete('/app/anslq25', async(req, res, next) => {
|
|
1014
|
+
try {
|
|
1015
|
+
await sys.anslq25Board.deleteAnslq25Async(req.body);
|
|
1016
|
+
return res.status(200).send(sys.anslq25.get(true));
|
|
1017
|
+
} catch (err) { next(err); }
|
|
1018
|
+
});
|
|
912
1019
|
}
|
|
913
1020
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* nodejs-poolController. An application to control pool equipment.
|
|
2
|
-
Copyright (C) 2016, 2017, 2018, 2019, 2020
|
|
2
|
+
Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021, 2022.
|
|
3
|
+
Russell Goldin, tagyoureit. russ.goldin@gmail.com
|
|
3
4
|
|
|
4
5
|
This program is free software: you can redistribute it and/or modify
|
|
5
6
|
it under the terms of the GNU Affero General Public License as
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* nodejs-poolController. An application to control pool equipment.
|
|
2
|
-
Copyright (C) 2016, 2017, 2018, 2019, 2020
|
|
2
|
+
Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021, 2022.
|
|
3
|
+
Russell Goldin, tagyoureit. russ.goldin@gmail.com
|
|
3
4
|
|
|
4
5
|
This program is free software: you can redistribute it and/or modify
|
|
5
6
|
it under the terms of the GNU Affero General Public License as
|
|
@@ -22,14 +23,64 @@ import { sys } from "../../../controller/Equipment";
|
|
|
22
23
|
import { utils } from '../../../controller/Constants';
|
|
23
24
|
import { logger } from "../../../logger/Logger";
|
|
24
25
|
import { DataLogger } from "../../../logger/DataLogger";
|
|
26
|
+
import { conn } from "../../../controller/comms/Comms";
|
|
27
|
+
import { config } from "../../../config/Config";
|
|
25
28
|
|
|
26
29
|
import { ServiceParameterError } from "../../../controller/Errors";
|
|
27
30
|
|
|
28
31
|
export class StateRoute {
|
|
29
32
|
public static initRoutes(app: express.Application) {
|
|
33
|
+
app.get('/state/rs485Port/:id', async (req, res, next) => {
|
|
34
|
+
try {
|
|
35
|
+
let portId = parseInt(req.params.id, 10);
|
|
36
|
+
if (isNaN(portId)) throw new ServiceParameterError(`RS485 port id not supplied`, '/state/rs485Port/:id', 'portId', req.params.id);
|
|
37
|
+
let cfg = config.getSection(portId === 0 ? 'controller.comms' : `controller.comms${portId}`);
|
|
38
|
+
if (typeof cfg === 'undefined') throw new ServiceParameterError(`RS485 port id not found`, '/state/rs485Port/:id', 'portId', req.params.id);
|
|
39
|
+
let port = conn.findPortById(portId);
|
|
40
|
+
let sport: any = {
|
|
41
|
+
portId: portId,
|
|
42
|
+
enabled: cfg.enabled || false,
|
|
43
|
+
netConnect: cfg.netConnect,
|
|
44
|
+
reconnects: 0,
|
|
45
|
+
inactivityRetry: cfg.inactivityRetry,
|
|
46
|
+
isOpen: false,
|
|
47
|
+
mock: cfg.mock || false
|
|
48
|
+
}
|
|
49
|
+
if (cfg.netConnect) sport.netConnect = { host: cfg.netHost, port: cfg.netPort }
|
|
50
|
+
else if (typeof cfg.type !== 'undefined' && cfg.type === 'screenlogic'){
|
|
51
|
+
sport.screenlogic = cfg.screenlogic;
|
|
52
|
+
}
|
|
53
|
+
else sport.settings = extend(true, { name: cfg.rs485Port }, cfg.portSettings);
|
|
54
|
+
if (typeof port !== 'undefined' && port.type !== 'screenlogic') {
|
|
55
|
+
let stats = port.stats;
|
|
56
|
+
sport.reconnects = port.reconnects;
|
|
57
|
+
sport.isOpen = port.isOpen;
|
|
58
|
+
sport.received = {
|
|
59
|
+
bytes: stats.bytesReceived,
|
|
60
|
+
success: stats.recSuccess,
|
|
61
|
+
failed: stats.recFailed,
|
|
62
|
+
collisions: stats.recCollisions,
|
|
63
|
+
rewinds: stats.recFRewinds,
|
|
64
|
+
failureRate: stats.recFailureRate
|
|
65
|
+
};
|
|
66
|
+
sport.sent = {
|
|
67
|
+
bytes: stats.bytesSent,
|
|
68
|
+
success: stats.sndSuccess,
|
|
69
|
+
aborted: stats.sndAborted,
|
|
70
|
+
retries: stats.sndRetries,
|
|
71
|
+
failureRate: stats.sndFailureRate
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
res.status(200).send(sport);
|
|
75
|
+
}
|
|
76
|
+
catch (err) { next(err); }
|
|
77
|
+
});
|
|
30
78
|
app.get('/state/chemController/:id', (req, res) => {
|
|
31
79
|
res.status(200).send(state.chemControllers.getItemById(parseInt(req.params.id, 10)).getExtended());
|
|
32
80
|
});
|
|
81
|
+
app.get('/state/chemDoser/:id', (req, res) => {
|
|
82
|
+
res.status(200).send(state.chemDosers.getItemById(parseInt(req.params.id, 10)).getExtended());
|
|
83
|
+
});
|
|
33
84
|
app.put('/state/chemController', async (req, res, next) => {
|
|
34
85
|
try {
|
|
35
86
|
let schem = await sys.board.chemControllers.setChemControllerStateAsync(req.body);
|
|
@@ -37,6 +88,13 @@ export class StateRoute {
|
|
|
37
88
|
}
|
|
38
89
|
catch (err) { next(err); }
|
|
39
90
|
});
|
|
91
|
+
app.put('/state/chemDoser', async (req, res, next) => {
|
|
92
|
+
try {
|
|
93
|
+
let schem = await sys.board.chemDosers.setChemDoserStateAsync(req.body);
|
|
94
|
+
return res.status(200).send(schem.getExtended());
|
|
95
|
+
}
|
|
96
|
+
catch (err) { next(err); }
|
|
97
|
+
});
|
|
40
98
|
app.put('/state/chemController/manualDose', async (req, res, next) => {
|
|
41
99
|
try {
|
|
42
100
|
let schem = await sys.board.chemControllers.manualDoseAsync(req.body);
|
|
@@ -44,6 +102,14 @@ export class StateRoute {
|
|
|
44
102
|
}
|
|
45
103
|
catch (err) { next(err); }
|
|
46
104
|
});
|
|
105
|
+
app.put('/state/chemDoser/manualDose', async (req, res, next) => {
|
|
106
|
+
try {
|
|
107
|
+
let schem = await sys.board.chemDosers.manualDoseAsync(req.body);
|
|
108
|
+
return res.status(200).send(schem.getExtended());
|
|
109
|
+
}
|
|
110
|
+
catch (err) { next(err); }
|
|
111
|
+
});
|
|
112
|
+
|
|
47
113
|
app.put('/state/chemController/manualMix', async (req, res, next) => {
|
|
48
114
|
try {
|
|
49
115
|
logger.debug(`Starting manual mix`);
|
|
@@ -53,6 +119,13 @@ export class StateRoute {
|
|
|
53
119
|
}
|
|
54
120
|
catch (err) { next(err); }
|
|
55
121
|
});
|
|
122
|
+
app.put('/state/chemDoser/manualMix', async (req, res, next) => {
|
|
123
|
+
try {
|
|
124
|
+
let schem = await sys.board.chemDosers.manualMixAsync(req.body);
|
|
125
|
+
return res.status(200).send(schem.getExtended());
|
|
126
|
+
}
|
|
127
|
+
catch (err) { next(err); }
|
|
128
|
+
});
|
|
56
129
|
app.get('/state/chemController/:id/doseHistory', (req, res) => {
|
|
57
130
|
let schem = state.chemControllers.getItemById(parseInt(req.params.id));
|
|
58
131
|
let hist = { ph: [], orp: [] };
|
|
@@ -62,6 +135,11 @@ export class StateRoute {
|
|
|
62
135
|
hist.orp.push(schem.orp.doseHistory[i]);
|
|
63
136
|
return res.status(200).send(hist);
|
|
64
137
|
});
|
|
138
|
+
app.get('/state/chemDoser/:id/doseHistory', (req, res) => {
|
|
139
|
+
let schem = state.chemDosers.getItemById(parseInt(req.params.id));
|
|
140
|
+
return res.status(200).send(schem.doseHistory);
|
|
141
|
+
});
|
|
142
|
+
|
|
65
143
|
app.put('/state/chemController/:id/doseHistory/orp/clear', async (req, res, next) => {
|
|
66
144
|
try {
|
|
67
145
|
let schem = state.chemControllers.getItemById(parseInt(req.params.id));
|
|
@@ -71,6 +149,16 @@ export class StateRoute {
|
|
|
71
149
|
}
|
|
72
150
|
catch (err) { next(err); }
|
|
73
151
|
});
|
|
152
|
+
app.put('/state/chemDoser/:id/doseHistory/clear', async (req, res, next) => {
|
|
153
|
+
try {
|
|
154
|
+
let schem = state.chemDosers.getItemById(parseInt(req.params.id));
|
|
155
|
+
schem.doseHistory = [];
|
|
156
|
+
schem.calcDoseHistory();
|
|
157
|
+
return res.status(200).send(schem.doseHistory);
|
|
158
|
+
}
|
|
159
|
+
catch (err) { next(err); }
|
|
160
|
+
});
|
|
161
|
+
|
|
74
162
|
app.put('/state/chemController/:id/doseHistory/ph/clear', async (req, res, next) => {
|
|
75
163
|
try {
|
|
76
164
|
let schem = state.chemControllers.getItemById(parseInt(req.params.id));
|
|
@@ -95,6 +183,21 @@ export class StateRoute {
|
|
|
95
183
|
}
|
|
96
184
|
catch (err) { next(err); }
|
|
97
185
|
});
|
|
186
|
+
app.get('/state/chemDoser/:id/doseLog', async (req, res, next) => {
|
|
187
|
+
try {
|
|
188
|
+
let schem = state.chemDosers.getItemById(parseInt(req.params.id));
|
|
189
|
+
let filter = req.body || {};
|
|
190
|
+
let dh = await DataLogger.readFromEndAsync(`chemDosage_Peristalic.log`, ChemicalDoseState, (lineNumber: number, entry: ChemicalDoseState, arr: ChemicalDoseState[]): boolean => {
|
|
191
|
+
if (entry.id !== schem.id) return false;
|
|
192
|
+
if (typeof filter.lines !== 'undefined' && filter.lines <= arr.length) return false;
|
|
193
|
+
if (typeof filter.date !== 'undefined' && entry.end < filter.date) return false;
|
|
194
|
+
return true;
|
|
195
|
+
});
|
|
196
|
+
return res.status(200).send(dh);
|
|
197
|
+
}
|
|
198
|
+
catch (err) { next(err); }
|
|
199
|
+
});
|
|
200
|
+
|
|
98
201
|
app.search('/state/chemController/:id/doseLog/ph', async (req, res, next) => {
|
|
99
202
|
try {
|
|
100
203
|
let schem = state.chemControllers.getItemById(parseInt(req.params.id));
|
|
@@ -144,6 +247,13 @@ export class StateRoute {
|
|
|
144
247
|
}
|
|
145
248
|
catch (err) { next(err); }
|
|
146
249
|
});
|
|
250
|
+
app.put('/state/chemDoser/cancelDosing', async (req, res, next) => {
|
|
251
|
+
try {
|
|
252
|
+
let schem = await sys.board.chemDosers.cancelDosingAsync(req.body);
|
|
253
|
+
return res.status(200).send(schem.getExtended());
|
|
254
|
+
}
|
|
255
|
+
catch (err) { next(err); }
|
|
256
|
+
});
|
|
147
257
|
app.put('/state/chemController/cancelMixing', async (req, res, next) => {
|
|
148
258
|
try {
|
|
149
259
|
let schem = await sys.board.chemControllers.cancelMixingAsync(req.body);
|
|
@@ -151,6 +261,13 @@ export class StateRoute {
|
|
|
151
261
|
}
|
|
152
262
|
catch (err) { next(err); }
|
|
153
263
|
});
|
|
264
|
+
app.put('/state/chemDoser/cancelMixing', async (req, res, next) => {
|
|
265
|
+
try {
|
|
266
|
+
let schem = await sys.board.chemDosers.cancelMixingAsync(req.body);
|
|
267
|
+
return res.status(200).send(schem.getExtended());
|
|
268
|
+
}
|
|
269
|
+
catch (err) { next(err); }
|
|
270
|
+
});
|
|
154
271
|
|
|
155
272
|
app.get('/state/chlorinator/:id', (req, res) => {
|
|
156
273
|
res.status(200).send(state.chlorinators.getItemById(parseInt(req.params.id, 10), false).getExtended());
|
|
@@ -233,6 +350,13 @@ export class StateRoute {
|
|
|
233
350
|
}
|
|
234
351
|
catch (err) { next(err); }
|
|
235
352
|
});
|
|
353
|
+
app.put('/state/light/:id/colorSync', async (req, res, next) => {
|
|
354
|
+
try {
|
|
355
|
+
let slight = await sys.board.circuits.runLightCommandAsync({ id: parseInt(req.params.id, 10), command: 'colorsync' });
|
|
356
|
+
return res.status(200).send(slight.get(true));
|
|
357
|
+
}
|
|
358
|
+
catch (err) { next(err); }
|
|
359
|
+
});
|
|
236
360
|
app.put('/state/light/:id/colorHold', async (req, res, next) => {
|
|
237
361
|
try {
|
|
238
362
|
let slight = await sys.board.circuits.runLightCommandAsync({ id: parseInt(req.params.id, 10), command: 'colorhold' });
|
|
@@ -306,6 +430,7 @@ export class StateRoute {
|
|
|
306
430
|
// RKS: 06-24-20 -- Changed this so that users can send in the body id, circuit id, or the name.
|
|
307
431
|
// RKS: 05-14-21 -- Added cooling setpoints for the body.
|
|
308
432
|
try {
|
|
433
|
+
|
|
309
434
|
let body = sys.bodies.findByObject(req.body);
|
|
310
435
|
if (typeof body === 'undefined') return next(new ServiceParameterError(`Cannot set body setPoint. You must supply a valid id, circuit, name, or type for the body`, 'body', 'id', req.body.id));
|
|
311
436
|
if (typeof req.body.coolSetpoint !== 'undefined' && !isNaN(parseInt(req.body.coolSetpoint, 10)))
|
|
@@ -426,8 +551,24 @@ export class StateRoute {
|
|
|
426
551
|
}
|
|
427
552
|
catch (err) { next(err); }
|
|
428
553
|
});
|
|
429
|
-
|
|
430
|
-
|
|
554
|
+
app.put('/state/panelMode', async (req, res, next) => {
|
|
555
|
+
try {
|
|
556
|
+
await sys.board.system.setPanelModeAsync(req.body);
|
|
557
|
+
return res.status(200).send(state.controllerState);
|
|
558
|
+
} catch (err) { next(err); }
|
|
559
|
+
});
|
|
560
|
+
app.put('/state/toggleServiceMode', async (req, res, next) => {
|
|
561
|
+
try {
|
|
562
|
+
let data = extend({}, req.body);
|
|
563
|
+
if (state.mode === 0) {
|
|
564
|
+
if (typeof data.timeout !== 'undefined' && !isNaN(data.timeout)) data.mode = 'timeout';
|
|
565
|
+
else data.mode = 'service';
|
|
566
|
+
await sys.board.system.setPanelModeAsync(req.body);
|
|
567
|
+
}
|
|
568
|
+
else sys.board.system.setPanelModeAsync({ mode: 'auto' });
|
|
569
|
+
return res.status(200).send(state.controllerState);
|
|
570
|
+
} catch (err) { next(err); }
|
|
571
|
+
});
|
|
431
572
|
app.get('/state/emitAll', (req, res) => {
|
|
432
573
|
res.status(200).send(state.emitAllEquipmentChanges());
|
|
433
574
|
});
|