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
|
@@ -62,12 +62,21 @@ export class ConfigRoute {
|
|
|
62
62
|
};
|
|
63
63
|
return res.status(200).send(opts);
|
|
64
64
|
});
|
|
65
|
-
app.get('/config/options/rs485', (req, res) => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
app.get('/config/options/rs485', async (req, res, next) => {
|
|
66
|
+
try {
|
|
67
|
+
let opts = { ports: [], local: [] }
|
|
68
|
+
let cfg = config.getSection('controller');
|
|
69
|
+
for (let section in cfg) {
|
|
70
|
+
if (section.startsWith('comms')) {
|
|
71
|
+
let cport = extend(true, { enabled: false, netConnect: false }, cfg[section]);
|
|
72
|
+
let port = conn.findPortById(cport.portId || 0);
|
|
73
|
+
if (typeof port !== 'undefined') cport.stats = port.stats;
|
|
74
|
+
opts.ports.push(cport);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
opts.local = await conn.getLocalPortsAsync() || [];
|
|
78
|
+
return res.status(200).send(opts);
|
|
79
|
+
} catch (err) { next(err); }
|
|
71
80
|
});
|
|
72
81
|
app.get('/config/options/circuits', async (req, res, next) => {
|
|
73
82
|
try {
|
|
@@ -112,7 +121,7 @@ export class ConfigRoute {
|
|
|
112
121
|
invalidIds: sys.board.equipmentIds.invalidIds.get(),
|
|
113
122
|
equipmentIds: sys.equipment.equipmentIds.features,
|
|
114
123
|
equipmentNames: sys.board.circuits.getCircuitNames(),
|
|
115
|
-
functions: sys.board.
|
|
124
|
+
functions: sys.board.features.getFeatureFunctions(),
|
|
116
125
|
features: sys.features.get()
|
|
117
126
|
};
|
|
118
127
|
return res.status(200).send(opts);
|
|
@@ -156,7 +165,8 @@ export class ConfigRoute {
|
|
|
156
165
|
circuits: sys.board.circuits.getCircuitReferences(true, true, true, true),
|
|
157
166
|
bodies: sys.board.valueMaps.pumpBodies.toArray(),
|
|
158
167
|
pumps: sys.pumps.get(),
|
|
159
|
-
servers: await sys.ncp.getREMServers()
|
|
168
|
+
servers: await sys.ncp.getREMServers(),
|
|
169
|
+
rs485ports: await conn.listInstalledPorts()
|
|
160
170
|
};
|
|
161
171
|
// RKS: Why do we need the circuit names? We have the circuits. Is this so
|
|
162
172
|
// that we can name the pump. I thought that *Touch uses the pump type as the name
|
|
@@ -203,7 +213,8 @@ export class ConfigRoute {
|
|
|
203
213
|
heaterTypes: sys.board.valueMaps.heaterTypes.toArray(),
|
|
204
214
|
heatModes: sys.board.valueMaps.heatModes.toArray(),
|
|
205
215
|
coolDownDelay: sys.general.options.cooldownDelay,
|
|
206
|
-
servers: []
|
|
216
|
+
servers: [],
|
|
217
|
+
rs485ports: await conn.listInstalledPorts()
|
|
207
218
|
};
|
|
208
219
|
// We only need the servers data when the controller is a Nixie controller. We don't need to
|
|
209
220
|
// wait for this information if we are dealing with an OCP.
|
|
@@ -283,16 +294,19 @@ export class ConfigRoute {
|
|
|
283
294
|
return res.status(200).send(opts);
|
|
284
295
|
} catch (err) { next(err); }
|
|
285
296
|
});
|
|
286
|
-
app.get('/config/options/chlorinators', (req, res) => {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
297
|
+
app.get('/config/options/chlorinators', async (req, res, next) => {
|
|
298
|
+
try {
|
|
299
|
+
let opts = {
|
|
300
|
+
types: sys.board.valueMaps.chlorinatorType.toArray(),
|
|
301
|
+
bodies: sys.board.bodies.getBodyAssociations(),
|
|
302
|
+
chlorinators: sys.chlorinators.get(),
|
|
303
|
+
maxChlorinators: sys.equipment.maxChlorinators,
|
|
304
|
+
models: sys.board.valueMaps.chlorinatorModel.toArray(),
|
|
305
|
+
equipmentMasters: sys.board.valueMaps.equipmentMaster.toArray(),
|
|
306
|
+
rs485ports: await conn.listInstalledPorts()
|
|
307
|
+
};
|
|
308
|
+
return res.status(200).send(opts);
|
|
309
|
+
} catch (err) { next(err); }
|
|
296
310
|
});
|
|
297
311
|
app.get('/config/options/dateTime', (req, res) => {
|
|
298
312
|
let opts = {
|
|
@@ -592,8 +606,8 @@ export class ConfigRoute {
|
|
|
592
606
|
return res.status(200).send(circuitFunctions);
|
|
593
607
|
});
|
|
594
608
|
app.get('/config/features/functions', (req, res) => {
|
|
595
|
-
let
|
|
596
|
-
return res.status(200).send(
|
|
609
|
+
let featureFunctions = sys.board.features.getFeatureFunctions();
|
|
610
|
+
return res.status(200).send(featureFunctions);
|
|
597
611
|
});
|
|
598
612
|
app.get('/config/circuit/:id', (req, res) => {
|
|
599
613
|
// todo: need getInterfaceById.get() in case features are requested here
|
|
@@ -605,15 +619,15 @@ export class ConfigRoute {
|
|
|
605
619
|
let themes = typeof circuit !== 'undefined' && typeof circuit.getLightThemes === 'function' ? circuit.getLightThemes(circuit.type) : [];
|
|
606
620
|
return res.status(200).send(themes);
|
|
607
621
|
});
|
|
622
|
+
app.get('/config/circuit/:id/lightCommands', (req, res) => {
|
|
623
|
+
let circuit = sys.circuits.getInterfaceById(parseInt(req.params.id, 10));
|
|
624
|
+
let commands = typeof circuit !== 'undefined' && typeof circuit.getLightThemes === 'function' ? circuit.getLightCommands(circuit.type) : [];
|
|
625
|
+
return res.status(200).send(commands);
|
|
626
|
+
});
|
|
627
|
+
|
|
608
628
|
app.get('/config/chlorinator/:id', (req, res) => {
|
|
609
629
|
return res.status(200).send(sys.chlorinators.getItemById(parseInt(req.params.id, 10)).get());
|
|
610
630
|
});
|
|
611
|
-
//app.put('/config/chlorinator', (req, res) => {
|
|
612
|
-
// let chlor = sys.chlorinators.getItemById(parseInt(req.body.id, 10), true);
|
|
613
|
-
// sys.board.chlorinator.setChlorProps(chlor, req.body);
|
|
614
|
-
// // if (chlor.isVirtual) { sys.board.virtualChlorinatorController.start(); }
|
|
615
|
-
// return res.status(200).send(sys.chlorinators.getItemById(parseInt(req.params.id, 10)).get());
|
|
616
|
-
//});
|
|
617
631
|
app.get('/config/chlorinators/search', async (req, res, next) => {
|
|
618
632
|
// Change the options for the pool.
|
|
619
633
|
try {
|
|
@@ -624,103 +638,6 @@ export class ConfigRoute {
|
|
|
624
638
|
next(err);
|
|
625
639
|
}
|
|
626
640
|
});
|
|
627
|
-
/* app.get('/config/pump/:id/circuits', (req, res) => {
|
|
628
|
-
return res.status(200).send(sys.pumps.getItemById(parseInt(req.params.id, 10)).get().circuits);
|
|
629
|
-
});
|
|
630
|
-
app.get('/config/pump/availableCircuits', (req, res) => {
|
|
631
|
-
return res.status(200).send(sys.board.pumps.availableCircuits());
|
|
632
|
-
});
|
|
633
|
-
app.get('/config/pump/:id/circuit/:circuitid', (req, res) => {
|
|
634
|
-
return res.status(200).send(sys.pumps.getItemById(parseInt(req.params.id, 10)).get().circuits[parseInt(req.params.circuitid, 10)]);
|
|
635
|
-
});
|
|
636
|
-
app.get('/config/pump/:id/nextAvailablePumpCircuit', (req, res) => {
|
|
637
|
-
// if no pumpCircuitId is available, 0 will be returned
|
|
638
|
-
let _id = sys.pumps.getItemById(parseInt(req.params.id, 10)).nextAvailablePumpCircuit();
|
|
639
|
-
return res.status(200).send(_id.toString());
|
|
640
|
-
}); */
|
|
641
|
-
/*
|
|
642
|
-
app.put('/config/pump/:id/pumpCircuit', (req, res) => {
|
|
643
|
-
// if no pumpCircuitId is specified, set it as 0 and take the next available one
|
|
644
|
-
req.url = `${ req.url }/0`;
|
|
645
|
-
req.next();
|
|
646
|
-
});
|
|
647
|
-
app.put('/config/pump/:id/pumpCircuit/:pumpCircuitId', (req, res) => {
|
|
648
|
-
// RSG - do we want a /config/pump/:id/pumpCircuit/ that will just assume the next circuit?
|
|
649
|
-
let pump = sys.pumps.getItemById(parseInt(req.params.id, 10));
|
|
650
|
-
let _pumpCircuitId = parseInt(req.params.pumpCircuitId, 10);
|
|
651
|
-
let _circuit = parseInt(req.body.circuit, 10);
|
|
652
|
-
let _rate = parseInt(req.body.rate, 10);
|
|
653
|
-
let _units = parseInt(req.body.units, 10) || pump.defaultUnits;
|
|
654
|
-
let pumpCircuit = {
|
|
655
|
-
pump: parseInt(req.params.id, 10),
|
|
656
|
-
pumpCircuitId: isNaN(_pumpCircuitId) ? undefined : _pumpCircuitId,
|
|
657
|
-
circuit: isNaN(_circuit) ? undefined : _circuit,
|
|
658
|
-
rate: isNaN(_rate) ? undefined : _rate,
|
|
659
|
-
units: isNaN(_units) ? undefined : _units
|
|
660
|
-
};
|
|
661
|
-
let { result, reason } = pump.setPumpCircuit(pumpCircuit);
|
|
662
|
-
if (result === 'OK')
|
|
663
|
-
return res.status(200).send({ result: result, reason: reason });
|
|
664
|
-
else
|
|
665
|
-
return res.status(500).send({ result: result, reason: reason });
|
|
666
|
-
}); */
|
|
667
|
-
/* app.delete('/config/pump/:id/pumpCircuit/:pumpCircuitId', (req, res) => {
|
|
668
|
-
let pump = sys.pumps.getItemById(parseInt(req.params.id, 10));
|
|
669
|
-
// pump.circuits.removeItemById(parseInt(req.params.pumpCircuitId, 10));
|
|
670
|
-
pump.deletePumpCircuit(parseInt(req.params.pumpCircuitId, 10));
|
|
671
|
-
return res.status(200).send('OK');
|
|
672
|
-
}); */
|
|
673
|
-
/* app.get('/config/pump/types', (req, res) => {
|
|
674
|
-
let pumpTypes = sys.board.pumps.getPumpTypes();
|
|
675
|
-
return res.status(200).send(pumpTypes);
|
|
676
|
-
});
|
|
677
|
-
app.get('/config/pump/units', (req, res) => {
|
|
678
|
-
// get all units for all system board
|
|
679
|
-
let pumpTypes = sys.board.pumps.getCircuitUnits();
|
|
680
|
-
return res.status(200).send(pumpTypes);
|
|
681
|
-
});
|
|
682
|
-
app.get('/config/pump/:id/units', (req, res) => {
|
|
683
|
-
// get units for all specific pump types
|
|
684
|
-
// need to coorerce into array if only a single unit is returned; by default getExtended will return an array
|
|
685
|
-
// if there is 1+ object so this creates parity
|
|
686
|
-
let pump = sys.pumps.getItemById(parseInt(req.params.id, 10));
|
|
687
|
-
let pumpTypes = sys.board.pumps.getCircuitUnits(pump);
|
|
688
|
-
if (!Array.isArray(pumpTypes)) pumpTypes = [pumpTypes];
|
|
689
|
-
return res.status(200).send(pumpTypes);
|
|
690
|
-
});
|
|
691
|
-
app.put('/config/pump/:pumpId/type', (req, res) => {
|
|
692
|
-
const _type = parseInt(req.body.pumpType, 10);
|
|
693
|
-
const _pumpId = parseInt(req.params.pumpId, 10);
|
|
694
|
-
// RG - this was left as it's own end point because trying to combine changing the pump type (which requires resetting the pump values) while simultaneously setting new pump values was tricky.
|
|
695
|
-
let pump = sys.pumps.getItemById(_pumpId);
|
|
696
|
-
if (sys.controllerType === ControllerType.Virtual) {
|
|
697
|
-
pump.isVirtual = true;
|
|
698
|
-
}
|
|
699
|
-
if (_type !== pump.type) {
|
|
700
|
-
pump.setType(_type);
|
|
701
|
-
}
|
|
702
|
-
return res.status(200).send('OK');
|
|
703
|
-
}); */
|
|
704
|
-
/* app.get('/config/pump/:pumpId', (req, res) => {
|
|
705
|
-
let pump = sys.pumps.getItemById(parseInt(req.params.pumpId, 10)).get(true);
|
|
706
|
-
return res.status(200).send(pump);
|
|
707
|
-
});
|
|
708
|
-
app.put('/config/pump/:pumpId', (req, res) => {
|
|
709
|
-
// this will change the pump type
|
|
710
|
-
let _type = parseInt(req.body.pumpType, 10);
|
|
711
|
-
let pump = sys.pumps.getItemById(parseInt(req.params.pumpId, 10));
|
|
712
|
-
if (sys.controllerType === ControllerType.Virtual) {
|
|
713
|
-
// if virtualController, add the virtual pump
|
|
714
|
-
pump.isVirtual = true;
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
if (_type !== pump.type && typeof _type !== 'undefined') {
|
|
718
|
-
pump.setType(_type);
|
|
719
|
-
}
|
|
720
|
-
// get a new instance of the pump here because setType will remove/add a new instance
|
|
721
|
-
if (Object.keys(req.body).length) sys.pumps.getItemById(parseInt(req.params.pumpId, 10)).setPump(req.body);
|
|
722
|
-
return res.status(200).send('OK');
|
|
723
|
-
}); */
|
|
724
641
|
app.delete('/config/pump/:pumpId', (req, res) => {
|
|
725
642
|
let pump = sys.pumps.getItemById(parseInt(req.params.pumpId, 10));
|
|
726
643
|
if (pump.type === 0) {
|
|
@@ -738,13 +655,12 @@ export class ConfigRoute {
|
|
|
738
655
|
});
|
|
739
656
|
app.get('/config/lightGroups/themes', (req, res) => {
|
|
740
657
|
// RSG: is this and /config/circuit/:id/lightThemes both needed?
|
|
741
|
-
|
|
742
|
-
// if (sys.controllerType === ControllerType.IntelliCenter) {
|
|
743
658
|
let grp = sys.lightGroups.getItemById(parseInt(req.body.id, 10));
|
|
744
659
|
return res.status(200).send(grp.getLightThemes());
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
660
|
+
});
|
|
661
|
+
app.get('/config/lightGroups/commands', (req, res) => {
|
|
662
|
+
let grp = sys.lightGroups.getItemById(parseInt(req.body.id, 10));
|
|
663
|
+
return res.status(200).send(grp.getLightCommands());
|
|
748
664
|
});
|
|
749
665
|
app.get('/config/lightGroup/:id', (req, res) => {
|
|
750
666
|
// if (sys.controllerType === ControllerType.IntelliCenter) {
|
|
@@ -854,6 +770,13 @@ export class ConfigRoute {
|
|
|
854
770
|
}
|
|
855
771
|
catch (err) { next(err); }
|
|
856
772
|
});
|
|
773
|
+
app.delete('/app/rs485Port', async (req, res, next) => {
|
|
774
|
+
try {
|
|
775
|
+
let port = await conn.deleteAuxPort(req.body);
|
|
776
|
+
return res.status(200).send(port);
|
|
777
|
+
}
|
|
778
|
+
catch (err) { next(err); }
|
|
779
|
+
});
|
|
857
780
|
app.get('/app/config/startPacketCapture', (req, res) => {
|
|
858
781
|
startPacketCapture(true);
|
|
859
782
|
return res.status(200).send('OK');
|
|
@@ -874,7 +797,7 @@ export class ConfigRoute {
|
|
|
874
797
|
});
|
|
875
798
|
app.get('/app/config/options/backup', async (req, res, next) => {
|
|
876
799
|
try {
|
|
877
|
-
let opts = config.getSection('controller.backups', { automatic: false, interval: { days: 30, hours: 0, keepCount: 5, servers: [] }
|
|
800
|
+
let opts = config.getSection('controller.backups', { automatic: false, interval: { days: 30, hours: 0 }, keepCount: 5, servers: [] });
|
|
878
801
|
let servers = await sys.ncp.getREMServers();
|
|
879
802
|
if (typeof servers !== 'undefined') {
|
|
880
803
|
// Just in case somebody deletes the backup section and doesn't put it back properly.
|
|
@@ -893,7 +816,7 @@ export class ConfigRoute {
|
|
|
893
816
|
});
|
|
894
817
|
app.get('/app/config/options/restore', async (req, res, next) => {
|
|
895
818
|
try {
|
|
896
|
-
let opts = config.getSection('controller.backups', { automatic: false, interval: { days: 30, hours: 0, keepCount: 5, servers: [], backupFiles: [] }
|
|
819
|
+
let opts = config.getSection('controller.backups', { automatic: false, interval: { days: 30, hours: 0 }, keepCount: 5, servers: [], backupFiles: [] });
|
|
897
820
|
let servers = await sys.ncp.getREMServers();
|
|
898
821
|
if (typeof servers !== 'undefined') {
|
|
899
822
|
for (let i = 0; i < servers.length; i++) {
|
|
@@ -914,7 +837,7 @@ export class ConfigRoute {
|
|
|
914
837
|
app.put('/app/config/options/backup', async (req, res, next) => {
|
|
915
838
|
try {
|
|
916
839
|
config.setSection('controller.backups', req.body);
|
|
917
|
-
let opts = config.getSection('controller.backups', { automatic: false, interval: { days: 30, hours: 0, keepCount: 5, servers: [] }
|
|
840
|
+
let opts = config.getSection('controller.backups', { automatic: false, interval: { days: 30, hours: 0 }, keepCount: 5, servers: [] });
|
|
918
841
|
webApp.autoBackup = utils.makeBool(opts.automatic);
|
|
919
842
|
await webApp.checkAutoBackup();
|
|
920
843
|
return res.status(200).send(opts);
|
|
@@ -161,6 +161,9 @@ export class StateRoute {
|
|
|
161
161
|
app.get('/state/feature/:id', (req, res) => {
|
|
162
162
|
res.status(200).send(state.features.getItemById(parseInt(req.params.id, 10)).get());
|
|
163
163
|
});
|
|
164
|
+
app.get('/state/schedule/:id', (req, res) => {
|
|
165
|
+
res.status(200).send(state.schedules.getItemById(parseInt(req.params.id, 10)).get());
|
|
166
|
+
});
|
|
164
167
|
app.get('/state/circuitGroup/:id', (req, res) => {
|
|
165
168
|
res.status(200).send(state.circuitGroups.getItemById(parseInt(req.params.id, 10)).get());
|
|
166
169
|
});
|
|
@@ -214,7 +217,44 @@ export class StateRoute {
|
|
|
214
217
|
return res.status(200).send(theme.get(true));
|
|
215
218
|
}
|
|
216
219
|
catch (err) { next(err); }
|
|
217
|
-
});
|
|
220
|
+
});
|
|
221
|
+
app.put('/state/light/setTheme', async (req, res, next) => {
|
|
222
|
+
try {
|
|
223
|
+
let theme = await state.circuits.setLightThemeAsync(parseInt(req.body.id, 10), sys.board.valueMaps.lightThemes.encode(req.body.theme));
|
|
224
|
+
return res.status(200).send(theme.get(true));
|
|
225
|
+
}
|
|
226
|
+
catch (err) { next(err); }
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
app.put('/state/light/runCommand', async (req, res, next) => {
|
|
230
|
+
try {
|
|
231
|
+
let slight = await sys.board.circuits.runLightCommandAsync(req.body);
|
|
232
|
+
return res.status(200).send(slight.get(true));
|
|
233
|
+
}
|
|
234
|
+
catch (err) { next(err); }
|
|
235
|
+
});
|
|
236
|
+
app.put('/state/light/:id/colorHold', async (req, res, next) => {
|
|
237
|
+
try {
|
|
238
|
+
let slight = await sys.board.circuits.runLightCommandAsync({ id: parseInt(req.params.id, 10), command: 'colorhold' });
|
|
239
|
+
return res.status(200).send(slight.get(true));
|
|
240
|
+
}
|
|
241
|
+
catch (err) { next(err); }
|
|
242
|
+
});
|
|
243
|
+
app.put('/state/light/:id/colorRecall', async (req, res, next) => {
|
|
244
|
+
try {
|
|
245
|
+
let slight = await sys.board.circuits.runLightCommandAsync({ id: parseInt(req.params.id, 10), command: 'colorecall' });
|
|
246
|
+
return res.status(200).send(slight.get(true));
|
|
247
|
+
}
|
|
248
|
+
catch (err) { next(err); }
|
|
249
|
+
});
|
|
250
|
+
app.put('/state/light/:id/lightThumper', async (req, res, next) => {
|
|
251
|
+
try {
|
|
252
|
+
let slight = await sys.board.circuits.runLightCommandAsync({ id: parseInt(req.params.id, 10), command: 'lightthumper' });
|
|
253
|
+
return res.status(200).send(slight.get(true));
|
|
254
|
+
}
|
|
255
|
+
catch (err) { next(err); }
|
|
256
|
+
});
|
|
257
|
+
|
|
218
258
|
/* app.put('/state/intellibrite/setTheme', (req, res) => {
|
|
219
259
|
let id = sys.board.equipmentIds.circuitGroups.start;
|
|
220
260
|
if (typeof req.body.theme !== 'undefined') id = parseInt(req.body.id, 10);
|
|
@@ -330,27 +370,64 @@ export class StateRoute {
|
|
|
330
370
|
}
|
|
331
371
|
catch (err) { next(err); }
|
|
332
372
|
});
|
|
373
|
+
app.put('/state/manualOperationPriority', async (req, res, next) => {
|
|
374
|
+
try {
|
|
375
|
+
let cstate = await sys.board.system.setManualOperationPriority(parseInt(req.body.id, 10));
|
|
376
|
+
return res.status(200).send(cstate.get(true));
|
|
377
|
+
}
|
|
378
|
+
catch (err) { next(err); }
|
|
379
|
+
});
|
|
380
|
+
app.put('/state/lightGroup/runCommand', async (req, res, next) => {
|
|
381
|
+
try {
|
|
382
|
+
let sgroup = await sys.board.circuits.runLightGroupCommandAsync(req.body);
|
|
383
|
+
return res.status(200).send(sgroup.get(true));
|
|
384
|
+
}
|
|
385
|
+
catch (err) { next(err); }
|
|
386
|
+
});
|
|
333
387
|
app.put('/state/lightGroup/:id/colorSync', async (req, res, next) => {
|
|
334
388
|
try {
|
|
335
|
-
let sgroup = await sys.board.circuits.sequenceLightGroupAsync(parseInt(req.params.id, 10), '
|
|
389
|
+
let sgroup = await sys.board.circuits.sequenceLightGroupAsync(parseInt(req.params.id, 10), 'colorsync');
|
|
336
390
|
return res.status(200).send(sgroup.get(true));
|
|
337
391
|
}
|
|
338
392
|
catch (err) { next(err); }
|
|
339
393
|
});
|
|
340
394
|
app.put('/state/lightGroup/:id/colorSet', async (req, res, next) => {
|
|
341
395
|
try {
|
|
342
|
-
let sgroup = await sys.board.circuits.sequenceLightGroupAsync(parseInt(req.params.id, 10), '
|
|
396
|
+
let sgroup = await sys.board.circuits.sequenceLightGroupAsync(parseInt(req.params.id, 10), 'colorset');
|
|
343
397
|
return res.status(200).send(sgroup.get(true));
|
|
344
398
|
}
|
|
345
399
|
catch (err) { next(err); }
|
|
346
400
|
});
|
|
347
401
|
app.put('/state/lightGroup/:id/colorSwim', async (req, res, next) => {
|
|
348
402
|
try {
|
|
349
|
-
let sgroup = await sys.board.circuits.sequenceLightGroupAsync(parseInt(req.params.id, 10), '
|
|
403
|
+
let sgroup = await sys.board.circuits.sequenceLightGroupAsync(parseInt(req.params.id, 10), 'colorswim');
|
|
404
|
+
return res.status(200).send(sgroup.get(true));
|
|
405
|
+
}
|
|
406
|
+
catch (err) { next(err); }
|
|
407
|
+
});
|
|
408
|
+
app.put('/state/lightGroup/:id/colorHold', async (req, res, next) => {
|
|
409
|
+
try {
|
|
410
|
+
let sgroup = await sys.board.circuits.runLightGroupCommandAsync({ id: parseInt(req.params.id, 10), command: 'colorhold' });
|
|
350
411
|
return res.status(200).send(sgroup.get(true));
|
|
351
412
|
}
|
|
352
413
|
catch (err) { next(err); }
|
|
353
414
|
});
|
|
415
|
+
app.put('/state/lightGroup/:id/colorRecall', async (req, res, next) => {
|
|
416
|
+
try {
|
|
417
|
+
let sgroup = await sys.board.circuits.runLightGroupCommandAsync({ id: parseInt(req.params.id, 10), command: 'colorrecall' });
|
|
418
|
+
return res.status(200).send(sgroup.get(true));
|
|
419
|
+
}
|
|
420
|
+
catch (err) { next(err); }
|
|
421
|
+
});
|
|
422
|
+
app.put('/state/lightGroup/:id/lightThumper', async (req, res, next) => {
|
|
423
|
+
try {
|
|
424
|
+
let sgroup = await sys.board.circuits.runLightGroupCommandAsync({ id: parseInt(req.params.id, 10), command: 'lightthumper' });
|
|
425
|
+
return res.status(200).send(sgroup.get(true));
|
|
426
|
+
}
|
|
427
|
+
catch (err) { next(err); }
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
|
|
354
431
|
app.get('/state/emitAll', (req, res) => {
|
|
355
432
|
res.status(200).send(state.emitAllEquipmentChanges());
|
|
356
433
|
});
|
|
@@ -174,7 +174,7 @@ export class StateSocket {
|
|
|
174
174
|
sock.on('/circuit', async (data: any) => {
|
|
175
175
|
try {
|
|
176
176
|
data = JSON.parse(data);
|
|
177
|
-
let id =
|
|
177
|
+
let id = parseInt(data.id, 10);
|
|
178
178
|
if (!isNaN(id) && (typeof data.isOn !== 'undefined' || typeof data.state !== 'undefined')) {
|
|
179
179
|
await sys.board.circuits.setCircuitStateAsync(id, utils.makeBool(data.isOn || typeof data.state));
|
|
180
180
|
}
|
|
@@ -184,7 +184,7 @@ export class StateSocket {
|
|
|
184
184
|
sock.on('/feature', async (data: any) => {
|
|
185
185
|
try {
|
|
186
186
|
data = JSON.parse(data);
|
|
187
|
-
let id =
|
|
187
|
+
let id = parseInt(data.id, 10);
|
|
188
188
|
if (!isNaN(id) && (typeof data.isOn !== 'undefined' || typeof data.state !== 'undefined')) {
|
|
189
189
|
await sys.board.features.setFeatureStateAsync(id, utils.makeBool(data.isOn || typeof data.state));
|
|
190
190
|
}
|
|
@@ -194,7 +194,7 @@ export class StateSocket {
|
|
|
194
194
|
sock.on('/circuitGroup', async (data: any) => {
|
|
195
195
|
try {
|
|
196
196
|
data = JSON.parse(data);
|
|
197
|
-
let id =
|
|
197
|
+
let id = parseInt(data.id, 10);
|
|
198
198
|
if (!isNaN(id) && (typeof data.isOn !== 'undefined' || typeof data.state !== 'undefined')) {
|
|
199
199
|
await sys.board.circuits.setCircuitGroupStateAsync(id, utils.makeBool(data.isOn || typeof data.state));
|
|
200
200
|
}
|
|
@@ -204,7 +204,7 @@ export class StateSocket {
|
|
|
204
204
|
sock.on('/lightGroup', async (data: any) => {
|
|
205
205
|
try {
|
|
206
206
|
data = JSON.parse(data);
|
|
207
|
-
let id =
|
|
207
|
+
let id = parseInt(data.id, 10);
|
|
208
208
|
if (!isNaN(id) && (typeof data.isOn !== 'undefined' || typeof data.state !== 'undefined')) {
|
|
209
209
|
await sys.board.circuits.setLightGroupStateAsync(id, utils.makeBool(data.isOn || typeof data.state));
|
|
210
210
|
}
|
|
@@ -18,16 +18,18 @@ import * as express from 'express';
|
|
|
18
18
|
import { SsdpServer} from '../../Server';
|
|
19
19
|
import { state } from "../../../controller/State";
|
|
20
20
|
import { sys } from "../../../controller/Equipment";
|
|
21
|
-
|
|
21
|
+
import { webApp } from "../../Server";
|
|
22
22
|
const extend = require("extend");
|
|
23
23
|
export class UtilitiesRoute {
|
|
24
24
|
|
|
25
25
|
public static initRoutes(app: express.Application) {
|
|
26
|
-
app.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
app.use('/upnp.xml', async (req, res, next) => {
|
|
27
|
+
try {
|
|
28
|
+
// Put together the upnp device description.
|
|
29
|
+
let ssdp = webApp.findServer('ssdp') as SsdpServer;
|
|
30
|
+
if (typeof ssdp === 'undefined') throw new Error(`SSDP Server not initialized. No upnp information available.`);
|
|
31
|
+
res.status(200).set('Content-Type', 'text/xml').send(ssdp.deviceXML());
|
|
32
|
+
} catch (err) { next(err); }
|
|
31
33
|
});
|
|
32
34
|
app.get('/extended/:section', (req, res) => {
|
|
33
35
|
let cfg = sys.getSection(req.params.section);
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Bug report
|
|
3
|
-
about: Create a report to help us improve
|
|
4
|
-
title: ''
|
|
5
|
-
labels: ''
|
|
6
|
-
assignees: ''
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
**Describe the bug**
|
|
11
|
-
A clear and concise description of what the bug is.
|
|
12
|
-
|
|
13
|
-
**To Reproduce**
|
|
14
|
-
Steps to reproduce the behavior:
|
|
15
|
-
1. Go to '...'
|
|
16
|
-
2. Click on '....'
|
|
17
|
-
3. Scroll down to '....'
|
|
18
|
-
4. See error
|
|
19
|
-
|
|
20
|
-
**Expected behavior**
|
|
21
|
-
A clear and concise description of what you expected to happen.
|
|
22
|
-
|
|
23
|
-
**Screenshots**
|
|
24
|
-
If applicable, add screenshots to help explain your problem.
|
|
25
|
-
|
|
26
|
-
**Packet Capture**
|
|
27
|
-
Follow the instructions to complete a [packet capture](https://github.com/tagyoureit/nodejs-poolController/wiki/How-to-capture-all-packets-for-issue-resolution) and attach the resulting zip/log files.
|
|
28
|
-
|
|
29
|
-
**Pool Equipment**
|
|
30
|
-
- Controller: [e.g. IntelliCenter, EasyTouch, IntelliTouch]
|
|
31
|
-
- Controller Model: [e.g. IntelliCenter i5PS, EasyTouch2 8P]
|
|
32
|
-
- Controller Firmware Version: [e.g. 1.047]
|
|
33
|
-
- Pump(s) manufacturer and model: [e.g. IntelliFlow 2 VST 011056]
|
|
34
|
-
- Chlorinator: [e.g. iChlor, IntelliChlor-40]
|
|
35
|
-
- Heater(s): [e.g. gas, solar, heatpump, ultratemp]
|
|
36
|
-
- Chemical controller: [e.g. IntelliChem, Relay Equipment Manager (REM)]
|
|
37
|
-
- Valves: [e.g. Intellivalve]
|
|
38
|
-
- Any other relevant equipment:
|
|
39
|
-
|
|
40
|
-
**Desktop (please complete the following information):**
|
|
41
|
-
- OS: [e.g. iOS]
|
|
42
|
-
- Browser [e.g. chrome, safari]
|
|
43
|
-
- Version [e.g. 22]
|
|
44
|
-
|
|
45
|
-
**Smartphone (please complete the following information):**
|
|
46
|
-
- Device: [e.g. iPhone6]
|
|
47
|
-
- OS: [e.g. iOS8.1]
|
|
48
|
-
- Browser [e.g. stock browser, safari]
|
|
49
|
-
- Version [e.g. 22]
|
|
50
|
-
|
|
51
|
-
**Additional context**
|
|
52
|
-
Add any other context about the problem here.
|