nodejs-poolcontroller 7.6.1 → 7.7.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 (91) hide show
  1. package/.eslintrc.json +44 -44
  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 +220 -215
  8. package/Dockerfile +17 -17
  9. package/Gruntfile.js +40 -40
  10. package/LICENSE +661 -661
  11. package/README.md +191 -191
  12. package/app.ts +1 -1
  13. package/config/Config.ts +14 -0
  14. package/config/VersionCheck.ts +2 -2
  15. package/controller/Constants.ts +2 -1
  16. package/controller/Equipment.ts +2484 -2459
  17. package/controller/Errors.ts +180 -180
  18. package/controller/Lockouts.ts +502 -436
  19. package/controller/State.ts +106 -30
  20. package/controller/boards/AquaLinkBoard.ts +1000 -0
  21. package/controller/boards/BoardFactory.ts +49 -45
  22. package/controller/boards/EasyTouchBoard.ts +2859 -2653
  23. package/controller/boards/IntelliCenterBoard.ts +4198 -4230
  24. package/controller/boards/IntelliComBoard.ts +63 -63
  25. package/controller/boards/IntelliTouchBoard.ts +273 -241
  26. package/controller/boards/NixieBoard.ts +1728 -1675
  27. package/controller/boards/SystemBoard.ts +4925 -4697
  28. package/controller/comms/Comms.ts +442 -479
  29. package/controller/comms/messages/Messages.ts +171 -25
  30. package/controller/comms/messages/config/ChlorinatorMessage.ts +5 -2
  31. package/controller/comms/messages/config/CircuitGroupMessage.ts +0 -0
  32. package/controller/comms/messages/config/CircuitMessage.ts +1 -0
  33. package/controller/comms/messages/config/ConfigMessage.ts +0 -0
  34. package/controller/comms/messages/config/CoverMessage.ts +0 -0
  35. package/controller/comms/messages/config/CustomNameMessage.ts +30 -30
  36. package/controller/comms/messages/config/EquipmentMessage.ts +0 -0
  37. package/controller/comms/messages/config/ExternalMessage.ts +0 -0
  38. package/controller/comms/messages/config/FeatureMessage.ts +0 -0
  39. package/controller/comms/messages/config/GeneralMessage.ts +0 -0
  40. package/controller/comms/messages/config/HeaterMessage.ts +142 -10
  41. package/controller/comms/messages/config/IntellichemMessage.ts +0 -0
  42. package/controller/comms/messages/config/OptionsMessage.ts +4 -21
  43. package/controller/comms/messages/config/PumpMessage.ts +53 -35
  44. package/controller/comms/messages/config/RemoteMessage.ts +0 -0
  45. package/controller/comms/messages/config/ScheduleMessage.ts +350 -347
  46. package/controller/comms/messages/config/SecurityMessage.ts +0 -0
  47. package/controller/comms/messages/config/ValveMessage.ts +1 -1
  48. package/controller/comms/messages/status/ChlorinatorStateMessage.ts +38 -86
  49. package/controller/comms/messages/status/EquipmentStateMessage.ts +58 -22
  50. package/controller/comms/messages/status/HeaterStateMessage.ts +116 -86
  51. package/controller/comms/messages/status/IntelliChemStateMessage.ts +445 -445
  52. package/controller/comms/messages/status/IntelliValveStateMessage.ts +35 -35
  53. package/controller/comms/messages/status/PumpStateMessage.ts +23 -1
  54. package/controller/comms/messages/status/VersionMessage.ts +0 -0
  55. package/controller/nixie/Nixie.ts +162 -162
  56. package/controller/nixie/NixieEquipment.ts +103 -103
  57. package/controller/nixie/bodies/Body.ts +120 -120
  58. package/controller/nixie/bodies/Filter.ts +135 -135
  59. package/controller/nixie/chemistry/ChemController.ts +2511 -2498
  60. package/controller/nixie/chemistry/Chlorinator.ts +363 -314
  61. package/controller/nixie/circuits/Circuit.ts +261 -248
  62. package/controller/nixie/heaters/Heater.ts +650 -648
  63. package/controller/nixie/pumps/Pump.ts +906 -661
  64. package/controller/nixie/schedules/Schedule.ts +313 -257
  65. package/controller/nixie/valves/Valve.ts +170 -170
  66. package/defaultConfig.json +306 -286
  67. package/logger/DataLogger.ts +448 -448
  68. package/logger/Logger.ts +0 -0
  69. package/package.json +56 -56
  70. package/tsconfig.json +25 -25
  71. package/web/Server.ts +92 -47
  72. package/web/bindings/aqualinkD.json +505 -0
  73. package/web/bindings/influxDB.json +1051 -1021
  74. package/web/bindings/mqtt.json +702 -654
  75. package/web/bindings/mqttAlt.json +731 -684
  76. package/web/bindings/rulesManager.json +54 -54
  77. package/web/bindings/smartThings-Hubitat.json +31 -31
  78. package/web/bindings/valveRelays.json +20 -20
  79. package/web/bindings/vera.json +25 -25
  80. package/web/interfaces/baseInterface.ts +137 -136
  81. package/web/interfaces/httpInterface.ts +145 -124
  82. package/web/interfaces/influxInterface.ts +276 -245
  83. package/web/interfaces/mqttInterface.ts +535 -475
  84. package/web/services/config/Config.ts +39 -18
  85. package/web/services/config/ConfigSocket.ts +0 -0
  86. package/web/services/state/State.ts +10 -0
  87. package/web/services/state/StateSocket.ts +4 -4
  88. package/web/services/utilities/Utilities.ts +44 -42
  89. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -52
  90. package/config copy.json +0 -300
  91. package/issue_template.md +0 -52
@@ -42,6 +42,8 @@ import { TouchScheduleCommands } from "controller/boards/EasyTouchBoard";
42
42
  import { IntelliValveStateMessage } from "./status/IntelliValveStateMessage";
43
43
  import { IntelliChemStateMessage } from "./status/IntelliChemStateMessage";
44
44
  import { OutboundMessageError } from "../../Errors";
45
+ import { prototype } from "events";
46
+ import extend = require("extend");
45
47
  export enum Direction {
46
48
  In = 'in',
47
49
  Out = 'out'
@@ -54,6 +56,8 @@ export enum Protocol {
54
56
  IntelliChem = 'intellichem',
55
57
  IntelliValve = 'intellivalve',
56
58
  Heater = 'heater',
59
+ AquaLink = 'aqualink',
60
+ Hayward = 'hayward',
57
61
  Unidentified = 'unidentified'
58
62
  }
59
63
  export class Message {
@@ -67,7 +71,7 @@ export class Message {
67
71
  // Fields
68
72
  private static _messageId: number = 0;
69
73
  public static get nextMessageId(): number { return this._messageId < 80000 ? ++this._messageId : this._messageId = 0; }
70
-
74
+ public portId = 0; // This will be the target or source port for the message. If this is from or to an Aux RS485 port the value will be > 0.
71
75
  public timestamp: Date = new Date();
72
76
  public direction: Direction = Direction.In;
73
77
  public protocol: Protocol = Protocol.Unknown;
@@ -85,32 +89,56 @@ export class Message {
85
89
  public get isComplete(): boolean { return this._complete; }
86
90
  public get sub(): number { return this.header.length > 1 ? this.header[1] : -1; }
87
91
  public get dest(): number {
88
- if (this.protocol === Protocol.Chlorinator) {
89
- return this.header[2] >= 80 ? this.header[2] - 79 : 0;
92
+ if (this.header.length > 2) {
93
+ if (this.protocol === Protocol.Chlorinator || this.protocol === Protocol.AquaLink) {
94
+ return this.header.length > 2 ? (this.header[2] >= 80 ? this.header[2] - 79 : 0) : -1;
95
+ }
96
+ else if (this.protocol === Protocol.Hayward) {
97
+ // src act dest
98
+ //0x10, 0x02, 0x00, 0x0C, 0x00, 0x00, 0x2D, 0x02, 0x36, 0x00, 0x83, 0x10, 0x03 -- Response from pump
99
+ return this.header.length > 4 ? this.header[4] : -1;
100
+ }
101
+ else return this.header.length > 2 ? this.header[2] : -1;
90
102
  }
91
- if (this.header.length > 2) return this.header[2];
92
103
  else return -1;
93
104
  }
94
105
  public get source(): number {
95
106
  if (this.protocol === Protocol.Chlorinator) {
96
- return this.header[2] >= 80 ? 0 : 1;
107
+ return this.header.length > 2 ? (this.header[2] >= 80 ? 0 : 1) : -1;
97
108
  // have to assume incoming packets with header[2] >= 80 (sent to a chlorinator)
98
109
  // are from controller (0);
99
110
  // likewise, if the destination is 0 (controller) we
100
111
  // have to assume it was sent from the 1st chlorinator (1)
101
112
  // until we learn otherwise.
102
113
  }
114
+ else if (this.protocol === Protocol.AquaLink) {
115
+ // Once we decode the devices we will be able to tell where it came from based upon the commands.
116
+ return 0;
117
+ }
118
+ else if (this.protocol === Protocol.Hayward) {
119
+ // src act dest
120
+ //0x10, 0x02, 0x00, 0x0C, 0x00, 0x00, 0x2D, 0x02, 0x36, 0x00, 0x83, 0x10, 0x03 -- Response from pump
121
+ //0x10, 0x02, 0x0C, 0x01, 0x02, 0x2D, 0x00, 0x4E, 0x10, 0x03 -- Command to AUX2 Pump
122
+ return this.header.length > 2 ? this.header[2] : -1;
123
+ }
103
124
  if (this.header.length > 3) return this.header[3];
104
125
  else return -1;
105
126
  }
106
127
  public get action(): number {
107
- if (this.protocol === Protocol.Chlorinator) return this.header[3];
108
- if (this.header.length > 5) return this.header[4];
128
+ // The action byte is actually the 4th byte in the header the destination address is the 5th byte.
129
+ if (this.protocol === Protocol.Chlorinator || this.protocol === Protocol.AquaLink) return this.header.length > 3 ? this.header[3] : -1;
130
+ else if (this.protocol === Protocol.Hayward) {
131
+ // src act dest
132
+ //0x10, 0x02, 0x00, 0x0C, 0x00, 0x00, 0x2D, 0x02, 0x36, 0x00, 0x83, 0x10, 0x03 -- Response from pump
133
+ //0x10, 0x02, 0x0C, 0x01, 0x02, 0x2D, 0x00, 0x4E, 0x10, 0x03 -- Command to AUX2 Pump
134
+ this.header.length > 3 ? this.header[3] : -1;
135
+ }
136
+ if (this.header.length > 4) return this.header[4];
109
137
  else return -1;
110
138
  }
111
- public get datalen(): number { return this.protocol === Protocol.Chlorinator ? this.payload.length : this.header.length > 5 ? this.header[5] : -1; }
112
- public get chkHi(): number { return this.protocol === Protocol.Chlorinator ? 0 : this.term.length > 0 ? this.term[0] : -1; }
113
- public get chkLo(): number { return this.protocol === Protocol.Chlorinator ? this.term[0] : this.term[1]; }
139
+ public get datalen(): number { return this.protocol === Protocol.Chlorinator || this.protocol === Protocol.AquaLink || this.protocol === Protocol.Hayward ? this.payload.length : this.header.length > 5 ? this.header[5] : -1; }
140
+ public get chkHi(): number { return this.protocol === Protocol.Chlorinator || this.protocol === Protocol.AquaLink ? 0 : this.term.length > 0 ? this.term[0] : -1; }
141
+ public get chkLo(): number { return this.protocol === Protocol.Chlorinator || this.protocol === Protocol.AquaLink ? this.term[0] : this.term[1]; }
114
142
  public get checksum(): number {
115
143
  var sum = 0;
116
144
  for (let i = 0; i < this.header.length; i++) sum += this.header[i];
@@ -136,7 +164,7 @@ export class Message {
136
164
  return pkt;
137
165
  }
138
166
  public toLog(): string {
139
- return `{"id":${this.id},"valid":${this.isValid},"dir":"${this.direction}","proto":"${this.protocol}","pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)},${JSON.stringify(this.header)},${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts":"${Timestamp.toISOLocal(this.timestamp)}"}`;
167
+ return `{"port":${this.portId},"id":${ this.id },"valid":${ this.isValid },"dir":"${this.direction}","proto":"${this.protocol}","pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)}, ${JSON.stringify(this.header)}, ${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts":"${Timestamp.toISOLocal(this.timestamp)}"}`;
140
168
  }
141
169
  }
142
170
  export class Inbound extends Message {
@@ -158,26 +186,41 @@ export class Inbound extends Message {
158
186
  public responseFor: number[] = [];
159
187
  public isProcessed: boolean = false;
160
188
  public collisions: number = 0;
189
+ public rewinds: number = 0;
161
190
  // Private methods
162
191
  private isValidChecksum(): boolean {
163
- if (this.protocol === Protocol.Chlorinator) return this.checksum % 256 === this.chkLo;
192
+ if (this.protocol === Protocol.Chlorinator || this.protocol === Protocol.AquaLink) return this.checksum % 256 === this.chkLo;
164
193
  return (this.chkHi * 256) + this.chkLo === this.checksum;
165
194
  }
166
195
  public toLog() {
167
196
  if (this.responseFor.length > 0)
168
- return `{"id":${this.id},"valid":${this.isValid},"dir":"${this.direction}","proto":"${this.protocol}","for":${JSON.stringify(this.responseFor)},"pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)},${JSON.stringify(this.header)},${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts": "${Timestamp.toISOLocal(this.timestamp)}"}`;
169
- return `{"id":${this.id},"valid":${this.isValid},"dir":"${this.direction}","proto":"${this.protocol}","pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)},${JSON.stringify(this.header)},${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts": "${Timestamp.toISOLocal(this.timestamp)}"}`;
197
+ return `{"port":${this.portId || 0},"id":${this.id},"valid":${this.isValid},"dir":"${ this.direction }","proto":"${ this.protocol }","for":${JSON.stringify(this.responseFor)},"pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)},${JSON.stringify(this.header)},${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts": "${ Timestamp.toISOLocal(this.timestamp) }"}`;
198
+ return `{"port":${this.portId || 0},"id":${this.id},"valid":${this.isValid},"dir":"${this.direction}","proto":"${this.protocol}","pkt":[${JSON.stringify(this.padding)},${JSON.stringify(this.preamble)},${JSON.stringify(this.header)},${JSON.stringify(this.payload)},${JSON.stringify(this.term)}],"ts": "${Timestamp.toISOLocal(this.timestamp)}"}`;
170
199
  }
171
200
  private testChlorHeader(bytes: number[], ndx: number): boolean {
172
201
  // if packets have 16,2 (eg status=16,2,29) in them and they come as partial packets, they would have
173
202
  // prev been detected as chlor packets;
174
203
  // valid chlor packets should have 16,2,0 or 16,2,[80-96];
175
204
  // this should reduce the number of false chlor packets
176
- return (ndx + 2 < bytes.length && bytes[ndx] === 16 && bytes[ndx + 1] === 2 && (bytes[ndx + 2] === 0 || (bytes[ndx + 2] >= 80 && bytes[ndx + 2] <= 96)))
205
+ return (ndx + 3 < bytes.length && bytes[ndx] === 16 && bytes[ndx + 1] === 2 && (bytes[ndx + 2] === 0 || (bytes[ndx + 2] >= 80 && bytes[ndx + 2] <= 96)))
206
+ }
207
+ private testAquaLinkHeader(bytes: number[], ndx: number): boolean {
208
+ return (sys.controllerType === 'aqualink' && ndx + 3 < bytes.length && bytes[ndx] === 16 && bytes[ndx + 1] === 2);
177
209
  }
210
+ private testHaywardHeader(bytes: number[], ndx: number): boolean {
211
+ //0x10, 0x02, 0x0C, 0x01, 0x00, 0x2D, 0x00, 0x4C, 0x10, 0x03 -- Command to pump
212
+ //0x10, 0x02, 0x0C, 0x01, 0x00, 0x2D, 0x00, 0x4C, 0x10, 0x03 -- Command to Filter Pump
213
+ //0x10, 0x02, 0x0C, 0x01, 0x02, 0x2D, 0x00, 0x4E, 0x10, 0x03 -- Command to AUX2 Pump
214
+ // src act dest
215
+ //0x10, 0x02, 0x00, 0x0C, 0x00, 0x00, 0x2D, 0x02, 0x36, 0x00, 0x83, 0x10, 0x03 -- Response from pump
216
+ return (sys.controllerType === 'nixie' && ndx + 4 < bytes.length && bytes[ndx] === 16 && bytes[ndx + 1] === 2 && (bytes[ndx + 2] === 12 && bytes[ndx + 3] === 12));
217
+ }
218
+
178
219
  private testBroadcastHeader(bytes: number[], ndx: number): boolean { return ndx < bytes.length - 3 && bytes[ndx] === 255 && bytes[ndx + 1] === 0 && bytes[ndx + 2] === 255 && bytes[ndx + 3] === 165; }
179
220
  private testUnidentifiedHeader(bytes: number[], ndx: number): boolean { return ndx < bytes.length - 3 && bytes[ndx] === 255 && bytes[ndx + 1] === 0 && bytes[ndx + 2] === 255 && bytes[ndx + 3] !== 165; }
180
- private testChlorTerm(bytes: number[], ndx: number): boolean { return ndx < bytes.length - 2 && bytes[ndx + 1] === 16 && bytes[ndx + 2] === 3; }
221
+ private testChlorTerm(bytes: number[], ndx: number): boolean { return ndx + 2 < bytes.length && bytes[ndx + 1] === 16 && bytes[ndx + 2] === 3; }
222
+ private testAquaLinkTerm(bytes: number[], ndx: number): boolean { return ndx + 2 < bytes.length && bytes[ndx + 1] === 16 && bytes[ndx + 2] === 3; }
223
+ private testHaywardTerm(bytes: number[], ndx: number): boolean { return ndx + 3 < bytes.length && bytes[ndx + 2] === 16 && bytes[ndx + 3] === 3; }
181
224
  private pushBytes(target: number[], bytes: number[], ndx: number, length: number): number {
182
225
  let end = ndx + length;
183
226
  while (ndx < bytes.length && ndx < end)
@@ -205,6 +248,7 @@ export class Inbound extends Message {
205
248
  this.isValid = true;
206
249
 
207
250
  this.collisions++;
251
+ this.rewinds++;
208
252
  logger.info(`rewinding message collision ${this.collisions} ${ndx} ${bytes.length} ${JSON.stringify(buff)}`);
209
253
  this.readPacket(buff);
210
254
  return ndx;
@@ -233,6 +277,14 @@ export class Inbound extends Message {
233
277
  this.protocol = Protocol.Chlorinator;
234
278
  break;
235
279
  }
280
+ if (this.testAquaLinkHeader(bytes, ndx)) {
281
+ this.protocol = Protocol.AquaLink;
282
+ break;
283
+ }
284
+ if (this.testHaywardHeader(bytes, ndx)) {
285
+ this.protocol = Protocol.Hayward;
286
+ break;
287
+ }
236
288
  if (this.testBroadcastHeader(bytes, ndx)) {
237
289
  this.protocol = Protocol.Broadcast;
238
290
  break;
@@ -277,6 +329,7 @@ export class Inbound extends Message {
277
329
  this.preamble = [];
278
330
  this.header = [];
279
331
  this.collisions++;
332
+ this.rewinds++;
280
333
  return ndxHeader + 1;
281
334
  }
282
335
  break;
@@ -298,6 +351,28 @@ export class Inbound extends Message {
298
351
  return ndxHeader;
299
352
  }
300
353
  break;
354
+ case Protocol.Hayward:
355
+ ndx = this.pushBytes(this.header, bytes, ndx, 4);
356
+ if (this.header.length < 4) {
357
+ // We actually don't have a complete header yet so just return.
358
+ // we will pick it up next go around.
359
+ logger.debug(`We have an incoming AquaLink message but the serial port hasn't given a complete header. [${this.padding}][${this.preamble}][${this.header}]`);
360
+ this.preamble = [];
361
+ this.header = [];
362
+ return ndxHeader;
363
+ }
364
+ break;
365
+ case Protocol.AquaLink:
366
+ ndx = this.pushBytes(this.header, bytes, ndx, 5);
367
+ if (this.header.length < 5) {
368
+ // We actually don't have a complete header yet so just return.
369
+ // we will pick it up next go around.
370
+ logger.debug(`We have an incoming AquaLink message but the serial port hasn't given a complete header. [${this.padding}][${this.preamble}][${this.header}]`);
371
+ this.preamble = [];
372
+ this.header = [];
373
+ return ndxHeader;
374
+ }
375
+ break;
301
376
  default:
302
377
  // We didn't get a message signature. don't do anything with it.
303
378
  ndx = ndxStart;
@@ -341,6 +416,31 @@ export class Inbound extends Message {
341
416
  }
342
417
  }
343
418
  break;
419
+ case Protocol.AquaLink:
420
+ // We need to deal with AquaLink packets where the terminator is actually split meaning only the first byte or
421
+ // two of the total payload is provided for the term. We need at least 3 bytes to make this determination.
422
+ while (ndx + 3 <= bytes.length && !this.testAquaLinkTerm(bytes, ndx)) {
423
+ this.payload.push(bytes[ndx++]);
424
+ if (this.payload.length > 25) {
425
+ this.isValid = false; // We have a runaway packet. Some collision occurred so lets preserve future packets.
426
+ logger.debug(`AquaLink message marked as invalid after not finding 16,3 in payload after ${this.payload.length} bytes`);
427
+ break;
428
+ }
429
+ }
430
+ break;
431
+ case Protocol.Hayward:
432
+ // We need to deal with AquaLink packets where the terminator is actually split meaning only the first byte or
433
+ // two of the total payload is provided for the term. We need at least 3 bytes to make this determination.
434
+ while (ndx + 4 <= bytes.length && !this.testHaywardTerm(bytes, ndx)) {
435
+ this.payload.push(bytes[ndx++]);
436
+ if (this.payload.length > 25) {
437
+ this.isValid = false; // We have a runaway packet. Some collision occurred so lets preserve future packets.
438
+ logger.debug(`Hayward message marked as invalid after not finding 16,3 in payload after ${this.payload.length} bytes`);
439
+ break;
440
+ }
441
+ }
442
+ break;
443
+
344
444
  }
345
445
  return ndx;
346
446
  }
@@ -369,6 +469,21 @@ export class Inbound extends Message {
369
469
  this.isValid = this.isValidChecksum();
370
470
  }
371
471
  break;
472
+ case Protocol.AquaLink:
473
+ if (ndx + 3 <= bytes.length && this.testAquaLinkTerm(bytes, ndx)) {
474
+ this._complete = true;
475
+ ndx = this.pushBytes(this.term, bytes, ndx, 3);
476
+ this.isValid = this.isValidChecksum();
477
+ }
478
+ break;
479
+ case Protocol.Hayward:
480
+ if (ndx + 4 <= bytes.length && this.testHaywardTerm(bytes, ndx)) {
481
+ this._complete = true;
482
+ ndx = this.pushBytes(this.term, bytes, ndx, 4);
483
+ this.isValid = this.isValidChecksum();
484
+ }
485
+ break;
486
+
372
487
  }
373
488
  return ndx;
374
489
  }
@@ -546,6 +661,9 @@ export class Inbound extends Message {
546
661
  case Protocol.Chlorinator:
547
662
  ChlorinatorStateMessage.process(this);
548
663
  break;
664
+ case Protocol.Hayward:
665
+ PumpStateMessage.processHayward(this);
666
+ break;
549
667
  default:
550
668
  logger.debug(`Unprocessed Message ${this.toPacket()}`)
551
669
  break;
@@ -553,15 +671,24 @@ export class Inbound extends Message {
553
671
  }
554
672
  }
555
673
  class OutboundCommon extends Message {
556
- public set sub(val: number) { if (this.protocol !== Protocol.Chlorinator) this.header[1] = val; }
674
+ public set sub(val: number) { if (this.protocol !== Protocol.Chlorinator && this.protocol !== Protocol.AquaLink) this.header[1] = val; }
557
675
  public get sub() { return super.sub; }
558
- public set dest(val: number) { this.protocol !== Protocol.Chlorinator ? this.header[2] = val : this.header[2] = val + 79; }
676
+ public set dest(val: number) {
677
+ if (this.protocol === Protocol.Chlorinator) this.header[2] = val + 79;
678
+ else if (this.protocol === Protocol.Hayward) this.header[4] = val;
679
+ else this.header[2] = val;
680
+ }
559
681
  public get dest() { return super.dest; }
560
- public set source(val: number) { if (this.protocol !== Protocol.Chlorinator) this.header[3] = val; }
682
+ public set source(val: number) {
683
+ if (this.protocol === Protocol.Hayward) this.header[2] = val;
684
+ else if (this.protocol !== Protocol.Chlorinator) this.header[3] = val;
685
+ }
561
686
  public get source() { return super.source; }
562
- public set action(val: number) { (this.protocol !== Protocol.Chlorinator) ? this.header[4] = val : this.header[3] = val; }
687
+ public set action(val: number) {
688
+ (this.protocol !== Protocol.Chlorinator && this.protocol !== Protocol.Hayward) ? this.header[4] = val : this.header[3] = val;
689
+ }
563
690
  public get action() { return super.action; }
564
- public set datalen(val: number) { if (this.protocol !== Protocol.Chlorinator) this.header[5] = val; }
691
+ public set datalen(val: number) { if (this.protocol !== Protocol.Chlorinator && this.protocol !== Protocol.Hayward) this.header[5] = val; }
565
692
  public get datalen() { return super.datalen; }
566
693
  public set chkHi(val: number) { if (this.protocol !== Protocol.Chlorinator) this.term[0] = val; }
567
694
  public get chkHi() { return super.chkHi; }
@@ -581,9 +708,14 @@ class OutboundCommon extends Message {
581
708
  this.chkHi = Math.floor(sum / 256);
582
709
  this.chkLo = (sum - (super.chkHi * 256));
583
710
  break;
711
+ case Protocol.AquaLink:
584
712
  case Protocol.Chlorinator:
585
713
  this.term[0] = sum;
586
714
  break;
715
+ case Protocol.Hayward:
716
+ this.chkHi = Math.floor(sum / 256);
717
+ this.chkLo = (sum - (super.chkHi * 256));
718
+ break;
587
719
  }
588
720
  }
589
721
  }
@@ -598,7 +730,7 @@ export class Outbound extends OutboundCommon {
598
730
  this.header.length = 0;
599
731
  this.term.length = 0;
600
732
  this.payload.length = 0;
601
- if (proto === Protocol.Chlorinator) {
733
+ if (proto === Protocol.Chlorinator || proto === Protocol.AquaLink) {
602
734
  this.header.push.apply(this.header, [16, 2, 0, 0]);
603
735
  this.term.push.apply(this.term, [0, 16, 3]);
604
736
  }
@@ -612,6 +744,10 @@ export class Outbound extends OutboundCommon {
612
744
  this.header.push.apply(this.header, [165, 0, 15, Message.pluginAddress, 0, 0]);
613
745
  this.term.push.apply(this.term, [0, 0]);
614
746
  }
747
+ else if (proto === Protocol.Hayward) {
748
+ this.header.push.apply(this.header, [16, 2, 0, 0, 0]);
749
+ this.term.push.apply(this.term, [0, 0, 16, 3]);
750
+ }
615
751
  this.scope = scope;
616
752
  this.source = source;
617
753
  this.dest = dest;
@@ -625,8 +761,19 @@ export class Outbound extends OutboundCommon {
625
761
  }
626
762
  // Factory
627
763
  public static create(obj?: any) {
628
- let out = new Outbound(obj.protocol || Protocol.Broadcast,
629
- obj.source || sys.board.commandSourceAddress || Message.pluginAddress, obj.dest || sys.board.commandDestAddress || 16, obj.action || 0, obj.payload || [], obj.retries || 0, obj.response || false, obj.scope || undefined);
764
+ let o = extend({
765
+ protocol: Protocol.Broadcast,
766
+ source: sys.board.commandSourceAddress || Message.pluginAddress,
767
+ dest: sys.board.commandDestAddress || 16,
768
+ action: 0,
769
+ payload: [],
770
+ retries: 0,
771
+ response: false,
772
+ }, obj, true);
773
+ let out = new Outbound(o.protocol, o.source, o.dest, o.action, o.payload, o.retries, o.response, o.scope);
774
+ //let out = new Outbound(obj.protocol || Protocol.Broadcast,
775
+ // obj.source || sys.board.commandSourceAddress || Message.pluginAddress, obj.dest || sys.board.commandDestAddress || 16, obj.action || 0, obj.payload || [], obj.retries || 0, obj.response || false, obj.scope || undefined);
776
+ out.portId = obj.portId || 0;
630
777
  out.onComplete = obj.onComplete;
631
778
  out.onAbort = obj.onAbort;
632
779
  out.timeout = obj.timeout;
@@ -659,7 +806,6 @@ export class Outbound extends OutboundCommon {
659
806
  return false;
660
807
  }
661
808
  public get remainingTries(): number { return this.retries - this.tries + 1; } // Always allow 1 try.
662
-
663
809
  public setPayloadByte(ndx: number, value: number, def?: number) {
664
810
  if (typeof value === 'undefined' || isNaN(value)) value = def;
665
811
  if (ndx < this.payload.length) this.payload[ndx] = value;
@@ -28,11 +28,12 @@ export class ChlorinatorMessage {
28
28
  for (let i = 0; i < 4 && i + 30 < msg.payload.length; i++) {
29
29
  let isActive = msg.extractPayloadByte(i + 22) === 1;
30
30
  chlor = sys.chlorinators.getItemById(chlorId);
31
- if (chlor.master === 1) continue; // RSG: probably never need this. See Touch chlor below.
31
+ //if (chlor.master !== 0) continue; // RSG: probably never need this. See Touch chlor below.
32
32
  if (isActive) {
33
33
  chlor = sys.chlorinators.getItemById(chlorId, true);
34
34
  let schlor = state.chlorinators.getItemById(chlor.id, true);
35
35
  chlor.isActive = schlor.isActive = true;
36
+ chlor.master = 0;
36
37
  chlor.body = msg.extractPayloadByte(i + 2);
37
38
  chlor.type = msg.extractPayloadByte(i + 6);
38
39
  if (!chlor.disabled && !chlor.isDosing) {
@@ -51,6 +52,7 @@ export class ChlorinatorMessage {
51
52
  schlor.poolSetpoint = chlor.poolSetpoint;
52
53
  schlor.spaSetpoint = chlor.spaSetpoint;
53
54
  schlor.type = chlor.type;
55
+ schlor.model = chlor.model;
54
56
  schlor.isActive = chlor.isActive;
55
57
  schlor.superChlorHours = chlor.superChlorHours;
56
58
  state.emitEquipmentChanges();
@@ -69,9 +71,10 @@ export class ChlorinatorMessage {
69
71
  }
70
72
  }
71
73
  public static processTouch(msg: Inbound) {
74
+ //[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
75
  // This is for the 25 message that is broadcast from the OCP.
73
76
  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
77
+ 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
78
  let isActive = (msg.extractPayloadByte(0) & 0x01) === 1;
76
79
  if (isActive) {
77
80
  let chlor = sys.chlorinators.getItemById(1, true);
@@ -243,6 +243,7 @@ export class CircuitMessage {
243
243
  if (_isActive) {
244
244
  const type = functionId & 63;
245
245
  let circuit: ICircuit = sys.circuits.getInterfaceById(id, _isActive);
246
+ circuit.master = 0;
246
247
  circuit.name = sys.board.circuits.getNameById(nameId);
247
248
  circuit.nameId = nameId;
248
249
  circuit.type = type;
File without changes
File without changes
@@ -1,31 +1,31 @@
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. 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
+ }
31
31
  }