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
@@ -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
@@ -28,11 +29,12 @@ export class ChlorinatorMessage {
28
29
  for (let i = 0; i < 4 && i + 30 < msg.payload.length; i++) {
29
30
  let isActive = msg.extractPayloadByte(i + 22) === 1;
30
31
  chlor = sys.chlorinators.getItemById(chlorId);
31
- if (chlor.master === 1) continue; // RSG: probably never need this. See Touch chlor below.
32
+ if (chlor.master !== 0) continue; // RSG: probably never need this. See Touch chlor below.
32
33
  if (isActive) {
33
34
  chlor = sys.chlorinators.getItemById(chlorId, true);
34
35
  let schlor = state.chlorinators.getItemById(chlor.id, true);
35
36
  chlor.isActive = schlor.isActive = true;
37
+ chlor.master = 0;
36
38
  chlor.body = msg.extractPayloadByte(i + 2);
37
39
  chlor.type = msg.extractPayloadByte(i + 6);
38
40
  if (!chlor.disabled && !chlor.isDosing) {
@@ -51,6 +53,7 @@ export class ChlorinatorMessage {
51
53
  schlor.poolSetpoint = chlor.poolSetpoint;
52
54
  schlor.spaSetpoint = chlor.spaSetpoint;
53
55
  schlor.type = chlor.type;
56
+ schlor.model = chlor.model;
54
57
  schlor.isActive = chlor.isActive;
55
58
  schlor.superChlorHours = chlor.superChlorHours;
56
59
  state.emitEquipmentChanges();
@@ -69,9 +72,10 @@ export class ChlorinatorMessage {
69
72
  }
70
73
  }
71
74
  public static processTouch(msg: Inbound) {
75
+ //[255, 0, 255][165, 1, 15, 16, 25, 22][1, 90, 128, 58, 128, 0, 73, 110, 116, 101, 108, 108, 105, 99, 104, 108, 111, 114, 45, 45, 54, 48][8, 50]
72
76
  // This is for the 25 message that is broadcast from the OCP.
73
77
  let chlor = sys.chlorinators.getItemById(1);
74
- if (chlor.master === 1) return; // Some Aquarite chlors need more frequent control (via Nixie) but will be disabled via Touch. https://github.com/tagyoureit/nodejs-poolController/issues/349
78
+ if (chlor.master !== 0 && typeof chlor.master !== 'undefined') return; // Some Aquarite chlors need more frequent control (via Nixie) but will be disabled via Touch. https://github.com/tagyoureit/nodejs-poolController/issues/349
75
79
  let isActive = (msg.extractPayloadByte(0) & 0x01) === 1;
76
80
  if (isActive) {
77
81
  let chlor = sys.chlorinators.getItemById(1, true);
@@ -82,7 +86,7 @@ export class ChlorinatorMessage {
82
86
  // chlorinator. These should be 0 anyway.
83
87
  schlor.spaSetpoint = chlor.spaSetpoint = msg.extractPayloadByte(0) >> 1;
84
88
  schlor.poolSetpoint = chlor.poolSetpoint = msg.extractPayloadByte(1);
85
- chlor.address = chlor.id + 79;
89
+ chlor.address = msg.dest;
86
90
  schlor.body = chlor.body = sys.equipment.maxBodies >= 1 || sys.equipment.shared === true ? 32 : 0;
87
91
  }
88
92
  if (typeof chlor.name === 'undefined') schlor.name = chlor.name = msg.extractPayloadString(6, 16);
@@ -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
@@ -113,7 +114,8 @@ export class CircuitGroupMessage {
113
114
  group.nameId = sgroup.nameId = feature.nameId;
114
115
  group.type = sgroup.type = sys.board.valueMaps.circuitGroupTypes.getValue('circuit');
115
116
  group.isActive = _isActive;
116
- if (typeof group.showInFeatures === 'undefined') sgroup.showInFeatures = group.showInFeatures = true;
117
+ if (typeof group.showInFeatures === 'undefined') group.showInFeatures = true;
118
+ sgroup.showInFeatures = group.showInFeatures;
117
119
  let circuits: CircuitGroupCircuitCollection = group.circuits;
118
120
  for (let byte = 1; byte <= 7; byte++){
119
121
  let offByte = msg.extractPayloadByte(byte);
@@ -189,6 +191,7 @@ export class CircuitGroupMessage {
189
191
  group.isActive = sgroup.isActive = true;
190
192
  if (typeof group.showInFeatures === 'undefined') group.showInFeatures = true;
191
193
  sgroup.type = group.type;
194
+ sgroup.showInFeatures = group.showInFeatures;
192
195
  }
193
196
  state.emitEquipmentChanges();
194
197
  msg.isProcessed = true;
@@ -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
@@ -18,12 +19,13 @@ import { Inbound } from "../Messages";
18
19
  import { sys, Body, Circuit, ICircuit } from "../../../Equipment";
19
20
  import { state, BodyTempState } from "../../../State";
20
21
  import { logger } from "../../../../logger/Logger";
22
+ import { ControllerType } from "../../../Constants";
21
23
 
22
24
  export class CircuitMessage {
23
25
  public static processTouch(msg: Inbound): void {
24
26
  switch (msg.action) {
25
27
  case 11: // IntelliTouch Circuits
26
- CircuitMessage.processCircuitAttributes(msg);
28
+ sys.controllerType === ControllerType.SunTouch ? CircuitMessage.processSunTouchCircuit(msg) : CircuitMessage.processCircuitAttributes(msg);
27
29
  break;
28
30
  case 39: // IntelliTouch Light Groups
29
31
  case 167:
@@ -153,7 +155,13 @@ export class CircuitMessage {
153
155
  let circuit: Circuit = sys.circuits.getItemById(circuitId++, true);
154
156
 
155
157
  // For some odd reason the circuit type for circuit 6 does not equal pool while circuit 1 does equal spa.
156
- circuit.type = circuitId - 1 !== 6 ? msg.extractPayloadByte(i) : 12;
158
+ // Apparently in later versions, spa does not do this either
159
+ if (circuit.id === 1)
160
+ circuit.type = 13
161
+ else if (circuit.id == 6)
162
+ circuit.type = 12
163
+ else
164
+ circuit.type = msg.extractPayloadByte(i);
157
165
  circuit.isActive = true;
158
166
  circuit.master = 0;
159
167
  }
@@ -175,7 +183,8 @@ export class CircuitMessage {
175
183
  let maxCircuitId = sys.board.equipmentIds.circuits.end;
176
184
  for (let i = circuitId + 1; i < msg.payload.length && circuitId <= maxCircuitId; i++) {
177
185
  let circuit: Circuit = sys.circuits.getItemById(circuitId++, true);
178
- circuit.showInFeatures = msg.extractPayloadByte(i) > 0;
186
+ let cstate = state.circuits.getItemById(circuit.id, true);
187
+ cstate.showInFeatures = circuit.showInFeatures = msg.extractPayloadByte(i) > 0;
179
188
  }
180
189
  msg.isProcessed = true;
181
190
  }
@@ -230,7 +239,49 @@ export class CircuitMessage {
230
239
  }
231
240
  msg.isProcessed = true;
232
241
  }
233
-
242
+ // SunTouch
243
+ private static processSunTouchCircuit(msg: Inbound) {
244
+ let id = msg.extractPayloadByte(0);
245
+ // We need to remap the SunTouch circuits because the features start with 5.
246
+ // SunTouch bit mapping for circuits and features
247
+ // Bit Mask Circuit/Feature id msg
248
+ // 1 = 0x01 Spa 1 1
249
+ // 2 = 0x02 Aux 1 2 2
250
+ // 3 = 0x04 Aux 2 3 3
251
+ // 4 = 0x08 Aux 3 4 4
252
+ // 5 = 0x10 Feature 1 7 5
253
+ // 6 = 0x20 Pool 6 6
254
+ // 7 = 0x40 Feature 2 8 7
255
+ // 8 = 0x80 Feature 3 9 8
256
+ // 9 = 0x01 Feature 4 10 9
257
+ if ([5, 7, 8, 9].includes(id)) {
258
+ id = id === 5 ? 7 : id + 1;
259
+ let feat = sys.features.getItemById(id, true);
260
+ let fstate = state.features.getItemById(id, true);
261
+ fstate.isActive = feat.isActive = true;
262
+ feat.master = 0;
263
+ fstate.nameId = feat.nameId = msg.extractPayloadByte(2);
264
+ fstate.type = feat.type = msg.extractPayloadByte(1) & 63;
265
+ feat.freeze = (msg.extractPayloadByte(1) & 64) > 0;
266
+ feat.showInFeatures = fstate.showInFeatures = typeof feat.showInFeatures === 'undefined' ? true : feat.showInFeatures;
267
+ if (typeof feat.eggTimer === 'undefined' || feat.eggTimer === 0) feat.eggTimer = 720;
268
+ if (typeof feat.dontStop === 'undefined') feat.dontStop = feat.eggTimer === 1620;
269
+ if (typeof feat.name === 'undefined') feat.name = fstate.name = sys.board.valueMaps.circuitNames.transform(feat.nameId).desc;
270
+ }
271
+ else if ([1, 2, 3, 4, 6].includes(id)) {
272
+ let circ = sys.circuits.getItemById(id, true);
273
+ let cstate = state.circuits.getItemById(id, true);
274
+ cstate.isActive = circ.isActive = true;
275
+ circ.master = 0;
276
+ cstate.nameId = circ.nameId = msg.extractPayloadByte(2);
277
+ cstate.type = circ.type = msg.extractPayloadByte(1) & 63;
278
+ circ.freeze = (msg.extractPayloadByte(1) & 64) > 0;
279
+ circ.showInFeatures = cstate.showInFeatures = typeof circ.showInFeatures === 'undefined' ? true : circ.showInFeatures;
280
+ if (typeof circ.eggTimer === 'undefined' || circ.eggTimer === 0) circ.eggTimer = 720;
281
+ if (typeof circ.dontStop === 'undefined') circ.dontStop = circ.eggTimer === 1620;
282
+ if (typeof circ.name === 'undefined') circ.name = cstate.name = sys.board.valueMaps.circuitNames.transform(circ.nameId).desc;
283
+ }
284
+ }
234
285
  // Intellitouch
235
286
  private static processCircuitAttributes(msg: Inbound) {
236
287
  // Sample packet
@@ -238,11 +289,12 @@ export class CircuitMessage {
238
289
  const id = msg.extractPayloadByte(0);
239
290
  const functionId = msg.extractPayloadByte(1);
240
291
  const nameId = msg.extractPayloadByte(2);
241
- let _isActive = functionId !== sys.board.valueMaps.circuitFunctions.getValue('notused') && nameId !== 0;
292
+ let _isActive = functionId !== sys.board.valueMaps.circuitFunctions.getValue('notused') && (nameId !== 0 || sys.controllerType === ControllerType.SunTouch);
242
293
  if (!sys.board.equipmentIds.invalidIds.isValidId(id)) { _isActive = false; }
243
294
  if (_isActive) {
244
295
  const type = functionId & 63;
245
296
  let circuit: ICircuit = sys.circuits.getInterfaceById(id, _isActive);
297
+ circuit.master = 0;
246
298
  circuit.name = sys.board.circuits.getNameById(nameId);
247
299
  circuit.nameId = nameId;
248
300
  circuit.type = type;
@@ -271,14 +323,14 @@ export class CircuitMessage {
271
323
  case 6: // pool
272
324
  body = sys.bodies.getItemById(1, sys.equipment.maxBodies > 0);
273
325
  sbody = state.temps.bodies.getItemById(1, sys.equipment.maxBodies > 0);
274
- sbody.name = body.name = "Pool";
326
+ if (typeof body.name === 'undefined') sbody.name = body.name = "Pool";
275
327
  sbody.type = body.type = 0; // RKS: The body types were backwards here but correct everywhere else e.g. PumpMessage.
276
328
  circuit.type === 2 ? body.isActive = true : body.isActive = false;
277
329
  break;
278
330
  case 1: // spa
279
331
  body = sys.bodies.getItemById(2, sys.equipment.maxBodies > 1);
280
- sbody = state.temps.bodies.getItemById(1, sys.equipment.maxBodies > 1);
281
- sbody.name = body.name = "Spa";
332
+ sbody = state.temps.bodies.getItemById(2, sys.equipment.maxBodies > 1);
333
+ if(typeof body.name === 'undefined') sbody.name = body.name = "Spa";
282
334
  sbody.type = body.type = 1;
283
335
  // process bodies - there might be a better place to do this but without other comparison packets from pools with expansion packs it is hard to determine
284
336
  // also, if we get this far spa should always be active. not sure if would ever not be active if we are here.
@@ -302,11 +354,28 @@ export class CircuitMessage {
302
354
  sys.lightGroups.removeItemById(sys.board.equipmentIds.circuitGroups.start);
303
355
  state.lightGroups.removeItemById(sys.board.equipmentIds.circuitGroups.start);
304
356
  }
305
- sys.features.removeItemById(id);
306
- state.features.removeItemById(id);
307
- sys.circuits.removeItemById(id);
308
- state.circuits.removeItemById(id);
357
+ if (!sys.board.equipmentIds.circuits.isInRange(id)) {
358
+ sys.circuits.removeItemById(id);
359
+ state.circuits.removeItemById(id);
360
+ }
361
+ else {
362
+ let circuit = sys.circuits.getItemById(id, true);
363
+ let cstate = sys.circuits.getItemById(id, true);
364
+ cstate.showInFeatures = circuit.showInFeatures = false;
365
+ cstate.type = circuit.type = functionId & 63;
366
+ cstate.name = circuit.name = sys.board.circuits.getNameById(nameId || id);
367
+ cstate.nameId = circuit.nameId = nameId || id;
368
+ cstate.isActive = circuit.isActive = true;
369
+ }
370
+ if (!sys.board.equipmentIds.features.isInRange(id)) {
371
+ sys.features.removeItemById(id);
372
+ state.features.removeItemById(id);
373
+ }
309
374
  sys.circuitGroups.removeItemById(id);
375
+ //sys.features.removeItemById(id);
376
+ //state.features.removeItemById(id);
377
+ //sys.circuits.removeItemById(id);
378
+ //state.circuits.removeItemById(id);
310
379
  }
311
380
  msg.isProcessed = true;
312
381
  }
@@ -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
@@ -103,6 +104,7 @@ export class ConfigMessage {
103
104
  }
104
105
  break;
105
106
  case ControllerType.EasyTouch:
107
+ case ControllerType.SunTouch:
106
108
  case ControllerType.IntelliCom:
107
109
  case ControllerType.IntelliTouch:
108
110
  // switch (msg.action) { }
@@ -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
@@ -1,31 +1,32 @@
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 { Inbound } from "../Messages";
18
- import { sys } from "../../../Equipment";
19
- export class CustomNameMessage
20
- {
21
- public static process ( msg: Inbound ): void
22
- {
23
- let customNameId = msg.extractPayloadByte( 0 );
24
- let customName = sys.customNames.getItemById( customNameId, customNameId <= sys.equipment.maxCustomNames );
25
- customName.name = msg.extractPayloadString( 1, 11 );
26
- // customName.isActive = customNameId <= sys.equipment.maxCustomNames && !customName.name.includes('USERNAME-')
27
- if (customNameId >= sys.equipment.maxCustomNames) sys.equipment.maxCustomNames = customNameId + 1;
28
- sys.board.system.syncCustomNamesValueMap();
29
- msg.isProcessed = true;
30
- }
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 { Inbound } from "../Messages";
19
+ import { sys } from "../../../Equipment";
20
+ export class CustomNameMessage
21
+ {
22
+ public static process ( msg: Inbound ): void
23
+ {
24
+ let customNameId = msg.extractPayloadByte( 0 );
25
+ let customName = sys.customNames.getItemById( customNameId, customNameId <= sys.equipment.maxCustomNames );
26
+ customName.name = msg.extractPayloadString( 1, 11 );
27
+ // customName.isActive = customNameId <= sys.equipment.maxCustomNames && !customName.name.includes('USERNAME-')
28
+ if (customNameId >= sys.equipment.maxCustomNames) sys.equipment.maxCustomNames = customNameId + 1;
29
+ sys.board.system.syncCustomNamesValueMap();
30
+ msg.isProcessed = true;
31
+ }
31
32
  }
@@ -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
@@ -131,7 +132,9 @@ export class EquipmentMessage {
131
132
  sys.bodies.removeItemById(bodyId);
132
133
  state.temps.bodies.removeItemById(bodyId);
133
134
  }
135
+ state.equipment.single = sys.equipment.single = sys.equipment.shared == false && sys.equipment.dual === false;
134
136
  state.equipment.shared = sys.equipment.shared;
137
+ state.equipment.dual = sys.equipment.dual;
135
138
  state.equipment.model = sys.equipment.model;
136
139
  state.equipment.controllerType = sys.controllerType;
137
140
  state.equipment.maxBodies = sys.equipment.maxBodies;
@@ -149,6 +152,7 @@ export class EquipmentMessage {
149
152
  case ControllerType.IntelliCom:
150
153
  case ControllerType.EasyTouch:
151
154
  case ControllerType.IntelliTouch:
155
+ case ControllerType.SunTouch:
152
156
  switch (msg.action) {
153
157
  case 252:
154
158
  EquipmentMessage.processSoftwareVersion(msg);
@@ -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
@@ -16,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17
  */
17
18
  import { Inbound } from "../Messages";
18
19
  import { sys, Body, ICircuitGroup, LightGroup, CircuitGroup } from "../../../Equipment";
19
- import { state, ICircuitGroupState, LightGroupState } from "../../../State";
20
+ import { state, ICircuitGroupState, LightGroupState, CircuitGroupState } from "../../../State";
20
21
  import { Timestamp, utils } from "../../../Constants";
21
22
  import { logger } from "../../../../logger/Logger";
22
23
  export class ExternalMessage {
@@ -208,6 +209,7 @@ export class ExternalMessage {
208
209
  sgroup = state.circuitGroups.getItemById(groupId, true);
209
210
  sgroup.type = group.type = type;
210
211
  if (typeof group.showInFeatures === 'undefined') group.showInFeatures = sgroup.showInFeatures = true;
212
+ sgroup.showInFeatures = group.showInFeatures;
211
213
  sys.lightGroups.removeItemById(groupId);
212
214
  state.lightGroups.removeItemById(groupId);
213
215
  sgroup.isActive = group.isActive = true;
@@ -274,6 +276,8 @@ export class ExternalMessage {
274
276
  private static processHeater(msg: Inbound) {
275
277
  // So a user is changing the heater info. Lets
276
278
  // hijack it and get it ourselves.
279
+ // Installing hybrid heater.
280
+ //[165, 63, 15, 16, 168, 30][10, 0, 2, 5, 32, 5, 6, 3, 0, 6, 112, 72, 121, 98, 114, 105, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1][4, 230]
277
281
  let isActive = msg.extractPayloadByte(3) !== 0;
278
282
  let heaterId = msg.extractPayloadByte(2) + 1;
279
283
  if (isActive) {
@@ -406,6 +410,7 @@ export class ExternalMessage {
406
410
  for (let j = 0; j < 8; j++) {
407
411
  let group = sys.circuitGroups.getInterfaceById(groupId);
408
412
  let gstate = group.type === 1 ? state.lightGroups.getItemById(groupId, group.isActive) : state.circuitGroups.getItemById(groupId, group.isActive);
413
+
409
414
  if (group.isActive !== false) {
410
415
  let isOn = ((byte & (1 << (j))) >> j) > 0;
411
416
  sys.board.circuits.setEndTime(group, gstate, isOn);
@@ -442,6 +447,9 @@ export class ExternalMessage {
442
447
  break;
443
448
  }
444
449
  }
450
+ else if(gstate.dataName === 'circuitGroup') {
451
+ (gstate as CircuitGroupState).showInFeatures = group.showInFeatures;
452
+ }
445
453
  }
446
454
  else {
447
455
  state.circuitGroups.removeItemById(groupId);
@@ -850,7 +858,7 @@ export class ExternalMessage {
850
858
  // chlorinator. These should be 0 anyway.
851
859
  schlor.poolSetpoint = chlor.spaSetpoint = msg.extractPayloadByte(0) >> 1;
852
860
  schlor.spaSetpoint = chlor.poolSetpoint = msg.extractPayloadByte(1);
853
- chlor.address = chlor.id + 79;
861
+ if (typeof chlor.address === 'undefined') chlor.address = 80; // chlor.id + 79;
854
862
  schlor.body = chlor.body = sys.equipment.maxBodies >= 1 || sys.equipment.shared === true ? 32 : 0;
855
863
  }
856
864
  schlor.superChlor = chlor.superChlor = msg.extractPayloadByte(2) - 128 > 0;
@@ -868,4 +876,26 @@ export class ExternalMessage {
868
876
  state.chlorinators.removeItemById(1);
869
877
  }
870
878
  }
879
+ public static processTouchSetHeatMode(msg: Inbound) {
880
+ // We get here because some other controller is setting the heat
881
+ // mode. The OCP will emit an 8 later but it can be very slow
882
+ // in doing this. ScreenLogic also captures this message so it
883
+ // doesn't get behind.
884
+ //[165, 1, 16, 34, 136, 4][86, 100, 3, 0][2, 33]
885
+ //payload: [temp1, temp2, mode2 << 2 | mode1, setPoint],
886
+ let bstate1 = state.temps.bodies.getItemById(1);
887
+ let bstate2 = state.temps.bodies.getItemById(2);
888
+ let body1 = sys.bodies.getItemById(1);
889
+ let body2 = sys.bodies.getItemById(2);
890
+ let mode1 = msg.extractPayloadByte(2) & 0x03;
891
+ let mode2 = (msg.extractPayloadByte(2) & 0x0C) >> 2;
892
+ bstate1.setPoint = body1.heatSetpoint = msg.extractPayloadByte(0);
893
+ bstate1.coolSetpoint = body1.coolSetpoint = msg.extractPayloadByte(3);
894
+ bstate2.setPoint = body2.heatSetpoint = msg.extractPayloadByte(1);
895
+ bstate1.heatMode = body1.heatMode = mode1;
896
+ bstate2.heatMode = body2.heatMode = mode2;
897
+ msg.isProcessed = true;
898
+ state.emitEquipmentChanges();
899
+
900
+ }
871
901
  }
@@ -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
@@ -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