nodejs-poolcontroller 7.3.1 → 7.6.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 +44 -44
- package/.github/ISSUE_TEMPLATE/bug_report.md +52 -52
- package/CONTRIBUTING.md +74 -74
- package/Changelog +215 -195
- package/Dockerfile +17 -17
- package/Gruntfile.js +40 -40
- package/LICENSE +661 -661
- package/README.md +191 -186
- package/app.ts +2 -0
- package/config/Config.ts +27 -2
- package/config/VersionCheck.ts +33 -14
- package/config copy.json +299 -299
- package/controller/Constants.ts +88 -0
- package/controller/Equipment.ts +2459 -2225
- package/controller/Errors.ts +180 -157
- package/controller/Lockouts.ts +437 -0
- package/controller/State.ts +364 -79
- package/controller/boards/BoardFactory.ts +45 -45
- package/controller/boards/EasyTouchBoard.ts +2653 -2489
- package/controller/boards/IntelliCenterBoard.ts +4230 -3973
- package/controller/boards/IntelliComBoard.ts +63 -63
- package/controller/boards/IntelliTouchBoard.ts +241 -167
- package/controller/boards/NixieBoard.ts +1675 -1105
- package/controller/boards/SystemBoard.ts +4697 -3201
- package/controller/comms/Comms.ts +222 -10
- package/controller/comms/messages/Messages.ts +13 -9
- package/controller/comms/messages/config/ChlorinatorMessage.ts +13 -4
- package/controller/comms/messages/config/CircuitGroupMessage.ts +6 -0
- package/controller/comms/messages/config/CircuitMessage.ts +0 -0
- package/controller/comms/messages/config/ConfigMessage.ts +0 -0
- package/controller/comms/messages/config/CoverMessage.ts +1 -0
- package/controller/comms/messages/config/CustomNameMessage.ts +30 -30
- package/controller/comms/messages/config/EquipmentMessage.ts +4 -0
- package/controller/comms/messages/config/ExternalMessage.ts +53 -33
- package/controller/comms/messages/config/FeatureMessage.ts +8 -1
- package/controller/comms/messages/config/GeneralMessage.ts +8 -0
- package/controller/comms/messages/config/HeaterMessage.ts +14 -28
- package/controller/comms/messages/config/IntellichemMessage.ts +4 -1
- package/controller/comms/messages/config/OptionsMessage.ts +38 -2
- package/controller/comms/messages/config/PumpMessage.ts +4 -20
- package/controller/comms/messages/config/RemoteMessage.ts +4 -0
- package/controller/comms/messages/config/ScheduleMessage.ts +347 -331
- package/controller/comms/messages/config/SecurityMessage.ts +1 -0
- package/controller/comms/messages/config/ValveMessage.ts +13 -3
- package/controller/comms/messages/status/ChlorinatorStateMessage.ts +2 -3
- package/controller/comms/messages/status/EquipmentStateMessage.ts +79 -25
- package/controller/comms/messages/status/HeaterStateMessage.ts +86 -53
- package/controller/comms/messages/status/IntelliChemStateMessage.ts +445 -386
- package/controller/comms/messages/status/IntelliValveStateMessage.ts +35 -35
- package/controller/comms/messages/status/PumpStateMessage.ts +0 -0
- package/controller/comms/messages/status/VersionMessage.ts +0 -0
- package/controller/nixie/Nixie.ts +162 -160
- package/controller/nixie/NixieEquipment.ts +103 -103
- package/controller/nixie/bodies/Body.ts +120 -117
- package/controller/nixie/bodies/Filter.ts +135 -135
- package/controller/nixie/chemistry/ChemController.ts +2498 -2395
- package/controller/nixie/chemistry/Chlorinator.ts +314 -313
- package/controller/nixie/circuits/Circuit.ts +248 -210
- package/controller/nixie/heaters/Heater.ts +649 -441
- package/controller/nixie/pumps/Pump.ts +661 -599
- package/controller/nixie/schedules/Schedule.ts +257 -256
- package/controller/nixie/valves/Valve.ts +170 -170
- package/defaultConfig.json +286 -271
- package/issue_template.md +51 -51
- package/logger/DataLogger.ts +448 -433
- package/logger/Logger.ts +0 -0
- package/package.json +56 -54
- package/tsconfig.json +25 -25
- package/web/Server.ts +522 -31
- package/web/bindings/influxDB.json +1022 -894
- package/web/bindings/mqtt.json +654 -543
- package/web/bindings/mqttAlt.json +684 -574
- package/web/bindings/rulesManager.json +54 -54
- package/web/bindings/smartThings-Hubitat.json +31 -31
- package/web/bindings/valveRelays.json +20 -20
- package/web/bindings/vera.json +25 -25
- package/web/interfaces/baseInterface.ts +136 -136
- package/web/interfaces/httpInterface.ts +124 -122
- package/web/interfaces/influxInterface.ts +245 -240
- package/web/interfaces/mqttInterface.ts +475 -464
- package/web/services/config/Config.ts +181 -152
- package/web/services/config/ConfigSocket.ts +0 -0
- package/web/services/state/State.ts +118 -7
- package/web/services/state/StateSocket.ts +18 -1
- package/web/services/utilities/Utilities.ts +42 -42
|
@@ -14,16 +14,21 @@ GNU Affero General Public License for more details.
|
|
|
14
14
|
You should have received a copy of the GNU Affero General Public License
|
|
15
15
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
16
|
*/
|
|
17
|
+
import * as fs from "fs";
|
|
17
18
|
import * as express from "express";
|
|
18
19
|
import * as extend from 'extend';
|
|
20
|
+
import * as multer from 'multer';
|
|
21
|
+
import * as path from "path";
|
|
19
22
|
import { sys, LightGroup, ControllerType, Pump, Valve, Body, General, Circuit, ICircuit, Feature, CircuitGroup, CustomNameCollection, Schedule, Chlorinator, Heater } from "../../../controller/Equipment";
|
|
20
23
|
import { config } from "../../../config/Config";
|
|
21
24
|
import { logger } from "../../../logger/Logger";
|
|
22
25
|
import { utils } from "../../../controller/Constants";
|
|
26
|
+
import { ServiceProcessError } from "../../../controller/Errors";
|
|
23
27
|
import { state } from "../../../controller/State";
|
|
24
28
|
import { stopPacketCaptureAsync, startPacketCapture } from '../../../app';
|
|
25
29
|
import { conn } from "../../../controller/comms/Comms";
|
|
26
|
-
import { webApp } from "../../Server";
|
|
30
|
+
import { webApp, BackupFile, RestoreFile } from "../../Server";
|
|
31
|
+
import { release } from "os";
|
|
27
32
|
|
|
28
33
|
export class ConfigRoute {
|
|
29
34
|
public static initRoutes(app: express.Application) {
|
|
@@ -52,7 +57,8 @@ export class ConfigRoute {
|
|
|
52
57
|
clockSources: sys.board.valueMaps.clockSources.toArray(),
|
|
53
58
|
clockModes: sys.board.valueMaps.clockModes.toArray(),
|
|
54
59
|
pool: sys.general.get(true),
|
|
55
|
-
sensors: sys.board.system.getSensors()
|
|
60
|
+
sensors: sys.board.system.getSensors(),
|
|
61
|
+
systemUnits: sys.board.valueMaps.systemUnits.toArray()
|
|
56
62
|
};
|
|
57
63
|
return res.status(200).send(opts);
|
|
58
64
|
});
|
|
@@ -106,7 +112,7 @@ export class ConfigRoute {
|
|
|
106
112
|
invalidIds: sys.board.equipmentIds.invalidIds.get(),
|
|
107
113
|
equipmentIds: sys.equipment.equipmentIds.features,
|
|
108
114
|
equipmentNames: sys.board.circuits.getCircuitNames(),
|
|
109
|
-
functions: sys.board.
|
|
115
|
+
functions: sys.board.features.getFeatureFunctions(),
|
|
110
116
|
features: sys.features.get()
|
|
111
117
|
};
|
|
112
118
|
return res.status(200).send(opts);
|
|
@@ -115,7 +121,8 @@ export class ConfigRoute {
|
|
|
115
121
|
let opts = {
|
|
116
122
|
maxBodies: sys.equipment.maxBodies,
|
|
117
123
|
bodyTypes: sys.board.valueMaps.bodies.toArray(),
|
|
118
|
-
bodies: sys.bodies.get()
|
|
124
|
+
bodies: sys.bodies.get(),
|
|
125
|
+
capacityUnits: sys.board.valueMaps.volumeUnits.toArray()
|
|
119
126
|
};
|
|
120
127
|
return res.status(200).send(opts);
|
|
121
128
|
});
|
|
@@ -282,7 +289,8 @@ export class ConfigRoute {
|
|
|
282
289
|
bodies: sys.board.bodies.getBodyAssociations(),
|
|
283
290
|
chlorinators: sys.chlorinators.get(),
|
|
284
291
|
maxChlorinators: sys.equipment.maxChlorinators,
|
|
285
|
-
models: sys.board.valueMaps.chlorinatorModel.toArray()
|
|
292
|
+
models: sys.board.valueMaps.chlorinatorModel.toArray(),
|
|
293
|
+
equipmentMasters: sys.board.valueMaps.equipmentMaster.toArray()
|
|
286
294
|
};
|
|
287
295
|
return res.status(200).send(opts);
|
|
288
296
|
});
|
|
@@ -307,13 +315,16 @@ export class ConfigRoute {
|
|
|
307
315
|
let opts = {
|
|
308
316
|
interfaces: config.getSection('web.interfaces'),
|
|
309
317
|
types: [
|
|
310
|
-
{name: '
|
|
311
|
-
{name: '
|
|
318
|
+
{ name: 'rest', desc: 'Rest' },
|
|
319
|
+
{ name: 'http', desc: 'Http' },
|
|
320
|
+
{ name: 'rem', desc: 'Relay Equipment Manager' },
|
|
321
|
+
{ name: 'mqtt', desc: 'MQTT' },
|
|
322
|
+
{ name: 'influx', desc: 'InfluxDB' }
|
|
312
323
|
],
|
|
313
324
|
protocols: [
|
|
314
325
|
{ val: 0, name: 'http://', desc: 'http://' },
|
|
315
326
|
{ val: 1, name: 'https://', desc: 'https://' },
|
|
316
|
-
{ val: 2, name: 'mqtt://', desc: 'mqtt://' }
|
|
327
|
+
{ val: 2, name: 'mqtt://', desc: 'mqtt://' }
|
|
317
328
|
]
|
|
318
329
|
}
|
|
319
330
|
return res.status(200).send(opts);
|
|
@@ -332,6 +343,8 @@ export class ConfigRoute {
|
|
|
332
343
|
bodies: sys.board.bodies.getBodyAssociations(),
|
|
333
344
|
filters: sys.filters.get(),
|
|
334
345
|
areaUnits: sys.board.valueMaps.areaUnits.toArray(),
|
|
346
|
+
pressureUnits: sys.board.valueMaps.pressureUnits.toArray(),
|
|
347
|
+
circuits: sys.board.circuits.getCircuitReferences(true, true, true, false),
|
|
335
348
|
servers: []
|
|
336
349
|
};
|
|
337
350
|
if (sys.controllerType === ControllerType.Nixie) opts.servers = await sys.ncp.getREMServers();
|
|
@@ -340,14 +353,14 @@ export class ConfigRoute {
|
|
|
340
353
|
});
|
|
341
354
|
/******* END OF CONFIGURATION PICK LISTS/REFERENCES AND VALIDATION ***********/
|
|
342
355
|
/******* ENDPOINTS FOR MODIFYING THE OUTDOOR CONTROL PANEL SETTINGS **********/
|
|
343
|
-
app.put('/config/rem', async (req, res, next)=>{
|
|
356
|
+
app.put('/config/rem', async (req, res, next) => {
|
|
344
357
|
try {
|
|
345
358
|
// RSG: this is problematic because we now enable multiple rem type interfaces that may not be called REM.
|
|
346
359
|
// This is now also a dupe of PUT /app/interface and should be consolidated
|
|
347
360
|
// config.setSection('web.interfaces.rem', req.body);
|
|
348
361
|
config.setInterface(req.body);
|
|
349
362
|
}
|
|
350
|
-
catch (err) {next(err);}
|
|
363
|
+
catch (err) { next(err); }
|
|
351
364
|
})
|
|
352
365
|
app.put('/config/tempSensors', async (req, res, next) => {
|
|
353
366
|
try {
|
|
@@ -362,7 +375,7 @@ export class ConfigRoute {
|
|
|
362
375
|
});
|
|
363
376
|
app.put('/config/filter', async (req, res, next) => {
|
|
364
377
|
try {
|
|
365
|
-
let sfilter = sys.board.filters.
|
|
378
|
+
let sfilter = await sys.board.filters.setFilterAsync(req.body);
|
|
366
379
|
return res.status(200).send(sfilter.get(true));
|
|
367
380
|
}
|
|
368
381
|
catch (err) { next(err); }
|
|
@@ -375,7 +388,7 @@ export class ConfigRoute {
|
|
|
375
388
|
});
|
|
376
389
|
app.delete('/config/filter', async (req, res, next) => {
|
|
377
390
|
try {
|
|
378
|
-
let sfilter = sys.board.filters.
|
|
391
|
+
let sfilter = await sys.board.filters.deleteFilterAsync(req.body);
|
|
379
392
|
return res.status(200).send(sfilter.get(true));
|
|
380
393
|
}
|
|
381
394
|
catch (err) { next(err); }
|
|
@@ -579,8 +592,8 @@ export class ConfigRoute {
|
|
|
579
592
|
return res.status(200).send(circuitFunctions);
|
|
580
593
|
});
|
|
581
594
|
app.get('/config/features/functions', (req, res) => {
|
|
582
|
-
let
|
|
583
|
-
return res.status(200).send(
|
|
595
|
+
let featureFunctions = sys.board.features.getFeatureFunctions();
|
|
596
|
+
return res.status(200).send(featureFunctions);
|
|
584
597
|
});
|
|
585
598
|
app.get('/config/circuit/:id', (req, res) => {
|
|
586
599
|
// todo: need getInterfaceById.get() in case features are requested here
|
|
@@ -589,18 +602,18 @@ export class ConfigRoute {
|
|
|
589
602
|
});
|
|
590
603
|
app.get('/config/circuit/:id/lightThemes', (req, res) => {
|
|
591
604
|
let circuit = sys.circuits.getInterfaceById(parseInt(req.params.id, 10));
|
|
592
|
-
let themes = typeof circuit !== 'undefined' && typeof circuit.getLightThemes === 'function' ? circuit.getLightThemes() : [];
|
|
605
|
+
let themes = typeof circuit !== 'undefined' && typeof circuit.getLightThemes === 'function' ? circuit.getLightThemes(circuit.type) : [];
|
|
593
606
|
return res.status(200).send(themes);
|
|
594
607
|
});
|
|
608
|
+
app.get('/config/circuit/:id/lightCommands', (req, res) => {
|
|
609
|
+
let circuit = sys.circuits.getInterfaceById(parseInt(req.params.id, 10));
|
|
610
|
+
let commands = typeof circuit !== 'undefined' && typeof circuit.getLightThemes === 'function' ? circuit.getLightCommands(circuit.type) : [];
|
|
611
|
+
return res.status(200).send(commands);
|
|
612
|
+
});
|
|
613
|
+
|
|
595
614
|
app.get('/config/chlorinator/:id', (req, res) => {
|
|
596
615
|
return res.status(200).send(sys.chlorinators.getItemById(parseInt(req.params.id, 10)).get());
|
|
597
616
|
});
|
|
598
|
-
//app.put('/config/chlorinator', (req, res) => {
|
|
599
|
-
// let chlor = sys.chlorinators.getItemById(parseInt(req.body.id, 10), true);
|
|
600
|
-
// sys.board.chlorinator.setChlorProps(chlor, req.body);
|
|
601
|
-
// // if (chlor.isVirtual) { sys.board.virtualChlorinatorController.start(); }
|
|
602
|
-
// return res.status(200).send(sys.chlorinators.getItemById(parseInt(req.params.id, 10)).get());
|
|
603
|
-
//});
|
|
604
617
|
app.get('/config/chlorinators/search', async (req, res, next) => {
|
|
605
618
|
// Change the options for the pool.
|
|
606
619
|
try {
|
|
@@ -611,103 +624,6 @@ export class ConfigRoute {
|
|
|
611
624
|
next(err);
|
|
612
625
|
}
|
|
613
626
|
});
|
|
614
|
-
/* app.get('/config/pump/:id/circuits', (req, res) => {
|
|
615
|
-
return res.status(200).send(sys.pumps.getItemById(parseInt(req.params.id, 10)).get().circuits);
|
|
616
|
-
});
|
|
617
|
-
app.get('/config/pump/availableCircuits', (req, res) => {
|
|
618
|
-
return res.status(200).send(sys.board.pumps.availableCircuits());
|
|
619
|
-
});
|
|
620
|
-
app.get('/config/pump/:id/circuit/:circuitid', (req, res) => {
|
|
621
|
-
return res.status(200).send(sys.pumps.getItemById(parseInt(req.params.id, 10)).get().circuits[parseInt(req.params.circuitid, 10)]);
|
|
622
|
-
});
|
|
623
|
-
app.get('/config/pump/:id/nextAvailablePumpCircuit', (req, res) => {
|
|
624
|
-
// if no pumpCircuitId is available, 0 will be returned
|
|
625
|
-
let _id = sys.pumps.getItemById(parseInt(req.params.id, 10)).nextAvailablePumpCircuit();
|
|
626
|
-
return res.status(200).send(_id.toString());
|
|
627
|
-
}); */
|
|
628
|
-
/*
|
|
629
|
-
app.put('/config/pump/:id/pumpCircuit', (req, res) => {
|
|
630
|
-
// if no pumpCircuitId is specified, set it as 0 and take the next available one
|
|
631
|
-
req.url = `${ req.url }/0`;
|
|
632
|
-
req.next();
|
|
633
|
-
});
|
|
634
|
-
app.put('/config/pump/:id/pumpCircuit/:pumpCircuitId', (req, res) => {
|
|
635
|
-
// RSG - do we want a /config/pump/:id/pumpCircuit/ that will just assume the next circuit?
|
|
636
|
-
let pump = sys.pumps.getItemById(parseInt(req.params.id, 10));
|
|
637
|
-
let _pumpCircuitId = parseInt(req.params.pumpCircuitId, 10);
|
|
638
|
-
let _circuit = parseInt(req.body.circuit, 10);
|
|
639
|
-
let _rate = parseInt(req.body.rate, 10);
|
|
640
|
-
let _units = parseInt(req.body.units, 10) || pump.defaultUnits;
|
|
641
|
-
let pumpCircuit = {
|
|
642
|
-
pump: parseInt(req.params.id, 10),
|
|
643
|
-
pumpCircuitId: isNaN(_pumpCircuitId) ? undefined : _pumpCircuitId,
|
|
644
|
-
circuit: isNaN(_circuit) ? undefined : _circuit,
|
|
645
|
-
rate: isNaN(_rate) ? undefined : _rate,
|
|
646
|
-
units: isNaN(_units) ? undefined : _units
|
|
647
|
-
};
|
|
648
|
-
let { result, reason } = pump.setPumpCircuit(pumpCircuit);
|
|
649
|
-
if (result === 'OK')
|
|
650
|
-
return res.status(200).send({ result: result, reason: reason });
|
|
651
|
-
else
|
|
652
|
-
return res.status(500).send({ result: result, reason: reason });
|
|
653
|
-
}); */
|
|
654
|
-
/* app.delete('/config/pump/:id/pumpCircuit/:pumpCircuitId', (req, res) => {
|
|
655
|
-
let pump = sys.pumps.getItemById(parseInt(req.params.id, 10));
|
|
656
|
-
// pump.circuits.removeItemById(parseInt(req.params.pumpCircuitId, 10));
|
|
657
|
-
pump.deletePumpCircuit(parseInt(req.params.pumpCircuitId, 10));
|
|
658
|
-
return res.status(200).send('OK');
|
|
659
|
-
}); */
|
|
660
|
-
/* app.get('/config/pump/types', (req, res) => {
|
|
661
|
-
let pumpTypes = sys.board.pumps.getPumpTypes();
|
|
662
|
-
return res.status(200).send(pumpTypes);
|
|
663
|
-
});
|
|
664
|
-
app.get('/config/pump/units', (req, res) => {
|
|
665
|
-
// get all units for all system board
|
|
666
|
-
let pumpTypes = sys.board.pumps.getCircuitUnits();
|
|
667
|
-
return res.status(200).send(pumpTypes);
|
|
668
|
-
});
|
|
669
|
-
app.get('/config/pump/:id/units', (req, res) => {
|
|
670
|
-
// get units for all specific pump types
|
|
671
|
-
// need to coorerce into array if only a single unit is returned; by default getExtended will return an array
|
|
672
|
-
// if there is 1+ object so this creates parity
|
|
673
|
-
let pump = sys.pumps.getItemById(parseInt(req.params.id, 10));
|
|
674
|
-
let pumpTypes = sys.board.pumps.getCircuitUnits(pump);
|
|
675
|
-
if (!Array.isArray(pumpTypes)) pumpTypes = [pumpTypes];
|
|
676
|
-
return res.status(200).send(pumpTypes);
|
|
677
|
-
});
|
|
678
|
-
app.put('/config/pump/:pumpId/type', (req, res) => {
|
|
679
|
-
const _type = parseInt(req.body.pumpType, 10);
|
|
680
|
-
const _pumpId = parseInt(req.params.pumpId, 10);
|
|
681
|
-
// 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.
|
|
682
|
-
let pump = sys.pumps.getItemById(_pumpId);
|
|
683
|
-
if (sys.controllerType === ControllerType.Virtual) {
|
|
684
|
-
pump.isVirtual = true;
|
|
685
|
-
}
|
|
686
|
-
if (_type !== pump.type) {
|
|
687
|
-
pump.setType(_type);
|
|
688
|
-
}
|
|
689
|
-
return res.status(200).send('OK');
|
|
690
|
-
}); */
|
|
691
|
-
/* app.get('/config/pump/:pumpId', (req, res) => {
|
|
692
|
-
let pump = sys.pumps.getItemById(parseInt(req.params.pumpId, 10)).get(true);
|
|
693
|
-
return res.status(200).send(pump);
|
|
694
|
-
});
|
|
695
|
-
app.put('/config/pump/:pumpId', (req, res) => {
|
|
696
|
-
// this will change the pump type
|
|
697
|
-
let _type = parseInt(req.body.pumpType, 10);
|
|
698
|
-
let pump = sys.pumps.getItemById(parseInt(req.params.pumpId, 10));
|
|
699
|
-
if (sys.controllerType === ControllerType.Virtual) {
|
|
700
|
-
// if virtualController, add the virtual pump
|
|
701
|
-
pump.isVirtual = true;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
if (_type !== pump.type && typeof _type !== 'undefined') {
|
|
705
|
-
pump.setType(_type);
|
|
706
|
-
}
|
|
707
|
-
// get a new instance of the pump here because setType will remove/add a new instance
|
|
708
|
-
if (Object.keys(req.body).length) sys.pumps.getItemById(parseInt(req.params.pumpId, 10)).setPump(req.body);
|
|
709
|
-
return res.status(200).send('OK');
|
|
710
|
-
}); */
|
|
711
627
|
app.delete('/config/pump/:pumpId', (req, res) => {
|
|
712
628
|
let pump = sys.pumps.getItemById(parseInt(req.params.pumpId, 10));
|
|
713
629
|
if (pump.type === 0) {
|
|
@@ -725,13 +641,12 @@ export class ConfigRoute {
|
|
|
725
641
|
});
|
|
726
642
|
app.get('/config/lightGroups/themes', (req, res) => {
|
|
727
643
|
// RSG: is this and /config/circuit/:id/lightThemes both needed?
|
|
728
|
-
|
|
729
|
-
// if (sys.controllerType === ControllerType.IntelliCenter) {
|
|
730
|
-
let grp = sys.lightGroups.getItemById(parseInt(req.params.id, 10));
|
|
644
|
+
let grp = sys.lightGroups.getItemById(parseInt(req.body.id, 10));
|
|
731
645
|
return res.status(200).send(grp.getLightThemes());
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
646
|
+
});
|
|
647
|
+
app.get('/config/lightGroups/commands', (req, res) => {
|
|
648
|
+
let grp = sys.lightGroups.getItemById(parseInt(req.body.id, 10));
|
|
649
|
+
return res.status(200).send(grp.getLightCommands());
|
|
735
650
|
});
|
|
736
651
|
app.get('/config/lightGroup/:id', (req, res) => {
|
|
737
652
|
// if (sys.controllerType === ControllerType.IntelliCenter) {
|
|
@@ -760,16 +675,16 @@ export class ConfigRoute {
|
|
|
760
675
|
let grp = sys.circuitGroups.getItemById(parseInt(req.params.id, 10));
|
|
761
676
|
return res.status(200).send(grp.getExtended());
|
|
762
677
|
});
|
|
763
|
-
/* app.get('/config/chemController/search', async (req, res, next) => {
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
678
|
+
/* app.get('/config/chemController/search', async (req, res, next) => {
|
|
679
|
+
// Change the options for the pool.
|
|
680
|
+
try {
|
|
681
|
+
let result = await sys.board.virtualChemControllers.search();
|
|
682
|
+
return res.status(200).send(result);
|
|
683
|
+
}
|
|
684
|
+
catch (err) {
|
|
685
|
+
next(err);
|
|
686
|
+
}
|
|
687
|
+
}); */
|
|
773
688
|
app.put('/config/chemController', async (req, res, next) => {
|
|
774
689
|
try {
|
|
775
690
|
let chem = await sys.board.chemControllers.setChemControllerAsync(req.body);
|
|
@@ -792,17 +707,17 @@ export class ConfigRoute {
|
|
|
792
707
|
catch (err) { next(err); }
|
|
793
708
|
|
|
794
709
|
});
|
|
795
|
-
/* app.get('/config/intellibrite', (req, res) => {
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
710
|
+
/* app.get('/config/intellibrite', (req, res) => {
|
|
711
|
+
return res.status(200).send(sys.intellibrite.getExtended());
|
|
712
|
+
});
|
|
713
|
+
app.get('/config/intellibrite/colors', (req, res) => {
|
|
714
|
+
return res.status(200).send(sys.board.valueMaps.lightColors.toArray());
|
|
715
|
+
});
|
|
716
|
+
app.put('/config/intellibrite/setColors', (req, res) => {
|
|
717
|
+
let grp = extend(true, { id: 0 }, req.body);
|
|
718
|
+
sys.board.circuits.setIntelliBriteColors(new LightGroup(grp));
|
|
719
|
+
return res.status(200).send('OK');
|
|
720
|
+
}); */
|
|
806
721
|
app.get('/config', (req, res) => {
|
|
807
722
|
return res.status(200).send(sys.getSection('all'));
|
|
808
723
|
});
|
|
@@ -828,11 +743,11 @@ export class ConfigRoute {
|
|
|
828
743
|
return res.status(200).send('OK');
|
|
829
744
|
});
|
|
830
745
|
app.put('/app/interface', async (req, res, next) => {
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
746
|
+
try {
|
|
747
|
+
let iface = await webApp.updateServerInterface(req.body);
|
|
748
|
+
return res.status(200).send(iface);
|
|
749
|
+
}
|
|
750
|
+
catch (err) { next(err); }
|
|
836
751
|
});
|
|
837
752
|
app.put('/app/rs485Port', async (req, res, next) => {
|
|
838
753
|
try {
|
|
@@ -849,15 +764,129 @@ export class ConfigRoute {
|
|
|
849
764
|
startPacketCapture(false);
|
|
850
765
|
return res.status(200).send('OK');
|
|
851
766
|
});
|
|
852
|
-
app.get('/app/config/stopPacketCapture', async (req, res,next) => {
|
|
767
|
+
app.get('/app/config/stopPacketCapture', async (req, res, next) => {
|
|
853
768
|
try {
|
|
854
769
|
let file = await stopPacketCaptureAsync();
|
|
855
770
|
res.download(file);
|
|
856
771
|
}
|
|
857
|
-
catch (err) {next(err);}
|
|
772
|
+
catch (err) { next(err); }
|
|
858
773
|
});
|
|
859
774
|
app.get('/app/config/:section', (req, res) => {
|
|
860
775
|
return res.status(200).send(config.getSection(req.params.section));
|
|
861
776
|
});
|
|
777
|
+
app.get('/app/config/options/backup', async (req, res, next) => {
|
|
778
|
+
try {
|
|
779
|
+
let opts = config.getSection('controller.backups', { automatic: false, interval: { days: 30, hours: 0 }, keepCount: 5, servers: [] });
|
|
780
|
+
let servers = await sys.ncp.getREMServers();
|
|
781
|
+
if (typeof servers !== 'undefined') {
|
|
782
|
+
// Just in case somebody deletes the backup section and doesn't put it back properly.
|
|
783
|
+
for (let i = 0; i < servers.length; i++) {
|
|
784
|
+
let srv = servers[i];
|
|
785
|
+
if (typeof opts.servers.find(elem => elem.uuid === srv.uuid) === 'undefined') opts.servers.push({ name: srv.name, uuid: srv.uuid, backup: false, host: srv.interface.options.host });
|
|
786
|
+
}
|
|
787
|
+
for (let i = opts.servers.length - 1; i >= 0; i--) {
|
|
788
|
+
let srv = opts.servers[i];
|
|
789
|
+
if (typeof servers.find(elem => elem.uuid === srv.uuid) === 'undefined') opts.servers.splice(i, 1);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
if (typeof opts.servers === 'undefined') opts.servers = [];
|
|
793
|
+
return res.status(200).send(opts);
|
|
794
|
+
} catch (err) { next(err); }
|
|
795
|
+
});
|
|
796
|
+
app.get('/app/config/options/restore', async (req, res, next) => {
|
|
797
|
+
try {
|
|
798
|
+
let opts = config.getSection('controller.backups', { automatic: false, interval: { days: 30, hours: 0 }, keepCount: 5, servers: [], backupFiles: [] });
|
|
799
|
+
let servers = await sys.ncp.getREMServers();
|
|
800
|
+
if (typeof servers !== 'undefined') {
|
|
801
|
+
for (let i = 0; i < servers.length; i++) {
|
|
802
|
+
let srv = servers[i];
|
|
803
|
+
if (typeof opts.servers.find(elem => elem.uuid === srv.uuid) === 'undefined') opts.servers.push({ name: srv.name, uuid: srv.uuid, backup: false });
|
|
804
|
+
}
|
|
805
|
+
for (let i = opts.servers.length - 1; i >= 0; i--) {
|
|
806
|
+
let srv = opts.servers[i];
|
|
807
|
+
if (typeof servers.find(elem => elem.uuid === srv.uuid) === 'undefined') opts.servers.splice(i, 1);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
if (typeof opts.servers === 'undefined') opts.servers = [];
|
|
811
|
+
opts.backupFiles = await webApp.readBackupFiles();
|
|
812
|
+
return res.status(200).send(opts);
|
|
813
|
+
} catch (err) { next(err); }
|
|
814
|
+
|
|
815
|
+
});
|
|
816
|
+
app.put('/app/config/options/backup', async (req, res, next) => {
|
|
817
|
+
try {
|
|
818
|
+
config.setSection('controller.backups', req.body);
|
|
819
|
+
let opts = config.getSection('controller.backups', { automatic: false, interval: { days: 30, hours: 0 }, keepCount: 5, servers: [] });
|
|
820
|
+
webApp.autoBackup = utils.makeBool(opts.automatic);
|
|
821
|
+
await webApp.checkAutoBackup();
|
|
822
|
+
return res.status(200).send(opts);
|
|
823
|
+
} catch (err) { next(err); }
|
|
824
|
+
|
|
825
|
+
});
|
|
826
|
+
app.put('/app/config/createBackup', async (req, res, next) => {
|
|
827
|
+
try {
|
|
828
|
+
let ret = await webApp.backupServer(req.body);
|
|
829
|
+
res.download(ret.filePath);
|
|
830
|
+
}
|
|
831
|
+
catch (err) { next(err); }
|
|
832
|
+
});
|
|
833
|
+
app.delete('/app/backup/file', async (req, res, next) => {
|
|
834
|
+
try {
|
|
835
|
+
let opts = req.body;
|
|
836
|
+
fs.unlinkSync(opts.filePath);
|
|
837
|
+
return res.status(200).send(opts);
|
|
838
|
+
}
|
|
839
|
+
catch (err) { next(err); }
|
|
840
|
+
});
|
|
841
|
+
app.post('/app/backup/file', async (req, res, next) => {
|
|
842
|
+
try {
|
|
843
|
+
let file = multer({
|
|
844
|
+
limits: { fileSize: 1000000 },
|
|
845
|
+
storage: multer.memoryStorage()
|
|
846
|
+
}).single('backupFile');
|
|
847
|
+
file(req, res, async (err) => {
|
|
848
|
+
try {
|
|
849
|
+
if (err) { next(err); }
|
|
850
|
+
else {
|
|
851
|
+
// Validate the incoming data and save it off only if it is valid.
|
|
852
|
+
let bf = await BackupFile.fromBuffer(req.file.originalname, req.file.buffer);
|
|
853
|
+
if (typeof bf === 'undefined') {
|
|
854
|
+
err = new ServiceProcessError(`Invalid backup file: ${req.file.originalname}`, 'POST: app/backup/file', 'extractBackupOptions');
|
|
855
|
+
next(err);
|
|
856
|
+
}
|
|
857
|
+
else {
|
|
858
|
+
if (fs.existsSync(bf.filePath))
|
|
859
|
+
return next(new ServiceProcessError(`File already exists ${req.file.originalname}`, 'POST: app/backup/file', 'writeFile'));
|
|
860
|
+
else {
|
|
861
|
+
try {
|
|
862
|
+
fs.writeFileSync(bf.filePath, req.file.buffer);
|
|
863
|
+
} catch (e) { logger.error(`Error writing backup file ${e.message}`); }
|
|
864
|
+
}
|
|
865
|
+
return res.status(200).send(bf);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
} catch (e) {
|
|
869
|
+
err = new ServiceProcessError(`Error uploading file: ${e.message}`, 'POST: app/backup/file', 'uploadFile');
|
|
870
|
+
next(err);
|
|
871
|
+
logger.error(e);
|
|
872
|
+
}
|
|
873
|
+
});
|
|
874
|
+
} catch (err) { next(err); }
|
|
875
|
+
});
|
|
876
|
+
app.put('/app/restore/validate', async (req, res, next) => {
|
|
877
|
+
try {
|
|
878
|
+
// Validate all the restore options.
|
|
879
|
+
let opts = req.body;
|
|
880
|
+
let ctx = await webApp.validateRestore(opts);
|
|
881
|
+
return res.status(200).send(ctx);
|
|
882
|
+
} catch (err) { next(err); }
|
|
883
|
+
});
|
|
884
|
+
app.put('/app/restore/file', async (req, res, next) => {
|
|
885
|
+
try {
|
|
886
|
+
let opts = req.body;
|
|
887
|
+
let results = await webApp.restoreServers(opts);
|
|
888
|
+
return res.status(200).send(results);
|
|
889
|
+
} catch (err) { next(err); }
|
|
890
|
+
});
|
|
862
891
|
}
|
|
863
892
|
}
|
|
File without changes
|