nodejs-poolcontroller 7.7.0 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/.eslintrc.json +26 -35
  2. package/Changelog +22 -0
  3. package/README.md +7 -3
  4. package/anslq25/MessagesMock.ts +218 -0
  5. package/anslq25/boards/MockBoardFactory.ts +50 -0
  6. package/anslq25/boards/MockEasyTouchBoard.ts +696 -0
  7. package/anslq25/boards/MockSystemBoard.ts +217 -0
  8. package/anslq25/chemistry/MockChlorinator.ts +75 -0
  9. package/anslq25/pumps/MockPump.ts +84 -0
  10. package/app.ts +10 -14
  11. package/config/Config.ts +13 -9
  12. package/config/VersionCheck.ts +6 -2
  13. package/controller/Constants.ts +58 -25
  14. package/controller/Equipment.ts +225 -41
  15. package/controller/Errors.ts +2 -1
  16. package/controller/Lockouts.ts +34 -2
  17. package/controller/State.ts +491 -48
  18. package/controller/boards/AquaLinkBoard.ts +6 -3
  19. package/controller/boards/BoardFactory.ts +5 -1
  20. package/controller/boards/EasyTouchBoard.ts +1971 -1751
  21. package/controller/boards/IntelliCenterBoard.ts +1311 -1688
  22. package/controller/boards/IntelliComBoard.ts +7 -1
  23. package/controller/boards/IntelliTouchBoard.ts +153 -42
  24. package/controller/boards/NixieBoard.ts +209 -66
  25. package/controller/boards/SunTouchBoard.ts +393 -0
  26. package/controller/boards/SystemBoard.ts +1862 -1543
  27. package/controller/comms/Comms.ts +539 -138
  28. package/controller/comms/ScreenLogic.ts +1663 -0
  29. package/controller/comms/messages/Messages.ts +242 -60
  30. package/controller/comms/messages/config/ChlorinatorMessage.ts +4 -3
  31. package/controller/comms/messages/config/CircuitGroupMessage.ts +5 -2
  32. package/controller/comms/messages/config/CircuitMessage.ts +81 -13
  33. package/controller/comms/messages/config/ConfigMessage.ts +3 -1
  34. package/controller/comms/messages/config/CoverMessage.ts +2 -1
  35. package/controller/comms/messages/config/CustomNameMessage.ts +2 -1
  36. package/controller/comms/messages/config/EquipmentMessage.ts +5 -1
  37. package/controller/comms/messages/config/ExternalMessage.ts +33 -3
  38. package/controller/comms/messages/config/FeatureMessage.ts +2 -1
  39. package/controller/comms/messages/config/GeneralMessage.ts +2 -1
  40. package/controller/comms/messages/config/HeaterMessage.ts +3 -1
  41. package/controller/comms/messages/config/IntellichemMessage.ts +2 -1
  42. package/controller/comms/messages/config/OptionsMessage.ts +12 -6
  43. package/controller/comms/messages/config/PumpMessage.ts +9 -12
  44. package/controller/comms/messages/config/RemoteMessage.ts +80 -13
  45. package/controller/comms/messages/config/ScheduleMessage.ts +43 -3
  46. package/controller/comms/messages/config/SecurityMessage.ts +2 -1
  47. package/controller/comms/messages/config/ValveMessage.ts +43 -26
  48. package/controller/comms/messages/status/ChlorinatorStateMessage.ts +8 -7
  49. package/controller/comms/messages/status/EquipmentStateMessage.ts +93 -20
  50. package/controller/comms/messages/status/HeaterStateMessage.ts +24 -5
  51. package/controller/comms/messages/status/IntelliChemStateMessage.ts +7 -4
  52. package/controller/comms/messages/status/IntelliValveStateMessage.ts +2 -1
  53. package/controller/comms/messages/status/PumpStateMessage.ts +72 -4
  54. package/controller/comms/messages/status/VersionMessage.ts +2 -1
  55. package/controller/nixie/Nixie.ts +15 -4
  56. package/controller/nixie/NixieEquipment.ts +1 -0
  57. package/controller/nixie/chemistry/ChemController.ts +300 -129
  58. package/controller/nixie/chemistry/ChemDoser.ts +806 -0
  59. package/controller/nixie/chemistry/Chlorinator.ts +133 -129
  60. package/controller/nixie/circuits/Circuit.ts +171 -30
  61. package/controller/nixie/heaters/Heater.ts +337 -173
  62. package/controller/nixie/pumps/Pump.ts +264 -236
  63. package/controller/nixie/schedules/Schedule.ts +9 -3
  64. package/defaultConfig.json +46 -5
  65. package/logger/Logger.ts +38 -9
  66. package/package.json +13 -9
  67. package/web/Server.ts +235 -122
  68. package/web/bindings/aqualinkD.json +114 -59
  69. package/web/bindings/homeassistant.json +437 -0
  70. package/web/bindings/influxDB.json +15 -0
  71. package/web/bindings/mqtt.json +28 -9
  72. package/web/bindings/mqttAlt.json +15 -0
  73. package/web/interfaces/baseInterface.ts +58 -7
  74. package/web/interfaces/httpInterface.ts +5 -2
  75. package/web/interfaces/influxInterface.ts +9 -2
  76. package/web/interfaces/mqttInterface.ts +234 -74
  77. package/web/interfaces/ruleInterface.ts +87 -0
  78. package/web/services/config/Config.ts +140 -33
  79. package/web/services/config/ConfigSocket.ts +2 -1
  80. package/web/services/state/State.ts +144 -3
  81. package/web/services/state/StateSocket.ts +65 -14
  82. package/web/services/utilities/Utilities.ts +189 -1
@@ -1,5 +1,6 @@
1
1
  /* nodejs-poolController. An application to control pool equipment.
2
- Copyright (C) 2016, 2017, 2018, 2019, 2020. 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
@@ -14,12 +15,51 @@ GNU Affero General Public License for more details.
14
15
  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
- import { Inbound } from "../Messages";
18
+ import { Inbound, Outbound, Protocol } from "../Messages";
18
19
  import { state } from "../../../State";
19
20
  import { sys, ControllerType } from "../../../Equipment";
21
+ import { conn } from "../../Comms";
22
+ import { logger } from "../../../../logger/Logger";
23
+
20
24
  export class PumpStateMessage {
25
+ private static detectPumpType(msg: Inbound) {
26
+ let pumpType = -1;
27
+ switch (msg.action) {
28
+ case 1:
29
+ {
30
+ let speed = (msg.extractPayloadByte(2) * 256) + msg.extractPayloadByte(3);
31
+ if (speed > 0) {
32
+ pumpType = speed < 300 ? sys.board.valueMaps.pumpTypes.getValue('vf') : sys.board.valueMaps.pumpTypes.getValue('vs');
33
+ }
34
+ }
35
+ break;
36
+ case 9:
37
+ case 10:
38
+ pumpType = sys.board.valueMaps.pumpTypes.getValue('vsf');
39
+ break;
40
+ }
41
+ if (pumpType > 0) {
42
+ let pump = sys.pumps.find(x => x.address === msg.dest);
43
+ if (typeof pump === 'undefined') {
44
+ let id = sys.pumps.filter(elem => elem.master === 0).getMaxId(false, 0) + 1;
45
+ pump = sys.pumps.getItemById(id, true);
46
+ pump.name = `Pump ${msg.dest - 95}`;
47
+ pump.address = msg.dest;
48
+ pump.isActive = true;
49
+ pump.type = pumpType;
50
+ pump.master = 0;
51
+ }
52
+ let spump = state.pumps.getItemById(pump.id, true);
53
+ spump.address = pump.address;
54
+ spump.type = pump.type;
55
+ spump.isActive = pump.isActive;
56
+ spump.name = pump.name;
57
+ spump.type = pump.type;
58
+ }
59
+ }
21
60
  public static process(msg: Inbound) {
22
61
  if (sys.controllerType === ControllerType.Unknown) return;
62
+ if (msg.dest >= 96 && sys.controllerType === ControllerType.SunTouch) PumpStateMessage.detectPumpType(msg);
23
63
 
24
64
  // We only want to process the messages that are coming from the pump not to the pump. At some point
25
65
  // this filter was removed. Any messages that are coming from the panel are simply requests to the pump
@@ -33,6 +73,29 @@ export class PumpStateMessage {
33
73
  let ptype = sys.board.valueMaps.pumpTypes.transform(pumpCfg.type);
34
74
  let pump = state.pumps.getItemById(pumpId, pumpCfg.isActive === true);
35
75
  switch (msg.action) {
76
+ case 1:
77
+ if (msg.source === 96 && sys.controllerType === ControllerType.EasyTouch) {
78
+ if (sys.equipment.modules.getItemByIndex(0, false).type >= 128) {
79
+ // EasyTouch Version 1 controllers do not request the current information about rpms or wattage from the pump. We need to ask in
80
+ // its stead.
81
+ let out = Outbound.create({
82
+ portId: pumpCfg.portId || 0,
83
+ protocol: Protocol.Pump,
84
+ dest: pumpCfg.address,
85
+ action: 7,
86
+ payload: [],
87
+ retries: 1,
88
+ response: true,
89
+ onComplete: (err, _) => {
90
+ if (err) {
91
+ logger.error(`EasyTouch 1 request pump status failed for ${pump.name}: ${err.message}`);
92
+ }
93
+ }
94
+ });
95
+ conn.queueSendMessage(out);
96
+ }
97
+ }
98
+ break;
36
99
  case 7:
37
100
  //[165, 63, 15, 16, 2, 29][11, 47, 32, 0, 0, 0, 0, 0, 0, 32, 0, 0, 2, 0, 59, 59, 0, 241, 56, 121, 24, 246, 0, 0, 0, 0, 0, 23, 0][4, 219]
38
101
  //[165, 0, 96, 16, 1, 4][2, 196, 7, 58][2, 33]
@@ -57,7 +120,7 @@ export class PumpStateMessage {
57
120
  }
58
121
  public static processHayward(msg: Inbound) {
59
122
  switch (msg.action) {
60
- case 12:
123
+ case 12: // This is a pump status message
61
124
  PumpStateMessage.processHaywardStar(msg);
62
125
  break;
63
126
  }
@@ -67,7 +130,10 @@ export class PumpStateMessage {
67
130
  //[0x10, 0x02, 0x00, 0x0C, 0x00][0x00, 0x62, 0x17, 0x81][0x01, 0x18, 0x10, 0x03]
68
131
  //[0x10, 0x02, 0x00, 0x0C, 0x00][0x00, 0x2D, 0x02, 0x36][0x00, 0x83, 0x10, 0x03] -- Response from pump
69
132
  let ptype = sys.board.valueMaps.pumpTypes.transformByName('hwvs');
70
- let pump = sys.pumps.find(elem => elem.address === msg.source + 96 && elem.type === 6);
133
+ let address = msg.source + 96;
134
+ //console.log({ src: msg.source, dest: msg.dest, action: msg.action, address: address });
135
+
136
+ let pump = sys.pumps.find(elem => elem.address === address && elem.type === 6);
71
137
  if (typeof pump !== 'undefined') {
72
138
  let pstate = state.pumps.getItemById(pump.id, true);
73
139
  // 3450 * .5
@@ -75,6 +141,8 @@ export class PumpStateMessage {
75
141
  // This is really goofy as the watts are actually the hex string from the two bytes.
76
142
  pstate.watts = parseInt(msg.extractPayloadByte(2).toString(16) + msg.extractPayloadByte(3).toString(16), 10);
77
143
  pstate.isActive = true;
144
+ pstate.command = (pstate.rpm > 0 || pstate.watts > 0) ? 10 : 0;
145
+ pstate.driveState
78
146
  state.emitEquipmentChanges();
79
147
  }
80
148
  }
@@ -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
@@ -5,6 +5,7 @@ import { webApp } from "../../web/Server";
5
5
  import { logger } from "../../logger/Logger";
6
6
  import { INixieControlPanel } from "./NixieEquipment";
7
7
  import { NixieChemControllerCollection } from "./chemistry/ChemController";
8
+ import { NixieChemDoserCollection } from "./chemistry/ChemDoser";
8
9
 
9
10
  import { sys, PoolSystem } from "../../controller/Equipment";
10
11
  import { NixieCircuitCollection } from './circuits/Circuit';
@@ -55,6 +56,7 @@ export class NixieControlPanel implements INixieControlPanel {
55
56
  // Only equipment controlled by Nixie is represented on the controller. If interaction with
56
57
  // other equipment is required this should be sent back through the original controller.
57
58
  // Command sequence is <OCP>Board -> SystemBoard -> NixieController whenever the master is not identified as Nixie.
59
+ chemDosers: NixieChemDoserCollection = new NixieChemDoserCollection(this);
58
60
  chemControllers: NixieChemControllerCollection = new NixieChemControllerCollection(this);
59
61
  chlorinators: NixieChlorinatorCollection = new NixieChlorinatorCollection(this);
60
62
  circuits: NixieCircuitCollection = new NixieCircuitCollection(this);
@@ -64,7 +66,14 @@ export class NixieControlPanel implements INixieControlPanel {
64
66
  heaters: NixieHeaterCollection = new NixieHeaterCollection(this);
65
67
  pumps: NixiePumpCollection = new NixiePumpCollection(this);
66
68
  schedules: NixieScheduleCollection = new NixieScheduleCollection(this);
67
-
69
+ public async setServiceModeAsync() {
70
+ await this.circuits.setServiceModeAsync();
71
+ await this.heaters.setServiceModeAsync();
72
+ await this.chlorinators.setServiceModeAsync();
73
+ await this.chemControllers.setServiceModeAsync();
74
+ await this.chemDosers.setServiceModeAsync();
75
+ await this.pumps.setServiceModeAsync();
76
+ }
68
77
  public async initAsync(equipment: PoolSystem) {
69
78
  try {
70
79
 
@@ -80,6 +89,7 @@ export class NixieControlPanel implements INixieControlPanel {
80
89
  await this.heaters.initAsync(equipment.heaters);
81
90
  await this.chlorinators.initAsync(equipment.chlorinators);
82
91
  await this.chemControllers.initAsync(equipment.chemControllers);
92
+ await this.chemDosers.initAsync(equipment.chemDosers);
83
93
  await this.pumps.initAsync(equipment.pumps);
84
94
  await this.schedules.initAsync(equipment.schedules);
85
95
  logger.info(`Nixie Controller Initialized`)
@@ -97,7 +107,7 @@ export class NixieControlPanel implements INixieControlPanel {
97
107
  lines = buff.toString().split('\n');
98
108
  }
99
109
  return lines;
100
- } catch (err) { logger.error(err); }
110
+ } catch (err) { logger.error(`Error reading log file ${logFile}: ${err.message}`); }
101
111
  }
102
112
  public async logData(logFile: string, data: any) {
103
113
  try {
@@ -114,10 +124,11 @@ export class NixieControlPanel implements INixieControlPanel {
114
124
  else
115
125
  lines.unshift(data.toString());
116
126
  fs.writeFileSync(logPath, lines.join('\n'));
117
- } catch (err) { logger.error(err); }
127
+ } catch (err) { logger.error(`Error logging to ${logFile}: ${err.message}`); }
118
128
  }
119
129
  public async closeAsync() {
120
130
  // Close all the associated equipment.
131
+ await this.chemDosers.closeAsync();
121
132
  await this.chemControllers.closeAsync();
122
133
  await this.chlorinators.closeAsync();
123
134
  await this.heaters.closeAsync();
@@ -156,7 +167,7 @@ export class NixieControlPanel implements INixieControlPanel {
156
167
  await ncp.chemControllers.syncRemoteREMFeeds(srv);
157
168
  }
158
169
  return srv;
159
- } catch (err) { logger.error(err); }
170
+ } catch (err) { logger.error(`Error gettting REM Servers: ${err.message}`); }
160
171
  }
161
172
  }
162
173
 
@@ -86,6 +86,7 @@ export class NixieEquipmentCollection<T> extends Array<NixieEquipment> {
86
86
  let eq = this[ndx];
87
87
  await eq.closeAsync();
88
88
  this.splice(ndx, 1);
89
+ logger.info(`Removing chem doser id# ${id} at index ndx`);
89
90
  }
90
91
  else
91
92
  logger.warn(`A Nixie equipment item was not found with id ${id}. Equipment not removed.`);