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
@@ -0,0 +1,437 @@
1
+ {
2
+ "context": {
3
+ "name": "Home Assistant",
4
+ "type": "mqtt",
5
+ "options": {
6
+ "formatter": [
7
+ {
8
+ "transform": ".toLowerCase()"
9
+ },
10
+ {
11
+ "regexkey": "\\s",
12
+ "replace": "",
13
+ "description": "Remove whitespace"
14
+ },
15
+ {
16
+ "regexkey": "\\/",
17
+ "replace": "",
18
+ "description": "Remove /"
19
+ },
20
+ {
21
+ "regexkey": "\\+",
22
+ "replace": "",
23
+ "description": "Remove +"
24
+ },
25
+ {
26
+ "regexkey": "\\$",
27
+ "replace": "",
28
+ "description": "Remove $"
29
+ },
30
+ {
31
+ "regexkey": "\\#",
32
+ "replace": "",
33
+ "description": "Remove #"
34
+ }
35
+ ],
36
+ "rootTopic-DIRECTIONS": "rootTopic in config.json is ingored. Instead set the two topic variables in the vars section",
37
+ "_rootTopic": "@bind=(state.equipment.model).replace(' ','-').replace(' / ','').toLowerCase();",
38
+ "clientId": "@bind=`hass_njsPC_${webApp.mac().replace(/:/g, '_'}-${webApp.httpPort()}`;"
39
+ }
40
+ },
41
+ "events": [
42
+ {
43
+ "name": "circuit",
44
+ "description": "Populate the circuits topics",
45
+ "topics": [
46
+ {
47
+ "topic": "@bind=vars.hassTopic;/switch/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.id;-@bind=data.name;/config",
48
+ "useRootTopic": false,
49
+ "processor": [
50
+ "let device_id = {",
51
+ " name: 'Pool Controller - njsPC',",
52
+ " ids: [`${ctx.vars.mqttTopic}`],",
53
+ " suggested_area : 'Pool'};",
54
+ "let icontype='mdi:toggle-switch-variant';",
55
+ "if (data.type.val==1) {icontype='mdi:hot-tub'};",
56
+ "if (data.type.val==2) {icontype='mdi:pool'};",
57
+ "return JSON.stringify({ name: data.name,",
58
+ "unique_id: `poolController-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}`,",
59
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
60
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
61
+ "state_topic: `${ctx.vars.mqttTopic}/state/circuits/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}`,",
62
+ "command_topic: `${ctx.vars.mqttTopic}/state/circuits/setState`,",
63
+ "payload_on: `{\"id\": ${data.id}, \"isOn\": true}`,",
64
+ "payload_off: `{\"id\": ${data.id}, \"isOn\": false}`,",
65
+ "state_on: `on`,",
66
+ "state_off: `off`,",
67
+ "device: device_id,",
68
+ "device_class: 'switch',",
69
+ "icon: icontype,",
70
+ "value_template:'{{value_json.isOn}}'});"
71
+ ],
72
+ "filter": "@bind=data.showInFeatures; === true && @bind=data.type.isLight; !== true"
73
+ },
74
+ {
75
+ "topic": "@bind=vars.hassTopic;/light/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.id;-@bind=data.name;/config",
76
+ "useRootTopic": false,
77
+ "processor": [
78
+ "let device_id = {",
79
+ " name : 'Pool Controller - njsPC',",
80
+ " ids: [`${ctx.vars.mqttTopic}`],",
81
+ " suggested_area : 'Pool'};",
82
+ "return JSON.stringify({ name: `Pool ${data.name}`,",
83
+ "unique_id: `poolController-${data.id}-pool${data.name.replace(/\\s+/g, '').toLowerCase()}`,",
84
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
85
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
86
+ "schema: 'template',",
87
+ "command_topic: `${ctx.vars.mqttTopic}/state/circuits/setState`,",
88
+ "state_topic: `${ctx.vars.mqttTopic}/state/circuits/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}`,",
89
+ "device: device_id,",
90
+ "command_on_template: `{\"id\": ${data.id}, \"isOn\": true}`,",
91
+ "command_off_template: `{\"id\": ${data.id}, \"isOn\": false}`,",
92
+ "state_template: '{{value_json.isOn}}'});"
93
+ ],
94
+ "filter": "@bind=data.showInFeatures; === true && @bind=data.type.isLight; === true"
95
+ }
96
+ ]
97
+ },
98
+ {
99
+ "name": "pump",
100
+ "description": "Populate the pumps topics",
101
+ "topics": [
102
+ {
103
+ "topic": "@bind=vars.hassTopic;/sensor/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.id;-@bind=data.name;-rpm/config",
104
+ "useRootTopic": false,
105
+ "processor": [
106
+ "let device_id = {",
107
+ " name : 'Pool Controller - njsPC',",
108
+ " ids: [`${ctx.vars.mqttTopic}`],",
109
+ " suggested_area : 'Pool'};",
110
+ "return JSON.stringify({ name: `${data.name} RPM`,",
111
+ "unique_id: `poolController-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}-rpm`,",
112
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
113
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
114
+ "state_topic: `${ctx.vars.mqttTopic}/state/pumps/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/rpm`,",
115
+ "device: device_id,",
116
+ "icon: 'mdi:pump',",
117
+ "state_class: 'measurement',",
118
+ "unit_of_measurement: 'rpm',",
119
+ "value_template:'{{value_json.rpm}}'});"
120
+ ]
121
+ },
122
+ {
123
+ "topic": "@bind=vars.hassTopic;/sensor/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.id;-@bind=data.name;-watts/config",
124
+ "useRootTopic": false,
125
+ "processor": [
126
+ "let device_id = {",
127
+ " name : 'Pool Controller - njsPC',",
128
+ " ids: [`${ctx.vars.mqttTopic}`],",
129
+ " suggested_area : 'Pool'};",
130
+ "return JSON.stringify({ name: `${data.name} watts`,",
131
+ "unique_id: `poolController-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}-watts`,",
132
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
133
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
134
+ "state_topic: `${ctx.vars.mqttTopic}/state/pumps/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/watts`,",
135
+ "device: device_id,",
136
+ "icon: 'mdi:lightning-bolt',",
137
+ "unit_of_measurement: 'W',",
138
+ "state_class: 'measurement',",
139
+ "device_class: 'power',",
140
+ "value_template:'{{value_json.watts}}'});"
141
+ ]
142
+ },
143
+ {
144
+ "topic": "@bind=vars.hassTopic;/sensor/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.id;-@bind=data.name;-flow/config",
145
+ "useRootTopic": false,
146
+ "processor": [
147
+ "let device_id = {",
148
+ " name : 'Pool Controller - njsPC',",
149
+ " ids: [`${ctx.vars.mqttTopic}`],",
150
+ " suggested_area : 'Pool'};",
151
+ "return JSON.stringify({ name: `${data.name} flow`,",
152
+ "unique_id: `poolController-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}-flow`,",
153
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
154
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
155
+ "state_topic: `${ctx.vars.mqttTopic}/state/pumps/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/flow`,",
156
+ "device: device_id,",
157
+ "icon: 'mdi:waves-arrow-right',",
158
+ "state_class: 'measurement',",
159
+ "unit_of_measurement: 'gpm',",
160
+ "value_template:'{{value_json.flow}}'});"
161
+ ]
162
+ }
163
+ ]
164
+ },
165
+ {
166
+ "name": "feature",
167
+ "description": "Populate the feature topics",
168
+ "topics": [
169
+ {
170
+ "topic": "@bind=vars.hassTopic;/switch/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.id;-@bind=data.name;/config",
171
+ "useRootTopic": false,
172
+ "processor": [
173
+ "let device_id = {",
174
+ " name : 'Pool Controller - njsPC',",
175
+ " ids: [`${ctx.vars.mqttTopic}`],",
176
+ " suggested_area : 'Pool'};",
177
+ "return JSON.stringify({ name: data.name,",
178
+ "unique_id: `poolController-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}`,",
179
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
180
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
181
+ "state_topic: `${ctx.vars.mqttTopic}/state/features/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}`,",
182
+ "command_topic: `${ctx.vars.mqttTopic}/state/features/setState`,",
183
+ "payload_on: `{\"id\": ${data.id}, \"isOn\": true}`,",
184
+ "payload_off: `{\"id\": ${data.id}, \"isOn\": false}`,",
185
+ "state_on: `on`,",
186
+ "state_off: `off`,",
187
+ "device: device_id,",
188
+ "device_class: 'switch',",
189
+ "value_template:'{{value_json.isOn}}'});"
190
+ ],
191
+ "filter": "@bind=data.showInFeatures; === true"
192
+ }
193
+ ]
194
+ },
195
+ {
196
+ "name": "circuitGroup",
197
+ "description": "Populate the circuitGroup topics",
198
+ "topics": [
199
+ {
200
+ "topic": "@bind=vars.hassTopic;/switch/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.id;-@bind=data.name;/config",
201
+ "useRootTopic": false,
202
+ "processor": [
203
+ "let device_id = {",
204
+ " name : 'Pool Controller - njsPC',",
205
+ " ids: [`${ctx.vars.mqttTopic}`],",
206
+ " suggested_area : 'Pool'};",
207
+ "return JSON.stringify({ name: data.name,",
208
+ "unique_id: `poolController-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}`,",
209
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
210
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
211
+ "state_topic: `${ctx.vars.mqttTopic}/state/circuitGroups/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}`,",
212
+ "command_topic: `${ctx.vars.mqttTopic}/state/circuitGroups/setState`,",
213
+ "payload_on: `{\"id\": ${data.id}, \"isOn\": true}`,",
214
+ "payload_off: `{\"id\": ${data.id}, \"isOn\": false}`,",
215
+ "state_on: `on`,",
216
+ "state_off: `off`,",
217
+ "device: device_id,",
218
+ "device_class: 'switch',",
219
+ "value_template:'{{value_json.isOn}}'});"
220
+ ],
221
+ "filter": "@bind=data.showInFeatures; === true"
222
+ }
223
+ ]
224
+ },
225
+ {
226
+ "name": "body",
227
+ "description": "Populate the pool body/heater topics",
228
+ "topics": [
229
+ {
230
+ "topic": "@bind=vars.hassTopic;/climate/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.id;-@bind=data.name;/config",
231
+ "useRootTopic": false,
232
+ "processor": [
233
+ "let device_id = {",
234
+ " name : 'Pool Controller - njsPC',",
235
+ " ids: [`${ctx.vars.mqttTopic}`],",
236
+ " suggested_area : 'Pool'};",
237
+ "return JSON.stringify({ name: `${data.name} Heater`,",
238
+ "unique_id: `poolController-body-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}`,",
239
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
240
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
241
+ "action_topic: `${ctx.vars.mqttTopic}/state/temps/bodies/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/heatStatus`,",
242
+ "action_template: `{{ 'off' if value_json.heatStatus.val==0 else 'heating' }}`,",
243
+ "device: device_id,",
244
+ "modes: ['off', 'heat'],",
245
+ "mode_command_template: `{\"id\": ${data.id}, \"mode\": {{0 if value=='off' else 1}}}`,",
246
+ "mode_command_topic: `${ctx.vars.mqttTopic}/state/body/heatmode`,",
247
+ "mode_state_template: `{{ 'off' if value_json.heatMode.val==0 else 'heat' }}`,",
248
+ "mode_state_topic: `${ctx.vars.mqttTopic}/state/temps/bodies/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/heatMode`,",
249
+ "max_temp: `${(state.temps.data.units.name === 'F') ? 104.0 : 40.0}`,",
250
+ "min_temp: `${(state.temps.data.units.name === 'F') ? 65.0 : 18.0}`,",
251
+ "temperature_command_template: `{\"id\": ${data.id}, \"setPoint\": {{value}}}`,",
252
+ "temperature_command_topic: `${ctx.vars.mqttTopic}/state/body/setpoint`,",
253
+ "temperature_state_template: '{{value_json.setPoint}}',",
254
+ "temperature_state_topic: `${ctx.vars.mqttTopic}/state/temps/bodies/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/setPoint`,",
255
+ "temperature_unit: `${state.temps.data.units.name}`,",
256
+ "current_temperature_topic: `${ctx.vars.mqttTopic}/state/temps/bodies/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/temp`,",
257
+ "current_temperature_template: '{{value_json.temp}}'});"
258
+ ]
259
+ }
260
+ ]
261
+ },
262
+ {
263
+ "name": "temps",
264
+ "description": "Populate the temp sensor",
265
+ "topics": [
266
+ {
267
+ "topic": "@bind=vars.hassTopic;/sensor/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-1-airsensor/config",
268
+ "useRootTopic": false,
269
+ "processor": [
270
+ "let device_id = {",
271
+ " name : 'Pool Controller - njsPC',",
272
+ " ids: [`${ctx.vars.mqttTopic}`],",
273
+ " suggested_area : 'Pool'};",
274
+ "return JSON.stringify({ name: `Air temp`,",
275
+ "unique_id: `poolController-1-airsensor`,",
276
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
277
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
278
+ "device: device_id,",
279
+ "device_class: 'temperature',",
280
+ "state_class: 'measurement',",
281
+ "state_topic: `${ctx.vars.mqttTopic}/state/temps/air`,",
282
+ "unit_of_measurement: `°${state.temps.data.units.name}`,",
283
+ "value_template: '{{value_json.temp}}'});"
284
+ ]
285
+ }
286
+ ]
287
+ },
288
+ {
289
+ "name": "chemController",
290
+ "description": "Populate the chem controllers",
291
+ "topics": [
292
+ {
293
+ "topic": "@bind=vars.hassTopic;/sensor/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.name;-ph/config",
294
+ "useRootTopic": false,
295
+ "processor": [
296
+ "let device_id = {",
297
+ " name : 'Pool Controller - njsPC',",
298
+ " ids: [`${ctx.vars.mqttTopic}`],",
299
+ " suggested_area : 'Pool'};",
300
+ "return JSON.stringify({ name: `${data.name} pH`,",
301
+ "unique_id: `poolController-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}-ph`,",
302
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
303
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
304
+ "device: device_id,",
305
+ "icon: 'mdi:ph',",
306
+ "state_class: 'measurement',",
307
+ "state_topic: `${ctx.vars.mqttTopic}/state/chemControllers/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/ph/level`});"
308
+ ]
309
+ },
310
+ {
311
+ "topic": "@bind=vars.hassTopic;/sensor/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.name;-orp/config",
312
+ "useRootTopic": false,
313
+ "processor": [
314
+ "let device_id = {",
315
+ " name : 'Pool Controller - njsPC',",
316
+ " ids: [`${ctx.vars.mqttTopic}`],",
317
+ " suggested_area : 'Pool'};",
318
+ "return JSON.stringify({ name: `${data.name} ORP`,",
319
+ "unique_id: `poolController-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}-orp`,",
320
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
321
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
322
+ "device: device_id,",
323
+ "icon: 'mdi:water-check-outline',",
324
+ "state_class: 'measurement',",
325
+ "unit_of_measurement: 'mV',",
326
+ "state_topic: `${ctx.vars.mqttTopic}/state/chemControllers/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/orp/level`});"
327
+ ]
328
+ },
329
+ {
330
+ "topic": "@bind=vars.hassTopic;/sensor/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.name;-acid-tank-level/config",
331
+ "useRootTopic": false,
332
+ "processor": [
333
+ "let device_id = {",
334
+ " name : 'Pool Controller - njsPC',",
335
+ " ids: [`${ctx.vars.mqttTopic}`],",
336
+ " suggested_area : 'Pool'};",
337
+ "return JSON.stringify({ name: `${data.name} Acid Tank Level`,",
338
+ "unique_id: `poolController-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}-acid-tank-level`,",
339
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
340
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
341
+ "device: device_id,",
342
+ "icon: 'mdi:propane-tank-outline',",
343
+ "state_class: 'measurement',",
344
+ "state_topic: `${ctx.vars.mqttTopic}/state/chemControllers/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/acidTankLevel`,",
345
+ "value_template: '{{value_json.acidTankLevel}}'});"
346
+ ]
347
+ },
348
+ {
349
+ "topic": "@bind=vars.hassTopic;/sensor/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.name;-flow-alarm/config",
350
+ "useRootTopic": false,
351
+ "processor": [
352
+ "let device_id = {",
353
+ " name : 'Pool Controller - njsPC',",
354
+ " ids: [`${ctx.vars.mqttTopic}`],",
355
+ " suggested_area : 'Pool'};",
356
+ "return JSON.stringify({ name: `${data.name} Flow Alarm`,",
357
+ "unique_id: `poolController-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}-flow-alarm`,",
358
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
359
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
360
+ "device: device_id,",
361
+ "icon: 'mdi:waves-arrow-right',",
362
+ "state_topic: `${ctx.vars.mqttTopic}/state/chemControllers/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/alarms/flow`,",
363
+ "value_template: '{{value_json.name}}'});"
364
+ ]
365
+ }
366
+
367
+ ]
368
+ },
369
+ {
370
+ "name": "chlorinator",
371
+ "description": "Populate the chlorinators",
372
+ "topics": [
373
+ {
374
+ "topic": "@bind=vars.hassTopic;/sensor/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.name;-salt-level/config",
375
+ "useRootTopic": false,
376
+ "processor": [
377
+ "let device_id = {",
378
+ " name : 'Pool Controller - njsPC',",
379
+ " ids: [`${ctx.vars.mqttTopic}`],",
380
+ " suggested_area : 'Pool'};",
381
+ "return JSON.stringify({ name: `${data.name} Salt Level`,",
382
+ "unique_id: `poolController-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}-salt-level`,",
383
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
384
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
385
+ "device: device_id,",
386
+ "icon: 'mdi:shaker-outline',",
387
+ "state_class: 'measurement',",
388
+ "unit_of_measurement: 'ppm',",
389
+ "state_topic: `${ctx.vars.mqttTopic}/state/chlorinators/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/saltLevel`,",
390
+ "value_template: '{{value_json.saltLevel}}'});"
391
+ ]
392
+ },
393
+ {
394
+ "topic": "@bind=vars.hassTopic;/sensor/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.name;-current-output/config",
395
+ "useRootTopic": false,
396
+ "processor": [
397
+ "let device_id = {",
398
+ " name : 'Pool Controller - njsPC',",
399
+ " ids: [`${ctx.vars.mqttTopic}`],",
400
+ " suggested_area : 'Pool'};",
401
+ "return JSON.stringify({ name: `${data.name} Current Output`,",
402
+ "unique_id: `poolController-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}-current-output`,",
403
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
404
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
405
+ "device: device_id,",
406
+ "icon: 'mdi:gauge',",
407
+ "state_class: 'measurement',",
408
+ "unit_of_measurement: '%',",
409
+ "state_topic: `${ctx.vars.mqttTopic}/state/chlorinators/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/currentOutput`,",
410
+ "value_template: '{{value_json.currentOutput}}'});"
411
+ ]
412
+ },
413
+ {
414
+ "topic": "@bind=vars.hassTopic;/binary_sensor/@bind=vars.mqttTopic;/@bind=vars.mqttTopic;-@bind=data.name;-superchlorinate/config",
415
+ "useRootTopic": false,
416
+ "processor": [
417
+ "let device_id = {",
418
+ " name : 'Pool Controller - njsPC',",
419
+ " ids: [`${ctx.vars.mqttTopic}`],",
420
+ " suggested_area : 'Pool'};",
421
+ "return JSON.stringify({ name: `${data.name} Super Chlorinate`,",
422
+ "unique_id: `poolController-${data.id}-${data.name.replace(/\\s+/g, '').toLowerCase()}-super-chlorinate`,",
423
+ "availability_topic: `${ctx.vars.mqttTopic}/state/status`,",
424
+ "availability_template: \"{{'online' if value_json.name == 'ready' else 'offline'}}\",",
425
+ "device: device_id,",
426
+ "device_class: 'running',",
427
+ "icon: 'mdi:exclamation',",
428
+ "state_topic: `${ctx.vars.mqttTopic}/state/chlorinators/${data.id}/${data.name.replace(/\\s+/g, '').toLowerCase()}/superChlor`,",
429
+ "payload_on: 'on',",
430
+ "payload_off: 'off',",
431
+ "value_template: '{{value_json.superChlor}}'});"
432
+ ]
433
+ }
434
+ ]
435
+ }
436
+ ]
437
+ }