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
@@ -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
@@ -56,9 +57,10 @@ export class ValveMessage {
56
57
  case ControllerType.IntelliCom:
57
58
  case ControllerType.EasyTouch:
58
59
  case ControllerType.IntelliTouch:
60
+ case ControllerType.SunTouch:
59
61
  switch (msg.action) {
60
62
  case 29:
61
- ValveMessage.process_ValveAssignment_IT(msg);
63
+ sys.controllerType === ControllerType.SunTouch ? ValveMessage.process_ValveAssignment_ST(msg) : ValveMessage.process_ValveAssignment_IT(msg);
62
64
  break;
63
65
  case 35:
64
66
  ValveMessage.process_ValveOptions_IT(msg);
@@ -73,19 +75,38 @@ export class ValveMessage {
73
75
  sys.general.options.pumpDelay = msg.extractPayloadByte(0) >> 7 === 1;
74
76
  msg.isProcessed = true;
75
77
  }
78
+ private static process_ValveAssignment_ST(msg: Inbound) {
79
+ // SunTouch example
80
+ //[165,1,15,16,29,24][2,0,0,0,20,255,255,1,2,3,4,1,72,0,0,0,3,0,0,63,4,0,0,0][3,167]
81
+ let vA = sys.valves.getItemById(1, true);
82
+ let vB = sys.valves.getItemById(2, true);
83
+ let vC = sys.valves.getItemById(3, true);
84
+ if (sys.equipment.shared && !sys.equipment.single) {
85
+ vA.name = 'Intake';
86
+ vB.circuit = vA.circuit = sys.board.valueMaps.virtualCircuits.encode('poolspa');
87
+ vB.name = 'Return';
88
+ }
89
+ else {
90
+ vA.name = 'Valve A';
91
+ vB.name = 'Valve B';
92
+ vA.circuit = msg.extractPayloadByte(1);
93
+ vB.circuit = msg.extractPayloadByte(2);
94
+ }
95
+ vC.circuit = msg.extractPayloadByte(4);
96
+ vC.name = 'Valve C'
97
+ }
76
98
  private static process_ValveAssignment_IT(msg: Inbound) {
77
99
  // sample packet
78
- // 165,33,16,34,157,6,0,0,1,255,255,255,4,153 [set]
100
+ // [165,33,16,34,157,6],[0,0,1,255,255,255],[4,153] [set]
101
+ // [165,33,16,34,157,6],[0,0,7,255,255,255],[4,159]] [set]
79
102
  // [165,33,15,16,29,24],[2,0,0,0,128,1,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[4,154] [get]
80
- // [[][255,0,255][165,33,16,34,157,6][0,0,7,255,255,255][4,159]] [set]
81
103
  // what is payload[0]?
82
104
  for (let ndx = 4, id = 1; id <= sys.equipment.maxValves; ndx++) {
83
- let valve: Valve = sys.valves.getItemById(id);
84
105
  if (id === 3) {
85
- if (sys.equipment.shared) {
86
- valve = sys.valves.getItemById(id, true);
106
+ if (sys.equipment.shared && !sys.equipment.single) {
107
+ let valve: Valve = sys.valves.getItemById(id);
87
108
  valve.circuit = 6; // pool/spa -- fix
88
- valve.name = ValveMessage.getName(id, valve.circuit);
109
+ valve.name = 'Intake';
89
110
  valve.isIntake = true;
90
111
  valve.isReturn = false;
91
112
  valve.isActive = true;
@@ -99,13 +120,12 @@ export class ValveMessage {
99
120
  sys.valves.removeItemById(id);
100
121
  state.valves.removeItemById(id);
101
122
  }
102
- id++;
103
123
  }
104
124
  else if (id === 4) {
105
- if (sys.equipment.shared) {
106
- valve = sys.valves.getItemById(id, true);
125
+ if (sys.equipment.shared && !sys.equipment.single) {
126
+ let valve: Valve = sys.valves.getItemById(id);
107
127
  valve.circuit = 6; // pool/spa -- fix
108
- valve.name = ValveMessage.getName(id, valve.circuit);
128
+ valve.name = 'Return';
109
129
  valve.isIntake = false;
110
130
  valve.isReturn = true;
111
131
  valve.isActive = true;
@@ -119,40 +139,37 @@ export class ValveMessage {
119
139
  sys.valves.removeItemById(id);
120
140
  state.valves.removeItemById(id);
121
141
  }
122
- id++;
123
142
  }
124
143
  else {
125
- valve = sys.valves.getItemById(id, true);
144
+ let valve: Valve = sys.valves.getItemById(id);
126
145
  let circ = msg.extractPayloadByte(ndx);
127
146
  valve.circuit = circ > 0 && circ < 255 ? circ : 0;
128
- valve.circuit = msg.extractPayloadByte(ndx);
147
+ //valve.circuit = msg.extractPayloadByte(ndx);
129
148
  //valve.isActive = valve.circuit > 0 && valve.circuit < 255;
130
149
  // RKS: 04-14-21 -- Valves should always be active but shown with no assignment when
131
150
  // there is no circuit. The circuitry for the valve always exists although I am not sure
132
151
  // how the valve expansion is represented.
133
152
  valve.isActive = true;
134
- valve.isReturn = false;
153
+ valve.isReturn = false;
135
154
  valve.isIntake = false;
136
155
  valve.type = 0;
156
+ valve.master = 0;
137
157
  // Allow users to name the valve whatever they want. *Touch apparently only allows the valve to be named the same
138
158
  // as the circuit but this should be fine if we allow the user to edit it.
139
159
  valve.name = (typeof valve.name === 'undefined') ? ValveMessage.getName(id, valve.circuit) : valve.name;
140
160
  let svalve = state.valves.getItemById(id, true);
141
161
  svalve.name = valve.name;
142
- svalve.type = valve.type;
143
- valve.master = 0;
144
- }
145
- if (!valve.isActive) {
146
- sys.valves.removeItemById(id);
147
- state.valves.removeItemById(id);
148
- }
149
- else {
150
- valve.master = 0;
151
- // valve.isVirtual = false;
152
- valve.type = 0;
153
162
  }
154
163
  id++;
155
164
  }
165
+ // Clean up any valves that are leftovers from previous configs.
166
+ for (let i = sys.valves.length - 1; i >= 0; i--) {
167
+ let v = sys.valves.getItemByIndex(i);
168
+ if (v.master === 0 && v.id > sys.equipment.maxValves) {
169
+ sys.valves.removeItemByIndex(i);
170
+ state.valves.removeItemById(v.id);
171
+ }
172
+ }
156
173
  msg.isProcessed = true;
157
174
  }
158
175
  private static getName(id: number, cir: number) {
@@ -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
@@ -21,41 +22,44 @@ import { sys, ControllerType, Chlorinator } from "../../../Equipment";
21
22
  export class ChlorinatorStateMessage {
22
23
  public static process(msg: Inbound) {
23
24
  if (msg.protocol === Protocol.Chlorinator) {
24
- let chlor: Chlorinator;
25
- let cstate: ChlorinatorState;
26
-
27
- if (msg.dest >= 1 && msg.dest <= 4) {
28
- // RKS: The dest for these message are 80+ in raw terms. The msg object translates these into 1-4 for the installed chlorinators. This message
29
- // is from the OCP to the chlorinator.
30
- cstate = state.chlorinators.getItemById(msg.dest, true);
25
+ // RKS: 03-29-22 A lot of water has gone under the bridge at this point and we know much more. First there are two types of messages. Those inbound
26
+ // messages that are being sent to the chlorinator as commands and responses from the chlorinator. We have also determined that the chlorinator does
27
+ // not actually support a RS485 address. So njsPC can declare as many ports as required to communicate with multiple chlorinators.
28
+ //
29
+ // So instead of matching the chlorinator up with a specific id we need to match on the port as well for the inbound message. OCPs always operate on
30
+ // portId = 0. If the portId is > 0 then it is considered an Aux port. At this point you can only control 1 chlorinator per port so in order to
31
+ // control more than one chlorinator there needs to be only one chlorinator on each port.
32
+ let chlor: Chlorinator = sys.chlorinators.findItemByPortId(msg.portId || 0);
33
+ if (typeof chlor === 'undefined' || chlor.isActive === false) return; // Bail out of here if we don't find an active chlorinator.
34
+ let cstate: ChlorinatorState = state.chlorinators.getItemById(chlor.id, true);
35
+ if (msg.dest >= 80 && msg.dest <= 83) {
36
+ // RKS: This message is from the OCP to the chlorinator. NOTE: We will not see these messages when the communication is coming from njsPC on any
37
+ // comms port. The processing for no comms is done in the Nixe control when the message is sent.
31
38
  if (typeof cstate.lastComm === 'undefined') cstate.lastComm = new Date(1970, 0, 1, 0, 0, 0, 0).getTime();
32
39
  // RG: I was getting some time deltas of 25-30s and bumped this up
33
40
  else if (cstate.lastComm + (30 * 1000) < new Date().getTime()) {
34
41
  // We have not talked to the chlorinator in 30 seconds so we have lost communication.
35
42
  cstate.status = 128;
36
43
  }
37
- chlor = sys.chlorinators.getItemById(msg.dest, true);
38
- chlor.address = msg.dest + 79;
44
+ // chlor = sys.chlorinators.getItemById(msg.dest - 79, true); chlor is retrieved above; don't get in incorrectly here.
45
+ chlor.address = msg.dest; // Theoretically, this will always be 80.
39
46
  if (typeof chlor.isActive === 'undefined') cstate.isActive = chlor.isActive = true;
40
47
  }
41
48
  else {
42
- // Message from chlorinator
43
- cstate = state.chlorinators.getItemById(msg.dest + 1, true);
44
- chlor = sys.chlorinators.getItemById(msg.dest + 1, true);
49
+ // Response message from chlorinator. If the chlorinator is speaking to us then we need to hear it and clear the status when
50
+ // the previous status was no comms.
45
51
  cstate.lastComm = new Date().getTime();
46
52
  if (cstate.status === 128) cstate.status = 0;
47
53
  }
48
54
  cstate.body = chlor.body;
49
55
  switch (msg.action) {
50
- case 0: // request status (0): [16,2,80,0][0][98,16,3]
56
+ case 0: // Set control OCP->Chlorinator: [16,2,80,0][0][98,16,3]
51
57
  break;
52
- case 1: // response to request status: [16,2,0,1][0,0][19,16,3]
53
- {
54
- // let chlor = sys.chlorinators.getItemById(1, true);
55
- // chlor.isActive = true;
56
- break;
57
- }
58
- case 3: {
58
+ case 1: // Ack control Chlorinator->OCP response: [16,2,0,1][0,0][19,16,3]
59
+ // let chlor = sys.chlorinators.getItemById(1, true);
60
+ // chlor.isActive = true;
61
+ break;
62
+ case 3: // Chlorinator->OCP response for Get Model: [16,2,0,3][0,73,110,116,101,108,108,105,99,104,108,111,114,45,45,52,48][188,16,3]
59
63
  // RKS: 07-16-20 -- It appears that this message doesn't always come. It is very likely that the newer versions of IntelliChlor
60
64
  // do not respond to the 20 message. There have been multiple instances of this with recent versions of IntelliChlor. As a result,
61
65
  // don't overwrite the name should the user set it.
@@ -65,12 +69,11 @@ export class ChlorinatorStateMessage {
65
69
  // This is the model number of the chlorinator and the address is actually the second byte.
66
70
  let name = msg.extractPayloadString(1, 16);
67
71
  if (typeof chlor.name === 'undefined' || chlor.name === '') chlor.name = cstate.name = name;
68
- if (typeof chlor.model === 'undefined') chlor.model = sys.board.valueMaps.chlorinatorModel.getValue(name.toLowerCase());
72
+ if (typeof chlor.model === 'undefined' || chlor.model === 0) chlor.model = sys.board.valueMaps.chlorinatorModel.getValue(name.toLowerCase());
69
73
  cstate.isActive = chlor.isActive;
70
74
  state.emitEquipmentChanges();
71
75
  break;
72
- }
73
- case 17: {
76
+ case 17: // OCP->Chlorinator set output. [16,2,80,17][15][130,16,3]
74
77
  // If the chlorinator is no longer talking to us then clear the current output.
75
78
  if (cstate.status === 128) cstate.currentOutput = 0;
76
79
  cstate.targetOutput = msg.extractPayloadByte(0);
@@ -78,13 +81,16 @@ export class ChlorinatorStateMessage {
78
81
  // Some dumbass is trying to change our output. We need to set it back to 0.
79
82
  sys.board.chlorinator.setChlorAsync({ id: chlor.id, disabled: chlor.disabled, superChlor: false, superChlorHours: 0 });
80
83
  }
81
- else if (chlor.isDosing && cstate.targetOutput !== 100){
84
+ else if (chlor.isDosing && cstate.targetOutput !== 100) {
82
85
  sys.board.chlorinator.setChlorAsync({ id: chlor.id, isDosing: chlor.isDosing });
83
86
  }
84
87
  state.emitEquipmentChanges();
85
88
  break;
86
- }
87
- case 21: {
89
+ case 21: // Set output OCP->Chlorinator [16,2,80,21][0][119,16,3]
90
+ // RKS: 03-29-22 There is something absolutley wrong about the understanding of this message. It has to do with the fact that you could never set
91
+ // the output percentage to anything greater than 25.6% if this were the case. I assume this has something to do with the
92
+ // way IntelliChlor works. Values between 0 and 20% can be fractional. In this case the OCP would send a 21 instead of a 17 with
93
+ // the fractional value. Anything above that value will be sent in a 17 message.
88
94
  // Set Cell Output / 10
89
95
  // This packet is coming through differently on the IntelliConnect.
90
96
  // eg 13:42:31.304 VERBOSE Msg# 1531 Controller --> Salt cell: Set current output to 1.6 %: 16,2,80,21,0,119,16,3
@@ -95,34 +101,31 @@ export class ChlorinatorStateMessage {
95
101
  // Some dumbass is trying to change our output. We need to set it back to 0.
96
102
  sys.board.chlorinator.setChlorAsync({ id: chlor.id, disabled: chlor.disabled, superChlor: false, superChlorHours: 0 });
97
103
  }
98
- else if (chlor.isDosing && cstate.targetOutput !== 100){
104
+ else if (chlor.isDosing && cstate.targetOutput !== 100) {
99
105
  sys.board.chlorinator.setChlorAsync({ id: chlor.id, isDosing: chlor.isDosing });
100
106
  }
101
107
  state.emitEquipmentChanges();
102
108
  break;
103
- }
104
- case 18: {
109
+ case 18:
105
110
  // Response to Set Salt Output (17 & 20)
106
111
  // The most common failure with IntelliChlor is that the salt level stops reporting. Below should allow it to be fed from an alternate
107
112
  // source like REM.
108
- if(!chlor.ignoreSaltReading) cstate.saltLevel = msg.extractPayloadByte(0) * 50 || cstate.saltLevel || 0;
113
+ if (!chlor.ignoreSaltReading) cstate.saltLevel = msg.extractPayloadByte(0) * 50 || cstate.saltLevel || 0;
109
114
  cstate.status = (msg.extractPayloadByte(1) & 0x007F); // Strip off the high bit. The chlorinator does not actually report this.
110
115
  cstate.currentOutput = chlor.disabled ? 0 : cstate.setPointForCurrentBody;
111
116
  state.emitEquipmentChanges();
112
117
  break;
113
- }
114
- case 19: {
118
+ case 19:
115
119
  // This is an iChlor message with no payload. Perhaps simply a keep alive for the iChlor.
116
120
  // [16, 2, 80, 19][117, 16, 3]
117
121
  break;
118
- }
119
- case 20: {
120
- // Get version
121
- chlor.type = cstate.type = msg.extractPayloadByte(0);
122
+ case 20:
123
+ // OCP->Chlorinator Get model [16,2,80,20][0][118,16,3]
124
+ if (typeof chlor.type === 'undefined') chlor.type = msg.extractPayloadByte(0);
125
+ cstate.type = chlor.type;
122
126
  state.emitEquipmentChanges();
123
127
  break;
124
- }
125
- case 22: {
128
+ case 22: // Chlorinator->OCP this is actually an iChlor message and has no bearing on IntelliConnect.
126
129
  // temp and output as seen from IntelliConnect.
127
130
  // Issue #157 - https://github.com/tagyoureit/nodejs-poolController/issues/157
128
131
  // [10 02, 10, 16], [00, 0f, 49, 00,05, 10], [85, 10,03] = hex
@@ -134,64 +137,14 @@ export class ChlorinatorStateMessage {
134
137
  // Set it back to disabled. Some asshole is futzing with the chlorinator output.
135
138
  sys.board.chlorinator.setChlorAsync({ id: chlor.id, disabled: true });
136
139
  }
137
- if (sys.controllerType === ControllerType.Virtual) {
138
- // This lets the iChlor use the temp probe from the
140
+ if (sys.controllerType === ControllerType.Nixie) {
141
+ // This lets the current body use the iChlor temp probe
139
142
  let tbody: BodyTempState = sys.pumps.length > 0 ? state.temps.bodies.getBodyIsOn() : state.temps.bodies.getItemById(1, true);
140
143
  if (msg.extractPayloadByte(2) >= 40 && typeof tbody !== 'undefined') tbody.temp = msg.extractPayloadByte(2);
141
144
  }
142
145
  state.emitEquipmentChanges();
143
146
  break;
144
- }
145
147
  }
146
148
  }
147
- // question: does IntelliCenter ever broadcast Chlorinator packet? Answer: Never. My guess is that this is actually
148
- // a configuration message rather than a status message. Also, IntelliCenter has a 204 extension status that contains
149
- // the current countdown timer for the superChlor in the last 2 bytes. Perhaps this is the equivalent.
150
- //else if (msg.protocol === Protocol.Broadcast) {
151
- // if (!state.isInitialized) return;
152
- // // sample packet
153
- // // [165,33,15,16,25,22],[1,10,128,29,132,0,73,110,116,101,108,108,105,99,104,108,111,114,45,45,52,48],[7,231]
154
- // let chlorId = 1;
155
- // let chlor = sys.chlorinators.getItemById(chlorId, true);
156
- // if (chlor.isVirtual) { return; } // shouldn't get here except for testing Chlor on *Touch system.
157
- // // installed = (aaaaaaa)1 so 1 = installed
158
- // chlor.isActive = (msg.extractPayloadByte(0) & 0x01) === 1;
159
- // if (chlor.isActive) {
160
- // // RSG : making the assumption here that the chlorinator will be tied to the pool in any system that is not a shared body
161
- // sys.equipment.maxBodies >= 1 || sys.equipment.shared === true ? chlor.body = 32 : chlor.body = 0;
162
- // // outputSpaPercent field is aaaaaaab (binary) where aaaaaaa = % and b===installed (0=no,1=yes)
163
- // // eg. a value of 41 is 00101001
164
- // // spa percent = 0010100(b) so 10100 = 20
165
- // if (!chlor.disabled) {
166
- // // RKS: We don't want these setpoints if our chem controller disabled the
167
- // // chlorinator. These should be 0 anyway.
168
- // chlor.spaSetpoint = msg.extractPayloadByte(0) >> 1;
169
- // chlor.poolSetpoint = msg.extractPayloadByte(1);
170
- // }
171
- // chlor.address = chlor.id + 79;
172
- // chlor.superChlor = msg.extractPayloadByte(5) > 0;
173
- // chlor.superChlorHours = msg.extractPayloadByte(5);
174
- // chlor.name = msg.extractPayloadString(6, 16);
175
- // let schlor = state.chlorinators.getItemById(chlorId, true);
176
- // // The most common failure with IntelliChlor is that the salt level stops reporting. Below should allow it to be fed from an alternate
177
- // // source like REM.
178
- // schlor.saltLevel = msg.extractPayloadByte(3) * 50 || schlor.saltLevel || 0;
179
- // schlor.status = msg.extractPayloadByte(4) & 0x007F; // Strip off the high bit. The chlorinator does not actually report this.;
180
- // schlor.lastComm = new Date().getTime(); // rely solely on "true" chlor messages for this?
181
- // schlor.poolSetpoint = chlor.poolSetpoint;
182
- // schlor.spaSetpoint = chlor.spaSetpoint;
183
- // schlor.superChlor = chlor.superChlor;
184
- // schlor.superChlorHours = chlor.superChlorHours;
185
- // schlor.name = chlor.name;
186
- // schlor.body = chlor.body;
187
- // if (state.temps.bodies.getItemById(1).isOn) schlor.targetOutput = chlor.disabled ? 0 : chlor.poolSetpoint;
188
- // else if (state.temps.bodies.getItemById(2).isOn) schlor.targetOutput = chlor.disabled ? 0 : chlor.spaSetpoint;
189
- // state.emitEquipmentChanges();
190
- // }
191
- // else {
192
- // sys.chlorinators.removeItemById(chlorId);
193
- // state.chlorinators.removeItemById(chlorId);
194
- // }
195
- //}
196
149
  }
197
150
  }