nodejs-poolcontroller 7.6.1 → 8.0.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.
Files changed (102) hide show
  1. package/.eslintrc.json +36 -45
  2. package/.github/ISSUE_TEMPLATE/1-bug-report.yml +84 -0
  3. package/.github/ISSUE_TEMPLATE/2-docs.md +12 -0
  4. package/.github/ISSUE_TEMPLATE/3-proposal.md +28 -0
  5. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  6. package/CONTRIBUTING.md +74 -74
  7. package/Changelog +242 -215
  8. package/Dockerfile +17 -17
  9. package/Gruntfile.js +40 -40
  10. package/LICENSE +661 -661
  11. package/README.md +195 -191
  12. package/anslq25/MessagesMock.ts +218 -0
  13. package/anslq25/boards/MockBoardFactory.ts +50 -0
  14. package/anslq25/boards/MockEasyTouchBoard.ts +696 -0
  15. package/anslq25/boards/MockSystemBoard.ts +217 -0
  16. package/anslq25/chemistry/MockChlorinator.ts +75 -0
  17. package/anslq25/pumps/MockPump.ts +84 -0
  18. package/app.ts +10 -14
  19. package/config/Config.ts +26 -8
  20. package/config/VersionCheck.ts +8 -4
  21. package/controller/Constants.ts +59 -25
  22. package/controller/Equipment.ts +2667 -2459
  23. package/controller/Errors.ts +181 -180
  24. package/controller/Lockouts.ts +534 -436
  25. package/controller/State.ts +596 -77
  26. package/controller/boards/AquaLinkBoard.ts +1003 -0
  27. package/controller/boards/BoardFactory.ts +53 -45
  28. package/controller/boards/EasyTouchBoard.ts +3079 -2653
  29. package/controller/boards/IntelliCenterBoard.ts +3821 -4230
  30. package/controller/boards/IntelliComBoard.ts +69 -63
  31. package/controller/boards/IntelliTouchBoard.ts +384 -241
  32. package/controller/boards/NixieBoard.ts +1871 -1675
  33. package/controller/boards/SunTouchBoard.ts +393 -0
  34. package/controller/boards/SystemBoard.ts +5244 -4697
  35. package/controller/comms/Comms.ts +905 -541
  36. package/controller/comms/ScreenLogic.ts +1663 -0
  37. package/controller/comms/messages/Messages.ts +382 -54
  38. package/controller/comms/messages/config/ChlorinatorMessage.ts +8 -4
  39. package/controller/comms/messages/config/CircuitGroupMessage.ts +5 -2
  40. package/controller/comms/messages/config/CircuitMessage.ts +82 -13
  41. package/controller/comms/messages/config/ConfigMessage.ts +3 -1
  42. package/controller/comms/messages/config/CoverMessage.ts +2 -1
  43. package/controller/comms/messages/config/CustomNameMessage.ts +31 -30
  44. package/controller/comms/messages/config/EquipmentMessage.ts +5 -1
  45. package/controller/comms/messages/config/ExternalMessage.ts +33 -3
  46. package/controller/comms/messages/config/FeatureMessage.ts +2 -1
  47. package/controller/comms/messages/config/GeneralMessage.ts +2 -1
  48. package/controller/comms/messages/config/HeaterMessage.ts +145 -11
  49. package/controller/comms/messages/config/IntellichemMessage.ts +2 -1
  50. package/controller/comms/messages/config/OptionsMessage.ts +16 -27
  51. package/controller/comms/messages/config/PumpMessage.ts +62 -47
  52. package/controller/comms/messages/config/RemoteMessage.ts +80 -13
  53. package/controller/comms/messages/config/ScheduleMessage.ts +390 -347
  54. package/controller/comms/messages/config/SecurityMessage.ts +2 -1
  55. package/controller/comms/messages/config/ValveMessage.ts +44 -27
  56. package/controller/comms/messages/status/ChlorinatorStateMessage.ts +44 -91
  57. package/controller/comms/messages/status/EquipmentStateMessage.ts +139 -30
  58. package/controller/comms/messages/status/HeaterStateMessage.ts +135 -86
  59. package/controller/comms/messages/status/IntelliChemStateMessage.ts +448 -445
  60. package/controller/comms/messages/status/IntelliValveStateMessage.ts +36 -35
  61. package/controller/comms/messages/status/PumpStateMessage.ts +92 -2
  62. package/controller/comms/messages/status/VersionMessage.ts +2 -1
  63. package/controller/nixie/Nixie.ts +173 -162
  64. package/controller/nixie/NixieEquipment.ts +104 -103
  65. package/controller/nixie/bodies/Body.ts +120 -120
  66. package/controller/nixie/bodies/Filter.ts +135 -135
  67. package/controller/nixie/chemistry/ChemController.ts +2682 -2498
  68. package/controller/nixie/chemistry/ChemDoser.ts +806 -0
  69. package/controller/nixie/chemistry/Chlorinator.ts +367 -314
  70. package/controller/nixie/circuits/Circuit.ts +402 -248
  71. package/controller/nixie/heaters/Heater.ts +815 -649
  72. package/controller/nixie/pumps/Pump.ts +934 -661
  73. package/controller/nixie/schedules/Schedule.ts +319 -257
  74. package/controller/nixie/valves/Valve.ts +170 -170
  75. package/defaultConfig.json +346 -286
  76. package/logger/DataLogger.ts +448 -448
  77. package/logger/Logger.ts +38 -9
  78. package/package.json +60 -56
  79. package/tsconfig.json +25 -25
  80. package/web/Server.ts +275 -117
  81. package/web/bindings/aqualinkD.json +560 -0
  82. package/web/bindings/homeassistant.json +437 -0
  83. package/web/bindings/influxDB.json +1066 -1021
  84. package/web/bindings/mqtt.json +721 -654
  85. package/web/bindings/mqttAlt.json +746 -684
  86. package/web/bindings/rulesManager.json +54 -54
  87. package/web/bindings/smartThings-Hubitat.json +31 -31
  88. package/web/bindings/valveRelays.json +20 -20
  89. package/web/bindings/vera.json +25 -25
  90. package/web/interfaces/baseInterface.ts +188 -136
  91. package/web/interfaces/httpInterface.ts +148 -124
  92. package/web/interfaces/influxInterface.ts +283 -245
  93. package/web/interfaces/mqttInterface.ts +695 -475
  94. package/web/interfaces/ruleInterface.ts +87 -0
  95. package/web/services/config/Config.ts +177 -49
  96. package/web/services/config/ConfigSocket.ts +2 -1
  97. package/web/services/state/State.ts +154 -3
  98. package/web/services/state/StateSocket.ts +69 -18
  99. package/web/services/utilities/Utilities.ts +232 -42
  100. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -52
  101. package/config copy.json +0 -300
  102. package/issue_template.md +0 -52
@@ -0,0 +1,87 @@
1
+ /* nodejs-poolController. An application to control pool equipment.
2
+ Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021, 2022.
3
+ Russell Goldin, tagyoureit. russ.goldin@gmail.com
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Affero General Public License as
7
+ published by the Free Software Foundation, either version 3 of the
8
+ License, or (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Affero General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Affero General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+ import { webApp } from "../../web/Server";
19
+ import extend=require("extend");
20
+ import { logger } from "../../logger/Logger";
21
+ import { PoolSystem, sys } from "../../controller/Equipment";
22
+ import { State, state } from "../../controller/State";
23
+ import { InterfaceContext, InterfaceEvent, BaseInterfaceBindings } from "./baseInterface";
24
+
25
+ export class RuleInterfaceBindings extends BaseInterfaceBindings {
26
+ constructor(cfg) { super(cfg);}
27
+ declare events: RuleInterfaceEvent[];
28
+ public bindProcessor(evt: RuleInterfaceEvent) {
29
+ if (evt.processorBound) return;
30
+ if (typeof evt.fnProcessor === 'undefined') {
31
+ let fnBody = Array.isArray(evt.processor) ? evt.processor.join('\n') : evt.processor;
32
+ if (typeof fnBody !== 'undefined' && fnBody !== '') {
33
+ //let AsyncFunction = Object.getPrototypeOf(async => () => { }).constructor;
34
+ let AsyncFunction = Object.getPrototypeOf(async function () { }).constructor;
35
+ try {
36
+ evt.fnProcessor = new AsyncFunction('rule', 'options', 'vars', 'logger', 'webApp', 'sys', 'state', 'data', fnBody) as (rule: RuleInterfaceEvent, vars: any, sys: PoolSystem, state: State, data: any) => void;
37
+ } catch (err) { logger.error(`Error compiling rule event processor: ${err} -- ${fnBody}`); }
38
+ }
39
+ }
40
+ evt.processorBound = true;
41
+ }
42
+ public executeProcessor(eventName: string, evt: RuleInterfaceEvent, ...data: any) {
43
+ this.bindProcessor(evt);
44
+ let vars = this.bindVarTokens(evt, eventName, data);
45
+ let opts = extend(true, this.cfg.options, this.context.options, evt.options);
46
+ if (typeof evt.fnProcessor !== undefined) evt.fnProcessor(evt, opts, vars, logger, webApp, sys, state, data);
47
+ }
48
+ public bindEvent(evt: string, ...data: any) {
49
+ // Find the binding by first looking for the specific event name.
50
+ // If that doesn't exist then look for the "*" (all events).
51
+ if (typeof this.events !== 'undefined') {
52
+ let evts = this.events.filter(elem => elem.name === evt);
53
+ // If we don't have an explicitly defined event then see if there is a default.
54
+ if (evts.length === 0) {
55
+ let e = this.events.find(elem => elem.name === '*');
56
+ evts = e ? [e] : [];
57
+ }
58
+ if (evts.length > 0) {
59
+ let toks = {};
60
+ for (let i = 0; i < evts.length; i++) {
61
+ let e = evts[i];
62
+ if (typeof e.enabled !== 'undefined' && !e.enabled) continue;
63
+ // Figure out whether we need to check the filter.
64
+ if (typeof e.filter !== 'undefined') {
65
+ this.buildTokens(e.filter, evt, toks, e, data[0]);
66
+ if (eval(this.replaceTokens(e.filter, toks)) === false) continue;
67
+ }
68
+ // Look for the processor.
69
+ this.executeProcessor(evt, e, ...data);
70
+ }
71
+ }
72
+ }
73
+ }
74
+ }
75
+ class RuleInterfaceEvent extends InterfaceEvent {
76
+ event: string;
77
+ description: string;
78
+ fnProcessor: (rule: RuleInterfaceEvent, options:any, vars: any, logger: any, webApp: any, sys: PoolSystem, state: State, data: any) => void;
79
+ processorBound: boolean = false;
80
+ }
81
+ export interface IRuleInterfaceEvent {
82
+ event: string,
83
+ description: string,
84
+ processor?: string
85
+ }
86
+
87
+
@@ -1,5 +1,6 @@
1
1
  /* nodejs-poolController. An application to control pool equipment.
2
- Copyright (C) 2016, 2017, 2018, 2019, 2020. Russell Goldin, tagyoureit. russ.goldin@gmail.com
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 * as path from "path";
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) {
@@ -62,12 +65,49 @@ export class ConfigRoute {
62
65
  };
63
66
  return res.status(200).send(opts);
64
67
  });
65
- app.get('/config/options/rs485', (req, res) => {
66
- let opts = {
67
- port: config.getSection('controller.comms', { enabled: false, netConnect: false }),
68
- stats: conn.buffer.counter
69
- };
70
- return res.status(200).send(opts);
68
+ app.get('/config/options/rs485', async (req, res, next) => {
69
+ try {
70
+ let opts = { ports: [], local: [], screenlogic: {} }
71
+ let cfg = config.getSection('controller');
72
+ for (let section in cfg) {
73
+ if (section.startsWith('comms')) {
74
+ let cport = extend(true, { enabled: false, netConnect: false, mock: false }, cfg[section]);
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
+ }
79
+ if (typeof port !== 'undefined') cport.stats = port.stats;
80
+ if (port.portId === 0 && port.type === 'screenlogic') {
81
+ cport.screenlogic.stats = sl.stats;
82
+ }
83
+ opts.ports.push(cport);
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
+ // }
91
+ }
92
+ opts.local = await conn.getLocalPortsAsync() || [];
93
+ return res.status(200).send(opts);
94
+ } catch (err) { next(err); }
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); }
71
111
  });
72
112
  app.get('/config/options/circuits', async (req, res, next) => {
73
113
  try {
@@ -156,7 +196,8 @@ export class ConfigRoute {
156
196
  circuits: sys.board.circuits.getCircuitReferences(true, true, true, true),
157
197
  bodies: sys.board.valueMaps.pumpBodies.toArray(),
158
198
  pumps: sys.pumps.get(),
159
- servers: await sys.ncp.getREMServers()
199
+ servers: await sys.ncp.getREMServers(),
200
+ rs485ports: await conn.listInstalledPorts()
160
201
  };
161
202
  // RKS: Why do we need the circuit names? We have the circuits. Is this so
162
203
  // that we can name the pump. I thought that *Touch uses the pump type as the name
@@ -203,7 +244,8 @@ export class ConfigRoute {
203
244
  heaterTypes: sys.board.valueMaps.heaterTypes.toArray(),
204
245
  heatModes: sys.board.valueMaps.heatModes.toArray(),
205
246
  coolDownDelay: sys.general.options.cooldownDelay,
206
- servers: []
247
+ servers: [],
248
+ rs485ports: await conn.listInstalledPorts()
207
249
  };
208
250
  // We only need the servers data when the controller is a Nixie controller. We don't need to
209
251
  // wait for this information if we are dealing with an OCP.
@@ -258,12 +300,34 @@ export class ConfigRoute {
258
300
  warnings,
259
301
  // waterFlow: sys.board.valueMaps.chemControllerWaterFlow.toArray(), // remove
260
302
  controllers: sys.chemControllers.get(),
261
- maxChemControllers: sys.equipment.maxChemControllers
303
+ maxChemControllers: sys.equipment.maxChemControllers,
304
+ doserTypes: sys.board.valueMaps.chemDoserTypes.toArray()
262
305
  };
263
306
  return res.status(200).send(opts);
264
307
  }
265
308
  catch (err) { next(err); }
266
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
+
267
331
  app.get('/config/options/rem', async (req, res, next) => {
268
332
  try {
269
333
  let opts = {
@@ -283,16 +347,32 @@ export class ConfigRoute {
283
347
  return res.status(200).send(opts);
284
348
  } catch (err) { next(err); }
285
349
  });
286
- app.get('/config/options/chlorinators', (req, res) => {
287
- let opts = {
288
- types: sys.board.valueMaps.chlorinatorType.toArray(),
289
- bodies: sys.board.bodies.getBodyAssociations(),
290
- chlorinators: sys.chlorinators.get(),
291
- maxChlorinators: sys.equipment.maxChlorinators,
292
- models: sys.board.valueMaps.chlorinatorModel.toArray(),
293
- equipmentMasters: sys.board.valueMaps.equipmentMaster.toArray()
294
- };
295
- return res.status(200).send(opts);
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
+ });
363
+ app.get('/config/options/chlorinators', async (req, res, next) => {
364
+ try {
365
+ let opts = {
366
+ types: sys.board.valueMaps.chlorinatorType.toArray(),
367
+ bodies: sys.board.bodies.getBodyAssociations(),
368
+ chlorinators: sys.chlorinators.get(),
369
+ maxChlorinators: sys.equipment.maxChlorinators,
370
+ models: sys.board.valueMaps.chlorinatorModel.toArray(),
371
+ equipmentMasters: sys.board.valueMaps.equipmentMaster.toArray(),
372
+ rs485ports: await conn.listInstalledPorts()
373
+ };
374
+ return res.status(200).send(opts);
375
+ } catch (err) { next(err); }
296
376
  });
297
377
  app.get('/config/options/dateTime', (req, res) => {
298
378
  let opts = {
@@ -310,25 +390,6 @@ export class ConfigRoute {
310
390
  let opts = config.getSection();
311
391
  return res.status(200).send(opts);
312
392
  });
313
- app.get('/app/options/interfaces', (req, res) => {
314
- // todo: move bytevaluemaps out to a proper location; add additional definitions
315
- let opts = {
316
- interfaces: config.getSection('web.interfaces'),
317
- types: [
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' }
323
- ],
324
- protocols: [
325
- { val: 0, name: 'http://', desc: 'http://' },
326
- { val: 1, name: 'https://', desc: 'https://' },
327
- { val: 2, name: 'mqtt://', desc: 'mqtt://' }
328
- ]
329
- }
330
- return res.status(200).send(opts);
331
- });
332
393
  app.get('/config/options/tempSensors', (req, res) => {
333
394
  let opts = {
334
395
  tempUnits: sys.board.valueMaps.tempUnits.toArray(),
@@ -386,6 +447,13 @@ export class ConfigRoute {
386
447
  return res.status(200).send(controller.get(true));
387
448
  } catch (err) { next(err); }
388
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
+ });
389
457
  app.delete('/config/filter', async (req, res, next) => {
390
458
  try {
391
459
  let sfilter = await sys.board.filters.deleteFilterAsync(req.body);
@@ -507,6 +575,18 @@ export class ConfigRoute {
507
575
  }
508
576
  catch (err) { next(err); }
509
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
+ //});
510
590
  app.delete('/config/pump', async (req, res, next) => {
511
591
  try {
512
592
  let pump = await sys.board.pumps.deletePumpAsync(req.body);
@@ -624,14 +704,6 @@ export class ConfigRoute {
624
704
  next(err);
625
705
  }
626
706
  });
627
- app.delete('/config/pump/:pumpId', (req, res) => {
628
- let pump = sys.pumps.getItemById(parseInt(req.params.pumpId, 10));
629
- if (pump.type === 0) {
630
- return res.status(500).send(`Pump ${pump.id} not active`);
631
- }
632
- pump.setType(0);
633
- return res.status(200).send('OK');
634
- });
635
707
  app.put('/config/dateTime', async (req, res, next) => {
636
708
  try {
637
709
  let time = await sys.updateControllerDateTimeAsync(req.body);
@@ -692,6 +764,28 @@ export class ConfigRoute {
692
764
  }
693
765
  catch (err) { next(err); }
694
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
+ });
695
789
  app.put('/config/chemController/feed', async (req, res, next) => {
696
790
  try {
697
791
  let chem = await sys.board.chemControllers.setChemControllerAsync(req.body);
@@ -705,8 +799,16 @@ export class ConfigRoute {
705
799
  return res.status(200).send(chem.get());
706
800
  }
707
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); }
708
809
 
709
810
  });
811
+
710
812
  /* app.get('/config/intellibrite', (req, res) => {
711
813
  return res.status(200).send(sys.intellibrite.getExtended());
712
814
  });
@@ -756,6 +858,20 @@ export class ConfigRoute {
756
858
  }
757
859
  catch (err) { next(err); }
758
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
+ // });
868
+ app.delete('/app/rs485Port', async (req, res, next) => {
869
+ try {
870
+ let port = await conn.deleteAuxPort(req.body);
871
+ return res.status(200).send(port);
872
+ }
873
+ catch (err) { next(err); }
874
+ });
759
875
  app.get('/app/config/startPacketCapture', (req, res) => {
760
876
  startPacketCapture(true);
761
877
  return res.status(200).send('OK');
@@ -888,5 +1004,17 @@ export class ConfigRoute {
888
1004
  return res.status(200).send(results);
889
1005
  } catch (err) { next(err); }
890
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
+ });
891
1019
  }
892
1020
  }
@@ -1,5 +1,6 @@
1
1
  /* nodejs-poolController. An application to control pool equipment.
2
- Copyright (C) 2016, 2017, 2018, 2019, 2020. Russell Goldin, tagyoureit. russ.goldin@gmail.com
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