nodejs-poolcontroller 7.3.1 → 7.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/.eslintrc.json +44 -44
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +52 -52
  3. package/CONTRIBUTING.md +74 -74
  4. package/Changelog +215 -195
  5. package/Dockerfile +17 -17
  6. package/Gruntfile.js +40 -40
  7. package/LICENSE +661 -661
  8. package/README.md +191 -186
  9. package/app.ts +2 -0
  10. package/config/Config.ts +27 -2
  11. package/config/VersionCheck.ts +33 -14
  12. package/config copy.json +299 -299
  13. package/controller/Constants.ts +88 -0
  14. package/controller/Equipment.ts +2459 -2225
  15. package/controller/Errors.ts +180 -157
  16. package/controller/Lockouts.ts +437 -0
  17. package/controller/State.ts +364 -79
  18. package/controller/boards/BoardFactory.ts +45 -45
  19. package/controller/boards/EasyTouchBoard.ts +2653 -2489
  20. package/controller/boards/IntelliCenterBoard.ts +4230 -3973
  21. package/controller/boards/IntelliComBoard.ts +63 -63
  22. package/controller/boards/IntelliTouchBoard.ts +241 -167
  23. package/controller/boards/NixieBoard.ts +1675 -1105
  24. package/controller/boards/SystemBoard.ts +4697 -3201
  25. package/controller/comms/Comms.ts +222 -10
  26. package/controller/comms/messages/Messages.ts +13 -9
  27. package/controller/comms/messages/config/ChlorinatorMessage.ts +13 -4
  28. package/controller/comms/messages/config/CircuitGroupMessage.ts +6 -0
  29. package/controller/comms/messages/config/CircuitMessage.ts +0 -0
  30. package/controller/comms/messages/config/ConfigMessage.ts +0 -0
  31. package/controller/comms/messages/config/CoverMessage.ts +1 -0
  32. package/controller/comms/messages/config/CustomNameMessage.ts +30 -30
  33. package/controller/comms/messages/config/EquipmentMessage.ts +4 -0
  34. package/controller/comms/messages/config/ExternalMessage.ts +53 -33
  35. package/controller/comms/messages/config/FeatureMessage.ts +8 -1
  36. package/controller/comms/messages/config/GeneralMessage.ts +8 -0
  37. package/controller/comms/messages/config/HeaterMessage.ts +14 -28
  38. package/controller/comms/messages/config/IntellichemMessage.ts +4 -1
  39. package/controller/comms/messages/config/OptionsMessage.ts +38 -2
  40. package/controller/comms/messages/config/PumpMessage.ts +4 -20
  41. package/controller/comms/messages/config/RemoteMessage.ts +4 -0
  42. package/controller/comms/messages/config/ScheduleMessage.ts +347 -331
  43. package/controller/comms/messages/config/SecurityMessage.ts +1 -0
  44. package/controller/comms/messages/config/ValveMessage.ts +13 -3
  45. package/controller/comms/messages/status/ChlorinatorStateMessage.ts +2 -3
  46. package/controller/comms/messages/status/EquipmentStateMessage.ts +79 -25
  47. package/controller/comms/messages/status/HeaterStateMessage.ts +86 -53
  48. package/controller/comms/messages/status/IntelliChemStateMessage.ts +445 -386
  49. package/controller/comms/messages/status/IntelliValveStateMessage.ts +35 -35
  50. package/controller/comms/messages/status/PumpStateMessage.ts +0 -0
  51. package/controller/comms/messages/status/VersionMessage.ts +0 -0
  52. package/controller/nixie/Nixie.ts +162 -160
  53. package/controller/nixie/NixieEquipment.ts +103 -103
  54. package/controller/nixie/bodies/Body.ts +120 -117
  55. package/controller/nixie/bodies/Filter.ts +135 -135
  56. package/controller/nixie/chemistry/ChemController.ts +2498 -2395
  57. package/controller/nixie/chemistry/Chlorinator.ts +314 -313
  58. package/controller/nixie/circuits/Circuit.ts +248 -210
  59. package/controller/nixie/heaters/Heater.ts +649 -441
  60. package/controller/nixie/pumps/Pump.ts +661 -599
  61. package/controller/nixie/schedules/Schedule.ts +257 -256
  62. package/controller/nixie/valves/Valve.ts +170 -170
  63. package/defaultConfig.json +286 -271
  64. package/issue_template.md +51 -51
  65. package/logger/DataLogger.ts +448 -433
  66. package/logger/Logger.ts +0 -0
  67. package/package.json +56 -54
  68. package/tsconfig.json +25 -25
  69. package/web/Server.ts +522 -31
  70. package/web/bindings/influxDB.json +1022 -894
  71. package/web/bindings/mqtt.json +654 -543
  72. package/web/bindings/mqttAlt.json +684 -574
  73. package/web/bindings/rulesManager.json +54 -54
  74. package/web/bindings/smartThings-Hubitat.json +31 -31
  75. package/web/bindings/valveRelays.json +20 -20
  76. package/web/bindings/vera.json +25 -25
  77. package/web/interfaces/baseInterface.ts +136 -136
  78. package/web/interfaces/httpInterface.ts +124 -122
  79. package/web/interfaces/influxInterface.ts +245 -240
  80. package/web/interfaces/mqttInterface.ts +475 -464
  81. package/web/services/config/Config.ts +181 -152
  82. package/web/services/config/ConfigSocket.ts +0 -0
  83. package/web/services/state/State.ts +118 -7
  84. package/web/services/state/StateSocket.ts +18 -1
  85. package/web/services/utilities/Utilities.ts +42 -42
@@ -17,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  import { Inbound } from "../Messages";
18
18
  import { sys, Body, ICircuitGroup, LightGroup, CircuitGroup } from "../../../Equipment";
19
19
  import { state, ICircuitGroupState, LightGroupState } from "../../../State";
20
- import { utils } from "../../../Constants";
20
+ import { Timestamp, utils } from "../../../Constants";
21
21
  import { logger } from "../../../../logger/Logger";
22
22
  export class ExternalMessage {
23
23
  public static processIntelliCenter(msg: Inbound): void {
@@ -83,7 +83,8 @@ export class ExternalMessage {
83
83
  if (isActive) {
84
84
  let chem = sys.chemControllers.getItemById(id, true);
85
85
  let schem = state.chemControllers.getItemById(id, true);
86
- chem.isVirtual = false;
86
+ // chem.isVirtual = false;
87
+ chem.master = 0;
87
88
  chem.ph.tank.capacity = chem.orp.tank.capacity = 6;
88
89
  chem.ph.tank.units = chem.orp.tank.units = '';
89
90
  schem.type = chem.type = 2;
@@ -106,7 +107,8 @@ export class ExternalMessage {
106
107
  let valve = sys.valves.getItemById(msg.extractPayloadByte(2) + 1);
107
108
  valve.circuit = msg.extractPayloadByte(3) + 1;
108
109
  valve.name = msg.extractPayloadString(4, 16);
109
- valve.isVirtual = false;
110
+ valve.master = 0;
111
+ // valve.isVirtual = false;
110
112
  msg.isProcessed = true;
111
113
  }
112
114
  public static processPool(msg: Inbound) {
@@ -215,7 +217,7 @@ export class ExternalMessage {
215
217
  if (group.isActive) {
216
218
  for (let i = 0; i < 16; i++) {
217
219
  let circuitId = msg.extractPayloadByte(i + 6);
218
- let circuit = group.circuits.getItemById(i + 1, circuitId !== 255);
220
+ let circuit = group.circuits.getItemById(i + 1, circuitId < 255);
219
221
  if (circuitId === 255) group.circuits.removeItemById(i + 1);
220
222
  circuit.circuit = circuitId + 1;
221
223
 
@@ -272,31 +274,30 @@ export class ExternalMessage {
272
274
  private static processHeater(msg: Inbound) {
273
275
  // So a user is changing the heater info. Lets
274
276
  // hijack it and get it ourselves.
275
- let heater = sys.heaters.getItemById(msg.extractPayloadByte(2) + 1);
276
- heater.type = msg.extractPayloadByte(3);
277
- heater.body = msg.extractPayloadByte(4);
278
- heater.cooldownDelay = msg.extractPayloadByte(5);
279
- heater.startTempDelta = msg.extractPayloadByte(6);
280
- heater.stopTempDelta = msg.extractPayloadByte(7);
281
- heater.coolingEnabled = msg.extractPayloadByte(8) > 0;
282
- heater.differentialTemp = msg.extractPayloadByte(9);
283
- heater.address = msg.extractPayloadByte(10);
284
- heater.name = msg.extractPayloadString(11, 16);
285
- heater.efficiencyMode = msg.extractPayloadByte(27);
286
- heater.maxBoostTemp = msg.extractPayloadByte(28);
287
- heater.economyTime = msg.extractPayloadByte(29);
288
- if (heater.type === 0) {
289
- sys.heaters.removeItemById(heater.id);
290
- state.heaters.removeItemById(heater.id);
277
+ let isActive = msg.extractPayloadByte(3) !== 0;
278
+ let heaterId = msg.extractPayloadByte(2) + 1;
279
+ if (isActive) {
280
+ let heater = sys.heaters.getItemById(heaterId, true);
281
+ let hstate = state.heaters.getItemById(heater.id, true);
282
+
283
+ hstate.type = heater.type = msg.extractPayloadByte(3);
284
+ heater.body = msg.extractPayloadByte(4);
285
+ heater.cooldownDelay = msg.extractPayloadByte(5);
286
+ heater.startTempDelta = msg.extractPayloadByte(6);
287
+ heater.stopTempDelta = msg.extractPayloadByte(7);
288
+ heater.coolingEnabled = msg.extractPayloadByte(8) > 0;
289
+ heater.differentialTemp = msg.extractPayloadByte(9);
290
+ heater.address = msg.extractPayloadByte(10);
291
+ hstate.name = heater.name = msg.extractPayloadString(11, 16);
292
+ heater.efficiencyMode = msg.extractPayloadByte(27);
293
+ heater.maxBoostTemp = msg.extractPayloadByte(28);
294
+ heater.economyTime = msg.extractPayloadByte(29);
295
+ heater.master = 0;
291
296
  }
292
297
  else {
293
- let hstate = state.heaters.getItemById(heater.id, true);
294
- hstate.name = heater.name;
295
- //heater.isVirtual = hstate.isVirtual = false;
296
- hstate.name = heater.name;
297
- hstate.type = heater.type;
298
+ sys.heaters.removeItemById(heaterId);
299
+ state.heaters.removeItemById(heaterId);
298
300
  }
299
-
300
301
  sys.board.heaters.updateHeaterServices();
301
302
  // Check anyway to make sure we got it all.
302
303
  //setTimeout(() => sys.checkConfiguration(), 500);
@@ -428,13 +429,13 @@ export class ExternalMessage {
428
429
  // [11] = No sequencing underway.
429
430
  switch (byte) {
430
431
  case 0: // Sync
431
- lg.action = 1;
432
+ lg.action = sys.board.valueMaps.circuitActions.getValue('colorsync');
432
433
  break;
433
434
  case 1: // Color swim
434
- lg.action = 3;
435
+ lg.action = sys.board.valueMaps.circuitActions.getValue('colorswim');
435
436
  break;
436
437
  case 2: // Color set
437
- lg.action = 2;
438
+ lg.action = sys.board.valueMaps.circuitActions.getValue('colorset');
438
439
  break;
439
440
  default:
440
441
  lg.action = 0;
@@ -499,11 +500,14 @@ export class ExternalMessage {
499
500
  let startTime = msg.extractPayloadInt(3);
500
501
  let endTime = msg.extractPayloadInt(5);
501
502
  let circuit = msg.extractPayloadByte(7) + 1;
502
- let cfg = sys.schedules.getItemById(schedId, circuit !== 256 && startTime !== 0 && endTime !== 0);
503
- cfg.isActive = (circuit !== 256 && startTime !== 0 && endTime !== 0);
503
+ let isActive = (msg.extractPayloadByte(8) & 128) === 128; // Inactive schedules do not have bit 8 set.
504
+ let cfg = sys.schedules.getItemById(schedId, isActive);
505
+ let s = state.schedules.getItemById(schedId, cfg.isActive);
506
+ //cfg.isActive = (circuit !== 256);
504
507
  cfg.startTime = startTime;
505
508
  cfg.endTime = endTime;
506
509
  cfg.circuit = circuit;
510
+ cfg.isActive = isActive;
507
511
  let byte = msg.extractPayloadByte(8);
508
512
  cfg.scheduleType = (byte & 1 & 0xFF) === 1 ? 0 : 128;
509
513
  if ((byte & 4 & 0xFF) === 4) cfg.startTimeType = 1;
@@ -524,7 +528,6 @@ export class ExternalMessage {
524
528
  cfg.heatSource = hs;
525
529
  cfg.heatSetpoint = msg.extractPayloadByte(14);
526
530
  cfg.coolSetpoint = msg.extractPayloadByte(15);
527
- let s = state.schedules.getItemById(schedId, cfg.isActive);
528
531
  if (cfg.isActive) {
529
532
  let s = state.schedules.getItemById(schedId, cfg.isActive);
530
533
  s.isActive = cfg.isActive = true;
@@ -738,6 +741,8 @@ export class ExternalMessage {
738
741
  sys.general.options.clockMode = (msg.extractPayloadByte(14) & 0x0001) == 1 ? 24 : 12;
739
742
  msg.isProcessed = true;
740
743
  break;
744
+ case 12: // This is byte 15 but we don't know what it is. Numbers witnessed include 51, 52, 89, 235.
745
+ break;
741
746
  case 14: // Clock source
742
747
  if ((msg.extractPayloadByte(17) & 0x0040) === 1)
743
748
  sys.general.options.clockSource = 'internet';
@@ -745,6 +750,8 @@ export class ExternalMessage {
745
750
  sys.general.options.clockSource = 'manual';
746
751
  msg.isProcessed = true;
747
752
  break;
753
+ case 15: // This is byte 18 but we don't know what it is. Numbers witnessed include 1, 2, 3, 5, 100.
754
+ break;
748
755
  case 18: // Body 1 Heat Setpoint
749
756
  body = sys.bodies.getItemById(1, false);
750
757
  body.heatSetpoint = msg.extractPayloadByte(21);
@@ -768,7 +775,7 @@ export class ExternalMessage {
768
775
  break;
769
776
  case 21: // Body 2 Cool Setpoint
770
777
  body = sys.bodies.getItemById(2, false);
771
- body.setPoint = msg.extractPayloadByte(24);
778
+ body.coolSetpoint = msg.extractPayloadByte(24);
772
779
  state.temps.bodies.getItemById(2).coolSetpoint = body.coolSetpoint;
773
780
  state.emitEquipmentChanges();
774
781
  msg.isProcessed = true;
@@ -817,6 +824,19 @@ export class ExternalMessage {
817
824
  sys.general.options.manualHeat = msg.extractPayloadByte(40) !== 0;
818
825
  msg.isProcessed = true;
819
826
  break;
827
+ case 64: // Vacation mode
828
+ let yy = msg.extractPayloadByte(5) + 2000;
829
+ let mm = msg.extractPayloadByte(6);
830
+ let dd = msg.extractPayloadByte(7);
831
+ sys.general.options.vacation.startDate = new Date(yy, mm - 1, dd);
832
+ yy = msg.extractPayloadByte(8) + 2000;
833
+ mm = msg.extractPayloadByte(9);
834
+ dd = msg.extractPayloadByte(10);
835
+ sys.general.options.vacation.endDate = new Date(yy, mm - 1, dd);
836
+ sys.general.options.vacation.enabled = msg.extractPayloadByte(3) > 0;
837
+ sys.general.options.vacation.useTimeframe = msg.extractPayloadByte(4) > 0;
838
+ msg.isProcessed = true;
839
+ break;
820
840
  }
821
841
  }
822
842
  public static processTouchChlorinator(msg: Inbound) {
@@ -58,6 +58,7 @@ export class FeatureMessage {
58
58
  FeatureMessage.processFeatureNames(msg);
59
59
  break;
60
60
  case 22: // Not sure what this is.
61
+ msg.isProcessed = true;
61
62
  break;
62
63
  default:
63
64
  logger.debug(`Unprocessed Config Message ${msg.toPacket()}`)
@@ -70,6 +71,7 @@ export class FeatureMessage {
70
71
  var feature: Feature = sys.features.getItemById(featureId, false);
71
72
  feature.dontStop = msg.extractPayloadByte(i + 1) == 1;
72
73
  }
74
+ msg.isProcessed = true;
73
75
  }
74
76
  private static processFeatureType(msg: Inbound) {
75
77
  for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxFeatures; i++) {
@@ -88,6 +90,7 @@ export class FeatureMessage {
88
90
  state.features.removeItemById(featureId);
89
91
  }
90
92
  }
93
+ msg.isProcessed = true;
91
94
  }
92
95
  private static processFreezeProtect(msg: Inbound) {
93
96
  for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxFeatures; i++) {
@@ -95,6 +98,7 @@ export class FeatureMessage {
95
98
  var feature: Feature = sys.features.getItemById(featureId);
96
99
  feature.freeze = msg.extractPayloadByte(i + 1) > 0;
97
100
  }
101
+ msg.isProcessed = true;
98
102
  }
99
103
  private static processFeatureNames(msg: Inbound) {
100
104
  var featureId = ((msg.extractPayloadByte(1) - 6) * 2) + sys.board.equipmentIds.features.start;
@@ -109,6 +113,7 @@ export class FeatureMessage {
109
113
  if (feature.isActive) state.features.getItemById(feature.id).name = feature.name;
110
114
  }
111
115
  state.emitEquipmentChanges();
116
+ msg.isProcessed = true;
112
117
  }
113
118
  private static processEggTimerHours(msg: Inbound) {
114
119
  for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxFeatures; i++) {
@@ -116,6 +121,7 @@ export class FeatureMessage {
116
121
  let feature: Feature = sys.features.getItemById(featureId);
117
122
  feature.eggTimer = (msg.extractPayloadByte(i + 1) * 60) + ((feature.eggTimer || 0) % 60);
118
123
  }
124
+ msg.isProcessed = true;
119
125
  }
120
126
  private static processEggTimerMinutes(msg: Inbound) {
121
127
  for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxFeatures; i++) {
@@ -123,6 +129,7 @@ export class FeatureMessage {
123
129
  var feature: Feature = sys.features.getItemById(featureId);
124
130
  feature.eggTimer = (Math.floor(feature.eggTimer / 60) * 60) + msg.extractPayloadByte(i + 1);
125
131
  }
132
+ msg.isProcessed = true;
126
133
  }
127
134
  private static processShowInFeatures(msg: Inbound) {
128
135
  for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxFeatures; i++) {
@@ -132,6 +139,6 @@ export class FeatureMessage {
132
139
  if (feature.isActive) state.features.getItemById(featureId, feature.isActive).showInFeatures = feature.showInFeatures;
133
140
  }
134
141
  state.emitEquipmentChanges();
142
+ msg.isProcessed = true;
135
143
  }
136
-
137
144
  }
@@ -24,31 +24,39 @@ export class GeneralMessage {
24
24
  sys.general.alias = msg.extractPayloadString(2, 16);
25
25
  sys.general.owner.name = msg.extractPayloadString(18, 16);
26
26
  sys.general.location.zip = msg.extractPayloadString(34, 6);
27
+ msg.isProcessed = true;
27
28
  break;
28
29
  case 1:
29
30
  sys.general.owner.phone = msg.extractPayloadString(2, 20);
30
31
  sys.general.owner.phone2 = msg.extractPayloadString(21, 15);
31
32
  sys.general.location.latitude = ((msg.extractPayloadByte(35) * 256) + msg.extractPayloadByte(34)) / 100;
33
+ msg.isProcessed = true;
32
34
  break;
33
35
  case 2:
34
36
  sys.general.location.address = msg.extractPayloadString(2, 32);
35
37
  sys.general.location.longitude = -(((msg.extractPayloadByte(35) * 256) + msg.extractPayloadByte(34)) / 100);
38
+ msg.isProcessed = true;
36
39
  break;
37
40
  case 3:
38
41
  sys.general.owner.email = msg.extractPayloadString(2, 32);
39
42
  sys.general.location.timeZone = msg.extractPayloadByte(34);
43
+ msg.isProcessed = true;
40
44
  break;
41
45
  case 4:
42
46
  sys.general.owner.email2 = msg.extractPayloadString(2, 32);
47
+ msg.isProcessed = true;
43
48
  break;
44
49
  case 5:
45
50
  sys.general.location.country = msg.extractPayloadString(2, 32);
51
+ msg.isProcessed = true;
46
52
  break;
47
53
  case 6:
48
54
  sys.general.location.city = msg.extractPayloadString(2, 32);
55
+ msg.isProcessed = true;
49
56
  break;
50
57
  case 7:
51
58
  sys.general.location.state = msg.extractPayloadString(2, 32);
59
+ msg.isProcessed = true;
52
60
  break;
53
61
  default:
54
62
  logger.debug(`Unprocessed Config Message ${msg.toPacket()}`)
@@ -107,6 +107,7 @@ export class HeaterMessage {
107
107
  catch (err) { logger.error(`Error with OCP reclaiming control over gas heater: ${err}`) }
108
108
  })();
109
109
  }
110
+ heater.master = 0;
110
111
  sys.heaters.getItemById(2).isActive = false;
111
112
  sys.heaters.getItemById(3).isActive = false;
112
113
  sys.heaters.getItemById(4).isActive = false;
@@ -133,6 +134,7 @@ export class HeaterMessage {
133
134
  catch (err) { logger.error(`Error with OCP reclaiming control over Ultratemp: ${err}`) }
134
135
  })();
135
136
  }
137
+ heatPump.master = 0;
136
138
  heatPump.name = 'Ultratemp';
137
139
  heatPump.body = 32;
138
140
  heatPump.type = 4;
@@ -158,6 +160,7 @@ export class HeaterMessage {
158
160
  catch (err) { logger.error(`Error with OCP reclaiming control over heat pump: ${err}`) }
159
161
  })();
160
162
  }
163
+ heatPump.master = 0;
161
164
  heatPump.name = 'Heat Pump';
162
165
  heatPump.body = 32;
163
166
  heatPump.type = 3;
@@ -184,6 +187,7 @@ export class HeaterMessage {
184
187
  catch (err) { logger.error(`Error with OCP reclaiming control over solar heater: ${err}`) }
185
188
  })();
186
189
  }
190
+ solar.master = 0;
187
191
  solar.name = 'Solar Heater';
188
192
  solar.type = 2;
189
193
  solar.isActive = true;
@@ -215,34 +219,8 @@ export class HeaterMessage {
215
219
  }
216
220
  sys.board.heaters.syncHeaterStates();
217
221
  sys.equipment.setEquipmentIds();
222
+ msg.isProcessed = true;
218
223
  break;
219
- case 114:
220
- // something to do with heat pumps... need equipment or other packets to decipher
221
- // [ 255, 0, 255], [165, 0, 112, 16, 114, 10], [144, 2, 0, 0, 0, 0, 0, 0, 0, 0], [2, 51 ]heat + cool
222
- // [165,0,112,16,114,10][144,0,0,0,0,0,0,0,0,0][2,49] == no Heater, no cool
223
- // [165,0,112,16,114,10][144,2,0,0,0,0,0,0,0,0][2,51] == no heat, cooling
224
- // this might be heatStatus not heatMode?
225
- break;
226
- case 168:
227
- {
228
- // IntelliChem Installed
229
- if ((msg.extractPayloadByte(3) & 0x01) === 1) {
230
- // only support for 1 ic with EasyTouch
231
- let chem = sys.chemControllers.getItemByAddress(144, true);
232
- let schem = state.chemControllers.getItemById(chem.id, true);
233
- chem.ph.tank.capacity = chem.orp.tank.capacity = 6;
234
- chem.ph.tank.units = chem.orp.tank.units = '';
235
-
236
- }
237
- else {
238
- let chem = sys.chemControllers.getItemByAddress(144);
239
- state.chemControllers.removeItemById(chem.id);
240
- sys.chemControllers.removeItemById(chem.id);
241
- }
242
- // Spa Manual Heat on/off
243
- sys.general.options.manualHeat = msg.extractPayloadByte(4) === 1 ? true : false;
244
-
245
- }
246
224
  }
247
225
  }
248
226
  private static processCooldownDelay(msg: Inbound) {
@@ -261,6 +239,7 @@ export class HeaterMessage {
261
239
  })();
262
240
  }
263
241
  }
242
+ msg.isProcessed = true;
264
243
  }
265
244
 
266
245
  //private static processBody(msg: Inbound) {
@@ -293,6 +272,7 @@ export class HeaterMessage {
293
272
  catch (err) { logger.error(`Error with OCP reclaiming control over heater: ${err}`) }
294
273
  })();
295
274
  }
275
+ heater.master = 0;
296
276
  let hstate = state.heaters.getItemById(i);
297
277
  // hstate.isVirtual = false;
298
278
  hstate.name = heater.name;
@@ -300,12 +280,14 @@ export class HeaterMessage {
300
280
 
301
281
  }
302
282
  sys.board.heaters.updateHeaterServices();
283
+ msg.isProcessed = true;
303
284
  }
304
285
  private static processMaxBoostTemp(msg: Inbound) {
305
286
  for (let i = 0; i < msg.payload.length - 1 && i < sys.equipment.maxHeaters; i++) {
306
287
  var heater: Heater = sys.heaters.getItemById(i + 1);
307
288
  heater.maxBoostTemp = msg.extractPayloadByte(i + 2);
308
289
  }
290
+ msg.isProcessed = true;
309
291
  }
310
292
  private static processStartStopDelta(msg: Inbound) {
311
293
  for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxHeaters; i++) {
@@ -313,6 +295,7 @@ export class HeaterMessage {
313
295
  heater.startTempDelta = msg.extractPayloadByte(i + 1);
314
296
  heater.stopTempDelta = msg.extractPayloadByte(i + 18);
315
297
  }
298
+ msg.isProcessed = true;
316
299
  }
317
300
  private static processCoolingSetTemp(msg: Inbound) {
318
301
  for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxHeaters; i++) {
@@ -320,20 +303,22 @@ export class HeaterMessage {
320
303
  heater.coolingEnabled = msg.extractPayloadByte(i + 1) > 0;
321
304
  heater.differentialTemp = msg.extractPayloadByte(i + 18);
322
305
  }
306
+ msg.isProcessed = true;
323
307
  }
324
308
  private static processAddress(msg: Inbound) {
325
309
  for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxHeaters; i++) {
326
310
  var heater: Heater = sys.heaters.getItemById(i);
327
311
  heater.address = msg.extractPayloadByte(i + 1);
328
312
  }
313
+ msg.isProcessed = true;
329
314
  }
330
315
  private static processEfficiencyMode(msg: Inbound) {
331
316
  for (let i = 1; i < msg.payload.length - 1 && i <= sys.equipment.maxHeaters; i++) {
332
317
  var heater: Heater = sys.heaters.getItemById(i);
333
318
  heater.efficiencyMode = msg.extractPayloadByte(i + 1);
334
319
  }
320
+ msg.isProcessed = true;
335
321
  }
336
-
337
322
  private static processHeaterNames(msg: Inbound) {
338
323
  var heaterId = ((msg.extractPayloadByte(1) - 5) * 2) + 1;
339
324
  if (heaterId <= sys.equipment.maxHeaters) {
@@ -344,5 +329,6 @@ export class HeaterMessage {
344
329
  let hstate = state.heaters.getItemById(heaterId);
345
330
  hstate.name = sys.heaters.getItemById(heaterId++).name = msg.extractPayloadString(18, 16);
346
331
  }
332
+ msg.isProcessed = true;
347
333
  }
348
334
  }
@@ -138,7 +138,8 @@ export class IntellichemMessage {
138
138
  let controller = sys.chemControllers.getItemById(id, isActive, { id: i + 1, type: 1 });
139
139
  let scontroller = state.chemControllers.getItemById(controller.id, isActive);
140
140
  scontroller.isActive = controller.isActive = true;
141
- controller.isVirtual = false;
141
+ // controller.isVirtual = false;
142
+ controller.master = 0;
142
143
  if (!controller.isActive) {
143
144
  sys.chemControllers.removeItemById(controller.id);
144
145
  state.chemControllers.removeItemById(controller.id);
@@ -163,6 +164,7 @@ export class IntellichemMessage {
163
164
  }
164
165
  }
165
166
  }
167
+ msg.isProcessed = true;
166
168
  break;
167
169
  case 1:
168
170
  for (let i = 0; i < 4; i++) {
@@ -175,6 +177,7 @@ export class IntellichemMessage {
175
177
  controller.alkalinity = msg.extractPayloadInt((i * 2) + 26);
176
178
  }
177
179
  }
180
+ msg.isProcessed = true;
178
181
  break;
179
182
  }
180
183
  }
@@ -92,9 +92,21 @@ export class OptionsMessage {
92
92
  //body = sys.bodies.getItemById(4, sys.equipment.maxBodies > 3);
93
93
  //body.heatMode = msg.extractPayloadByte(27);
94
94
  //body.heatSetpoint = msg.extractPayloadByte(23);
95
+ msg.isProcessed = true;
95
96
  break;
96
97
  }
97
- case 1: // Unknown
98
+ case 1: // Vacation mode
99
+ let yy = msg.extractPayloadByte(4) + 2000;
100
+ let mm = msg.extractPayloadByte(5);
101
+ let dd = msg.extractPayloadByte(6);
102
+ sys.general.options.vacation.startDate = new Date(yy, mm - 1, dd);
103
+ yy = msg.extractPayloadByte(7) + 2000;
104
+ mm = msg.extractPayloadByte(8);
105
+ dd = msg.extractPayloadByte(9);
106
+ sys.general.options.vacation.endDate = new Date(yy, mm - 1, dd);
107
+ sys.general.options.vacation.enabled = msg.extractPayloadByte(2) > 0;
108
+ sys.general.options.vacation.useTimeframe = msg.extractPayloadByte(3) > 0;
109
+ msg.isProcessed = true;
98
110
  break;
99
111
  }
100
112
  msg.isProcessed = true;
@@ -127,6 +139,9 @@ export class OptionsMessage {
127
139
  break;
128
140
  }
129
141
  case 40:
142
+ case 168:
143
+ {
144
+
130
145
  // [165,33,16,34,168,10],[0,0,0,254,0,0,0,0,0,0],[2,168 = manual heat mode off
131
146
  // [165,33,16,34,168,10],[0,0,0,254,1,0,0,0,0,0],[2,169] = manual heat mode on
132
147
  sys.general.options.manualHeat = msg.extractPayloadByte(4) === 1;
@@ -136,7 +151,7 @@ export class OptionsMessage {
136
151
  let schem = state.chemControllers.getItemById(chem.id, true);
137
152
  chem.ph.tank.capacity = chem.orp.tank.capacity = 6;
138
153
  chem.ph.tank.units = chem.orp.tank.units = '';
139
-
154
+
140
155
  }
141
156
  else {
142
157
  let chem = sys.chemControllers.getItemByAddress(144);
@@ -145,6 +160,27 @@ export class OptionsMessage {
145
160
  }
146
161
  msg.isProcessed = true;
147
162
  break;
163
+ }
164
+ /* case 168:
165
+ {
166
+ // IntelliChem Installed
167
+ if ((msg.extractPayloadByte(3) & 0x01) === 1) {
168
+ // only support for 1 ic with EasyTouch
169
+ let chem = sys.chemControllers.getItemByAddress(144, true);
170
+ let schem = state.chemControllers.getItemById(chem.id, true);
171
+ chem.ph.tank.capacity = chem.orp.tank.capacity = 6;
172
+ chem.ph.tank.units = chem.orp.tank.units = '';
173
+
174
+ }
175
+ else {
176
+ let chem = sys.chemControllers.getItemByAddress(144);
177
+ state.chemControllers.removeItemById(chem.id);
178
+ sys.chemControllers.removeItemById(chem.id);
179
+ }
180
+ // Spa Manual Heat on/off
181
+ sys.general.options.manualHeat = msg.extractPayloadByte(4) === 1 ? true : false;
182
+ msg.isProcessed = true;
183
+ } */
148
184
  }
149
185
  }
150
186
  }
@@ -132,8 +132,10 @@ export class PumpMessage {
132
132
  }
133
133
  }
134
134
  }
135
+ msg.isProcessed = true;
135
136
  switch (msgId) {
136
137
  case 0:
138
+ msg.isProcessed = true;
137
139
  break;
138
140
  case 1:
139
141
  PumpMessage.processFlowStepSize(msg);
@@ -347,38 +349,20 @@ export class PumpMessage {
347
349
  circuit.circuit = _circuit;
348
350
  circuit.flow = msg.extractPayloadByte(circuitId * 2 + 4);
349
351
  circuit.units = 1;
350
- switch (circuit.circuit) {
351
- case 1:
352
- {
353
- let body = sys.bodies.getItemById(2, sys.equipment.maxBodies >= 2);
354
- let sbody = state.temps.bodies.getItemById(2, sys.equipment.maxBodies >= 2);
355
- sbody.type = body.type = 1; // spa
356
- body.isActive = true;
357
- break;
358
- }
359
- case 6:
360
- {
361
- let body = sys.bodies.getItemById(1, sys.equipment.maxBodies >= 1);
362
- let sbody = state.temps.bodies.getItemById(1, sys.equipment.maxBodies >= 1);
363
- sbody.type = body.type = 0; // pool
364
- body.isActive = true;
365
- body.capacity = msg.extractPayloadByte(6) * 1000;
366
- break;
367
- }
368
- }
369
352
  }
370
353
  else {
371
354
  pump.circuits.removeItemById(_circuit);
372
355
  }
373
356
  }
374
357
  pump.backgroundCircuit = msg.extractPayloadByte(1);
358
+ pump.filterSize = msg.extractPayloadByte(2) * 1000;
375
359
  pump.turnovers = msg.extractPayloadByte(3);
360
+ pump.manualFilterGPM = msg.extractPayloadByte(21);
376
361
  pump.primingSpeed = msg.extractPayloadByte(22);
377
362
  pump.primingTime = (msg.extractPayloadByte(23) & 0xf);
378
363
  pump.minFlow = sys.board.valueMaps.pumpTypes.get(pump.type).minFlow;
379
364
  pump.maxFlow = sys.board.valueMaps.pumpTypes.get(pump.type).maxFlow;
380
365
  pump.flowStepSize = sys.board.valueMaps.pumpTypes.get(pump.type).flowStepSize;
381
- pump.manualFilterGPM = msg.extractPayloadByte(21);
382
366
  pump.maxSystemTime = msg.extractPayloadByte(23) >> 4;
383
367
  pump.maxPressureIncrease = msg.extractPayloadByte(24);
384
368
  pump.backwashFlow = msg.extractPayloadByte(25);
@@ -93,6 +93,7 @@ export class RemoteMessage {
93
93
  if (!remote.button1 && !remote.button2 && !remote.button3 && !remote.button4) remote.isActive = false;
94
94
  else remote.isActive = true;
95
95
  remote.name = "QuickTouch";
96
+ msg.isProcessed = true;
96
97
  break;
97
98
  }
98
99
  case 32: // is4/is10
@@ -120,6 +121,7 @@ export class RemoteMessage {
120
121
  remote.type = 1;
121
122
  remote.name = "is4";
122
123
  }
124
+ msg.isProcessed = true;
123
125
  break;
124
126
  }
125
127
  case 22: // Spa Command spa side remote additional config
@@ -132,6 +134,7 @@ export class RemoteMessage {
132
134
  remote.pumpId = msg.extractPayloadByte(5);
133
135
  remote.stepSize = msg.extractPayloadByte(6);
134
136
  remote.type = 7;
137
+ msg.isProcessed = true;
135
138
  break;
136
139
  }
137
140
  }
@@ -187,5 +190,6 @@ export class RemoteMessage {
187
190
  }
188
191
  remote["button" + (i + 1)] = msg.extractPayloadByte(i + 2);
189
192
  }
193
+ msg.isProcessed = true;
190
194
  }
191
195
  }