nodejs-poolcontroller 7.6.0 → 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.
Files changed (85) hide show
  1. package/.eslintrc.json +44 -44
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +52 -52
  3. package/CONTRIBUTING.md +74 -74
  4. package/Changelog +215 -215
  5. package/Dockerfile +17 -17
  6. package/Gruntfile.js +40 -40
  7. package/LICENSE +661 -661
  8. package/README.md +191 -186
  9. package/app.ts +0 -0
  10. package/config/Config.ts +24 -2
  11. package/config/VersionCheck.ts +27 -12
  12. package/config copy.json +299 -299
  13. package/controller/Constants.ts +0 -0
  14. package/controller/Equipment.ts +2459 -2405
  15. package/controller/Errors.ts +180 -180
  16. package/controller/Lockouts.ts +436 -422
  17. package/controller/State.ts +51 -26
  18. package/controller/boards/BoardFactory.ts +45 -45
  19. package/controller/boards/EasyTouchBoard.ts +2653 -2537
  20. package/controller/boards/IntelliCenterBoard.ts +4230 -4034
  21. package/controller/boards/IntelliComBoard.ts +63 -63
  22. package/controller/boards/IntelliTouchBoard.ts +241 -241
  23. package/controller/boards/NixieBoard.ts +1675 -1660
  24. package/controller/boards/SystemBoard.ts +4697 -4463
  25. package/controller/comms/Comms.ts +138 -1
  26. package/controller/comms/messages/Messages.ts +3 -5
  27. package/controller/comms/messages/config/ChlorinatorMessage.ts +1 -1
  28. package/controller/comms/messages/config/CircuitGroupMessage.ts +0 -0
  29. package/controller/comms/messages/config/CircuitMessage.ts +0 -0
  30. package/controller/comms/messages/config/ConfigMessage.ts +0 -0
  31. package/controller/comms/messages/config/CoverMessage.ts +0 -0
  32. package/controller/comms/messages/config/CustomNameMessage.ts +30 -30
  33. package/controller/comms/messages/config/EquipmentMessage.ts +0 -0
  34. package/controller/comms/messages/config/ExternalMessage.ts +9 -7
  35. package/controller/comms/messages/config/FeatureMessage.ts +0 -0
  36. package/controller/comms/messages/config/GeneralMessage.ts +0 -0
  37. package/controller/comms/messages/config/HeaterMessage.ts +0 -20
  38. package/controller/comms/messages/config/IntellichemMessage.ts +0 -0
  39. package/controller/comms/messages/config/OptionsMessage.ts +25 -1
  40. package/controller/comms/messages/config/PumpMessage.ts +0 -0
  41. package/controller/comms/messages/config/RemoteMessage.ts +0 -0
  42. package/controller/comms/messages/config/ScheduleMessage.ts +347 -342
  43. package/controller/comms/messages/config/SecurityMessage.ts +0 -0
  44. package/controller/comms/messages/config/ValveMessage.ts +0 -0
  45. package/controller/comms/messages/status/ChlorinatorStateMessage.ts +0 -0
  46. package/controller/comms/messages/status/EquipmentStateMessage.ts +1 -1
  47. package/controller/comms/messages/status/HeaterStateMessage.ts +86 -86
  48. package/controller/comms/messages/status/IntelliChemStateMessage.ts +445 -397
  49. package/controller/comms/messages/status/IntelliValveStateMessage.ts +35 -35
  50. package/controller/comms/messages/status/PumpStateMessage.ts +0 -0
  51. package/controller/comms/messages/status/VersionMessage.ts +0 -0
  52. package/controller/nixie/Nixie.ts +162 -162
  53. package/controller/nixie/NixieEquipment.ts +103 -103
  54. package/controller/nixie/bodies/Body.ts +120 -120
  55. package/controller/nixie/bodies/Filter.ts +135 -135
  56. package/controller/nixie/chemistry/ChemController.ts +2498 -2398
  57. package/controller/nixie/chemistry/Chlorinator.ts +314 -314
  58. package/controller/nixie/circuits/Circuit.ts +248 -245
  59. package/controller/nixie/heaters/Heater.ts +648 -600
  60. package/controller/nixie/pumps/Pump.ts +661 -661
  61. package/controller/nixie/schedules/Schedule.ts +257 -257
  62. package/controller/nixie/valves/Valve.ts +170 -170
  63. package/defaultConfig.json +286 -286
  64. package/issue_template.md +51 -51
  65. package/logger/DataLogger.ts +448 -448
  66. package/logger/Logger.ts +0 -0
  67. package/package.json +56 -56
  68. package/tsconfig.json +25 -25
  69. package/web/Server.ts +2 -2
  70. package/web/bindings/influxDB.json +1021 -981
  71. package/web/bindings/mqtt.json +654 -654
  72. package/web/bindings/mqttAlt.json +684 -684
  73. package/web/bindings/rulesManager.json +54 -54
  74. package/web/bindings/smartThings-Hubitat.json +31 -31
  75. package/web/bindings/valveRelays.json +20 -20
  76. package/web/bindings/vera.json +25 -25
  77. package/web/interfaces/baseInterface.ts +136 -136
  78. package/web/interfaces/httpInterface.ts +124 -124
  79. package/web/interfaces/influxInterface.ts +245 -241
  80. package/web/interfaces/mqttInterface.ts +475 -475
  81. package/web/services/config/Config.ts +10 -108
  82. package/web/services/config/ConfigSocket.ts +0 -0
  83. package/web/services/state/State.ts +71 -4
  84. package/web/services/state/StateSocket.ts +0 -0
  85. package/web/services/utilities/Utilities.ts +42 -42
@@ -605,15 +605,15 @@ export class ConfigRoute {
605
605
  let themes = typeof circuit !== 'undefined' && typeof circuit.getLightThemes === 'function' ? circuit.getLightThemes(circuit.type) : [];
606
606
  return res.status(200).send(themes);
607
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
+
608
614
  app.get('/config/chlorinator/:id', (req, res) => {
609
615
  return res.status(200).send(sys.chlorinators.getItemById(parseInt(req.params.id, 10)).get());
610
616
  });
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
617
  app.get('/config/chlorinators/search', async (req, res, next) => {
618
618
  // Change the options for the pool.
619
619
  try {
@@ -624,103 +624,6 @@ export class ConfigRoute {
624
624
  next(err);
625
625
  }
626
626
  });
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
627
  app.delete('/config/pump/:pumpId', (req, res) => {
725
628
  let pump = sys.pumps.getItemById(parseInt(req.params.pumpId, 10));
726
629
  if (pump.type === 0) {
@@ -738,13 +641,12 @@ export class ConfigRoute {
738
641
  });
739
642
  app.get('/config/lightGroups/themes', (req, res) => {
740
643
  // RSG: is this and /config/circuit/:id/lightThemes both needed?
741
-
742
- // if (sys.controllerType === ControllerType.IntelliCenter) {
743
644
  let grp = sys.lightGroups.getItemById(parseInt(req.body.id, 10));
744
645
  return res.status(200).send(grp.getLightThemes());
745
- // }
746
- // else
747
- // return res.status(200).send(sys.intellibrite.getLightThemes());
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());
748
650
  });
749
651
  app.get('/config/lightGroup/:id', (req, res) => {
750
652
  // if (sys.controllerType === ControllerType.IntelliCenter) {
File without changes
@@ -214,7 +214,44 @@ export class StateRoute {
214
214
  return res.status(200).send(theme.get(true));
215
215
  }
216
216
  catch (err) { next(err); }
217
- });
217
+ });
218
+ app.put('/state/light/setTheme', async (req, res, next) => {
219
+ try {
220
+ let theme = await state.circuits.setLightThemeAsync(parseInt(req.body.id, 10), sys.board.valueMaps.lightThemes.encode(req.body.theme));
221
+ return res.status(200).send(theme.get(true));
222
+ }
223
+ catch (err) { next(err); }
224
+ });
225
+
226
+ app.put('/state/light/runCommand', async (req, res, next) => {
227
+ try {
228
+ let slight = await sys.board.circuits.runLightCommandAsync(req.body);
229
+ return res.status(200).send(slight.get(true));
230
+ }
231
+ catch (err) { next(err); }
232
+ });
233
+ app.put('/state/light/:id/colorHold', async (req, res, next) => {
234
+ try {
235
+ let slight = await sys.board.circuits.runLightCommandAsync({ id: parseInt(req.params.id, 10), command: 'colorhold' });
236
+ return res.status(200).send(slight.get(true));
237
+ }
238
+ catch (err) { next(err); }
239
+ });
240
+ app.put('/state/light/:id/colorRecall', async (req, res, next) => {
241
+ try {
242
+ let slight = await sys.board.circuits.runLightCommandAsync({ id: parseInt(req.params.id, 10), command: 'colorecall' });
243
+ return res.status(200).send(slight.get(true));
244
+ }
245
+ catch (err) { next(err); }
246
+ });
247
+ app.put('/state/light/:id/lightThumper', async (req, res, next) => {
248
+ try {
249
+ let slight = await sys.board.circuits.runLightCommandAsync({ id: parseInt(req.params.id, 10), command: 'lightthumper' });
250
+ return res.status(200).send(slight.get(true));
251
+ }
252
+ catch (err) { next(err); }
253
+ });
254
+
218
255
  /* app.put('/state/intellibrite/setTheme', (req, res) => {
219
256
  let id = sys.board.equipmentIds.circuitGroups.start;
220
257
  if (typeof req.body.theme !== 'undefined') id = parseInt(req.body.id, 10);
@@ -330,27 +367,57 @@ export class StateRoute {
330
367
  }
331
368
  catch (err) { next(err); }
332
369
  });
370
+ app.put('/state/lightGroup/runCommand', async (req, res, next) => {
371
+ try {
372
+ let sgroup = await sys.board.circuits.runLightGroupCommandAsync(req.body);
373
+ return res.status(200).send(sgroup.get(true));
374
+ }
375
+ catch (err) { next(err); }
376
+ });
333
377
  app.put('/state/lightGroup/:id/colorSync', async (req, res, next) => {
334
378
  try {
335
- let sgroup = await sys.board.circuits.sequenceLightGroupAsync(parseInt(req.params.id, 10), 'sync');
379
+ let sgroup = await sys.board.circuits.sequenceLightGroupAsync(parseInt(req.params.id, 10), 'colorsync');
336
380
  return res.status(200).send(sgroup.get(true));
337
381
  }
338
382
  catch (err) { next(err); }
339
383
  });
340
384
  app.put('/state/lightGroup/:id/colorSet', async (req, res, next) => {
341
385
  try {
342
- let sgroup = await sys.board.circuits.sequenceLightGroupAsync(parseInt(req.params.id, 10), 'set');
386
+ let sgroup = await sys.board.circuits.sequenceLightGroupAsync(parseInt(req.params.id, 10), 'colorset');
343
387
  return res.status(200).send(sgroup.get(true));
344
388
  }
345
389
  catch (err) { next(err); }
346
390
  });
347
391
  app.put('/state/lightGroup/:id/colorSwim', async (req, res, next) => {
348
392
  try {
349
- let sgroup = await sys.board.circuits.sequenceLightGroupAsync(parseInt(req.params.id, 10), 'swim');
393
+ let sgroup = await sys.board.circuits.sequenceLightGroupAsync(parseInt(req.params.id, 10), 'colorswim');
350
394
  return res.status(200).send(sgroup.get(true));
351
395
  }
352
396
  catch (err) { next(err); }
353
397
  });
398
+ app.put('/state/lightGroup/:id/colorHold', async (req, res, next) => {
399
+ try {
400
+ let sgroup = await sys.board.circuits.runLightGroupCommandAsync({ id: parseInt(req.params.id, 10), command: 'colorhold' });
401
+ return res.status(200).send(sgroup.get(true));
402
+ }
403
+ catch (err) { next(err); }
404
+ });
405
+ app.put('/state/lightGroup/:id/colorRecall', async (req, res, next) => {
406
+ try {
407
+ let sgroup = await sys.board.circuits.runLightGroupCommandAsync({ id: parseInt(req.params.id, 10), command: 'colorrecall' });
408
+ return res.status(200).send(sgroup.get(true));
409
+ }
410
+ catch (err) { next(err); }
411
+ });
412
+ app.put('/state/lightGroup/:id/lightThumper', async (req, res, next) => {
413
+ try {
414
+ let sgroup = await sys.board.circuits.runLightGroupCommandAsync({ id: parseInt(req.params.id, 10), command: 'lightthumper' });
415
+ return res.status(200).send(sgroup.get(true));
416
+ }
417
+ catch (err) { next(err); }
418
+ });
419
+
420
+
354
421
  app.get('/state/emitAll', (req, res) => {
355
422
  res.status(200).send(state.emitAllEquipmentChanges());
356
423
  });
File without changes
@@ -1,43 +1,43 @@
1
- /* nodejs-poolController. An application to control pool equipment.
2
- Copyright (C) 2016, 2017, 2018, 2019, 2020. Russell Goldin, tagyoureit. russ.goldin@gmail.com
3
-
4
- This program is free software: you can redistribute it and/or modify
5
- it under the terms of the GNU Affero General Public License as
6
- published by the Free Software Foundation, either version 3 of the
7
- License, or (at your option) any later version.
8
-
9
- This program is distributed in the hope that it will be useful,
10
- but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- GNU Affero General Public License for more details.
13
-
14
- You should have received a copy of the GNU Affero General Public License
15
- along with this program. If not, see <http://www.gnu.org/licenses/>.
16
- */
17
- import * as express from 'express';
18
- import { SsdpServer} from '../../Server';
19
- import { state } from "../../../controller/State";
20
- import { sys } from "../../../controller/Equipment";
21
-
22
- const extend = require("extend");
23
- export class UtilitiesRoute {
24
-
25
- public static initRoutes(app: express.Application) {
26
- app.get('/device', function(req, res) {
27
- // there's got to be a better way to get this than instantiating SsdpServer() again.
28
- // RKS: There was I made the function static.
29
- let xml = SsdpServer.deviceXML();
30
- res.status(200).set('Content-Type', 'text/xml').send(xml);
31
- });
32
- app.get('/extended/:section', (req, res) => {
33
- let cfg = sys.getSection(req.params.section);
34
- let st = state.getState(req.params.section);
35
- let arr = [];
36
- for (let i = 0; i < cfg.length; i++){
37
- let p = extend(true, {}, cfg[i], st.find(s => s.id === cfg[i].id));
38
- arr.push(p);
39
- }
40
- return res.status(200).send(arr);
41
- });
42
- }
1
+ /* nodejs-poolController. An application to control pool equipment.
2
+ Copyright (C) 2016, 2017, 2018, 2019, 2020. Russell Goldin, tagyoureit. russ.goldin@gmail.com
3
+
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU Affero General Public License as
6
+ published by the Free Software Foundation, either version 3 of the
7
+ License, or (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU Affero General Public License for more details.
13
+
14
+ You should have received a copy of the GNU Affero General Public License
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ */
17
+ import * as express from 'express';
18
+ import { SsdpServer} from '../../Server';
19
+ import { state } from "../../../controller/State";
20
+ import { sys } from "../../../controller/Equipment";
21
+
22
+ const extend = require("extend");
23
+ export class UtilitiesRoute {
24
+
25
+ public static initRoutes(app: express.Application) {
26
+ app.get('/device', function(req, res) {
27
+ // there's got to be a better way to get this than instantiating SsdpServer() again.
28
+ // RKS: There was I made the function static.
29
+ let xml = SsdpServer.deviceXML();
30
+ res.status(200).set('Content-Type', 'text/xml').send(xml);
31
+ });
32
+ app.get('/extended/:section', (req, res) => {
33
+ let cfg = sys.getSection(req.params.section);
34
+ let st = state.getState(req.params.section);
35
+ let arr = [];
36
+ for (let i = 0; i < cfg.length; i++){
37
+ let p = extend(true, {}, cfg[i], st.find(s => s.id === cfg[i].id));
38
+ arr.push(p);
39
+ }
40
+ return res.status(200).send(arr);
41
+ });
42
+ }
43
43
  }