balboa_worldwide_app 1.3.0 → 2.0.3
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.
- checksums.yaml +4 -4
- data/exe/bwa_client +41 -0
- data/exe/bwa_mqtt_bridge +399 -0
- data/{bin → exe}/bwa_proxy +3 -2
- data/{bin → exe}/bwa_server +3 -2
- data/lib/balboa_worldwide_app.rb +3 -1
- data/lib/bwa/client.rb +123 -91
- data/lib/bwa/crc.rb +3 -1
- data/lib/bwa/discovery.rb +18 -17
- data/lib/bwa/logger.rb +9 -7
- data/lib/bwa/message.rb +67 -53
- data/lib/bwa/messages/configuration.rb +3 -1
- data/lib/bwa/messages/configuration_request.rb +3 -1
- data/lib/bwa/messages/control_configuration.rb +12 -9
- data/lib/bwa/messages/control_configuration_request.rb +13 -11
- data/lib/bwa/messages/filter_cycles.rb +50 -22
- data/lib/bwa/messages/ready.rb +3 -1
- data/lib/bwa/messages/{set_temperature.rb → set_target_temperature.rb} +5 -3
- data/lib/bwa/messages/set_temperature_scale.rb +5 -3
- data/lib/bwa/messages/set_time.rb +4 -2
- data/lib/bwa/messages/status.rb +53 -46
- data/lib/bwa/messages/toggle_item.rb +29 -27
- data/lib/bwa/proxy.rb +17 -18
- data/lib/bwa/server.rb +16 -14
- data/lib/bwa/version.rb +3 -1
- metadata +76 -24
- data/bin/bwa_client +0 -43
- data/bin/bwa_mqtt_bridge +0 -614
data/bin/bwa_mqtt_bridge
DELETED
@@ -1,614 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'mqtt'
|
4
|
-
require 'sd_notify'
|
5
|
-
require 'set'
|
6
|
-
require 'json'
|
7
|
-
|
8
|
-
require 'bwa/logger'
|
9
|
-
require 'bwa/client'
|
10
|
-
require 'bwa/discovery'
|
11
|
-
require 'bwa/version'
|
12
|
-
|
13
|
-
class MQTTBridge
|
14
|
-
def initialize(mqtt_uri, bwa, device_id: "bwa", base_topic: "homie")
|
15
|
-
@base_topic = "#{base_topic}/#{device_id}"
|
16
|
-
@mqtt = MQTT::Client.new(mqtt_uri)
|
17
|
-
@mqtt.set_will("#{@base_topic}/$state", "lost", true)
|
18
|
-
@mqtt.connect
|
19
|
-
@bwa = bwa
|
20
|
-
@attributes = {}
|
21
|
-
@things = Set.new
|
22
|
-
|
23
|
-
hass_discovery_topic = "homeassistant/"
|
24
|
-
@ha_binary_path = hass_discovery_topic + "binary_sensor/"
|
25
|
-
@ha_sensor_path = hass_discovery_topic + "sensor/"
|
26
|
-
@ha_switch_path = hass_discovery_topic + "switch/"
|
27
|
-
@ha_selects_path = hass_discovery_topic + "select/"
|
28
|
-
@ha_number_path = hass_discovery_topic + "number/"
|
29
|
-
|
30
|
-
@hass_device = {
|
31
|
-
device: {
|
32
|
-
identifiers: [device_id],
|
33
|
-
sw_version: BWA::VERSION,
|
34
|
-
name: "BWA Link"
|
35
|
-
}
|
36
|
-
}
|
37
|
-
|
38
|
-
# bwa availability topics (works for all devices)
|
39
|
-
@hass_availability = {
|
40
|
-
availability_topic: "#{@base_topic}/$state",
|
41
|
-
payload_available: "ready",
|
42
|
-
payload_not_available: "lost"
|
43
|
-
}
|
44
|
-
|
45
|
-
publish_basic_attributes
|
46
|
-
publish_filtercycles
|
47
|
-
|
48
|
-
# Home Assistant MQTT Discovery Section
|
49
|
-
publish_hass_discovery
|
50
|
-
|
51
|
-
# Tell systemd we've started up OK. Ignored if systemd not in use.
|
52
|
-
BWA.logger.warn "Balboa MQTT Bridge running (version #{BWA::VERSION})"
|
53
|
-
SdNotify.ready
|
54
|
-
|
55
|
-
bwa_thread = Thread.new do
|
56
|
-
loop do
|
57
|
-
begin
|
58
|
-
message = @bwa.poll
|
59
|
-
next if message.is_a?(BWA::Messages::Ready)
|
60
|
-
|
61
|
-
case message
|
62
|
-
when BWA::Messages::ControlConfiguration
|
63
|
-
publish("spa/$type", message.model)
|
64
|
-
when BWA::Messages::ControlConfiguration2
|
65
|
-
message.pumps.each_with_index do |speed, i|
|
66
|
-
publish_pump(i + 1, speed) if speed != 0
|
67
|
-
end
|
68
|
-
message.lights.each_with_index do |exists, i|
|
69
|
-
publish_thing(:light, i + 1) if exists
|
70
|
-
end
|
71
|
-
message.aux.each_with_index do |exists, i|
|
72
|
-
publish_thing(:aux, i + 1) if exists
|
73
|
-
end
|
74
|
-
publish_mister if message.mister
|
75
|
-
publish_blower(message.blower) if message.blower != 0
|
76
|
-
publish_circpump if message.circ_pump
|
77
|
-
publish("$state", "ready")
|
78
|
-
when BWA::Messages::FilterCycles
|
79
|
-
publish_attribute("spa/filter1hour",message.filter1_hour)
|
80
|
-
publish_attribute("spa/filter1minute",message.filter1_minute)
|
81
|
-
publish_attribute("spa/filter1durationhours",message.filter1_duration_hours)
|
82
|
-
publish_attribute("spa/filter1durationminutes",message.filter1_duration_minutes)
|
83
|
-
publish_attribute("spa/filter2enabled",message.filter2_enabled)
|
84
|
-
publish_attribute("spa/filter2hour",message.filter2_hour)
|
85
|
-
publish_attribute("spa/filter2minute",message.filter2_minute)
|
86
|
-
publish_attribute("spa/filter2durationhours",message.filter2_duration_hours)
|
87
|
-
publish_attribute("spa/filter2durationminutes",message.filter2_duration_minutes)
|
88
|
-
when BWA::Messages::Status
|
89
|
-
@bwa.request_control_info unless @bwa.last_control_configuration
|
90
|
-
@bwa.request_control_info2 unless @bwa.last_control_configuration2
|
91
|
-
@bwa.request_filter_configuration unless @bwa.last_filter_configuration
|
92
|
-
|
93
|
-
# make sure time is in sync
|
94
|
-
now = Time.now
|
95
|
-
now_minutes = now.hour * 60 + now.min
|
96
|
-
spa_minutes = message.hour * 60 + message.minute
|
97
|
-
# check the difference in both directions
|
98
|
-
diff = [(spa_minutes - now_minutes) % 1440, 1440 - (spa_minutes - now_minutes) % 1440].min
|
99
|
-
|
100
|
-
# allow a skew of 1 minute, since the seconds will always be off
|
101
|
-
if diff > 1
|
102
|
-
BWA.logger.info "Spa time #{"%02d:%02d" % [message.hour, message.minute]}, actually #{"%02d:%02d" % [now.hour, now.min]}; correcting difference of #{diff} min"
|
103
|
-
@bwa.set_time(now.hour, now.min, message.twenty_four_hour_time)
|
104
|
-
end
|
105
|
-
publish_attribute("spa/hold", message.hold)
|
106
|
-
publish_attribute("spa/priming", message.priming)
|
107
|
-
publish_attribute("spa/heatingmode", message.heating_mode)
|
108
|
-
publish_attribute("spa/temperaturescale", message.temperature_scale)
|
109
|
-
publish_attribute("spa/24htime", message.twenty_four_hour_time)
|
110
|
-
publish_attribute("spa/heating", message.heating)
|
111
|
-
publish_attribute("spa/temperaturerange", message.temperature_range)
|
112
|
-
publish_attribute("spa/currenttemperature", message.current_temperature)
|
113
|
-
publish_attribute("spa/currenttemperature/$unit", "º#{message.temperature_scale.to_s[0].upcase}")
|
114
|
-
publish_attribute("spa/settemperature", message.set_temperature)
|
115
|
-
publish_attribute("spa/settemperature/$unit", "º#{message.temperature_scale.to_s[0].upcase}")
|
116
|
-
if message.temperature_scale == :celsius
|
117
|
-
publish_attribute("spa/currenttemperature/$format", "0:42")
|
118
|
-
publish_attribute("spa/settemperature/$format", message.temperature_range == :high ? "26:40" : "10:26")
|
119
|
-
publish_hass_discovery_settemp(:celsius)
|
120
|
-
else
|
121
|
-
publish_attribute("spa/currenttemperature/$format", "32:108")
|
122
|
-
publish_attribute("spa/settemperature/$format", message.temperature_range == :high ? "80:106" : "50:99")
|
123
|
-
publish_hass_discovery_settemp(:fahrenheit)
|
124
|
-
end
|
125
|
-
publish_attribute("spa/filter1", message.filter[0])
|
126
|
-
publish_attribute("spa/filter2", message.filter[1])
|
127
|
-
|
128
|
-
publish_attribute("spa/circpump", message.circ_pump) if @bwa.last_control_configuration2&.circ_pump
|
129
|
-
publish_attribute("spa/blower", message.blower) if @bwa.last_control_configuration2&.blower.to_i != 0
|
130
|
-
publish_attribute("spa/mister", message.mister) if @bwa.last_control_configuration2&.mister
|
131
|
-
(0..5).each do |i|
|
132
|
-
publish_attribute("spa/pump#{i + 1}", message.pumps[i]) if @bwa.last_control_configuration2&.pumps&.[](i).to_i != 0
|
133
|
-
end
|
134
|
-
(0..1).each do |i|
|
135
|
-
publish_attribute("spa/light#{i + 1}", message.lights[i]) if @bwa.last_control_configuration2&.lights&.[](i)
|
136
|
-
end
|
137
|
-
(0..1).each do |i|
|
138
|
-
publish_attribute("spa/aux#{i + 1}", message.lights[i]) if @bwa.last_control_configuration2&.aux&.[](i)
|
139
|
-
end
|
140
|
-
|
141
|
-
# Tell systemd we are still alive and kicking. Ignored if systemd not in use.
|
142
|
-
SdNotify.watchdog
|
143
|
-
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
@mqtt.get do |topic, value|
|
150
|
-
BWA.logger.warn "from mqtt: #{value.inspect} at #{topic}"
|
151
|
-
case topic[@base_topic.length + 1..-1]
|
152
|
-
when "spa/hold/set"
|
153
|
-
next @bwa.toggle_hold if value == 'toggle'
|
154
|
-
next unless %w{true false}.include?(value)
|
155
|
-
@bwa.set_hold(value == 'true')
|
156
|
-
when "spa/heatingmode/set"
|
157
|
-
next @bwa.toggle_heating_mode if value == 'toggle'
|
158
|
-
next unless %w{ready rest}.include?(value)
|
159
|
-
@bwa.set_heating_mode(value.to_sym)
|
160
|
-
when "spa/temperaturescale/set"
|
161
|
-
next unless %w{fahrenheit celsius}.include?(value)
|
162
|
-
@bwa.set_temperature_scale(value.to_sym)
|
163
|
-
when "spa/24htime/set"
|
164
|
-
next unless %w{true false}.include?(value)
|
165
|
-
now = Time.now
|
166
|
-
@bwa.set_time(now.hour, now.min, value == 'true')
|
167
|
-
when "spa/temperaturerange/set"
|
168
|
-
next @bwa.toggle_temperature_range if value == 'toggle'
|
169
|
-
next unless %w{low high}.include?(value)
|
170
|
-
@bwa.set_temperature_range(value.to_sym)
|
171
|
-
when %r{^spa/pump([1-6])/set$}
|
172
|
-
next @bwa.toggle_pump($1.to_i) if value == 'toggle'
|
173
|
-
@bwa.set_pump($1.to_i, value.to_i)
|
174
|
-
when %r{^spa/(light|aux)([12])/set$}
|
175
|
-
next @bwa.send(:"toggle_#{$1}", $2.to_i) if value == 'toggle'
|
176
|
-
next unless %w{true false}.include?(value)
|
177
|
-
@bwa.send(:"set_#{$1}", $2.to_i, value == 'true')
|
178
|
-
when "spa/mister/set"
|
179
|
-
next @bwa.toggle_mister if value == 'toggle'
|
180
|
-
next unless %w{true false}.include?(value)
|
181
|
-
@bwa.set_mister(value == 'true')
|
182
|
-
when "spa/blower/set"
|
183
|
-
next @bwa.toggle_blower if value == 'toggle'
|
184
|
-
@bwa.set_blower(value.to_i)
|
185
|
-
when "spa/settemperature/set"
|
186
|
-
@bwa.set_temperature(value.to_f)
|
187
|
-
when %r{^spa/(filter[12](hour|minute|durationhours|durationminutes|enabled))/set$}
|
188
|
-
@bwa.set_filtercycles($1, value)
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
def publish(topic, value)
|
194
|
-
BWA.logger.debug " to mqtt: #{topic}: #{value}"
|
195
|
-
@mqtt.publish("#{@base_topic}/#{topic}", value, true)
|
196
|
-
end
|
197
|
-
|
198
|
-
def publish_attribute(attr, value)
|
199
|
-
if !@attributes.key?(attr) || @attributes[attr] != value
|
200
|
-
publish(attr, value.to_s)
|
201
|
-
@attributes[attr] = value
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
def subscribe(topic)
|
206
|
-
@mqtt.subscribe("#{@base_topic}/#{topic}")
|
207
|
-
end
|
208
|
-
|
209
|
-
def publish_hass_discovery()
|
210
|
-
#Priming
|
211
|
-
priming_config = {
|
212
|
-
name: "Hot Tub Priming",
|
213
|
-
state_topic: "#{@base_topic}/spa/priming",
|
214
|
-
device_class: "running",
|
215
|
-
unique_id: "spa_priming",
|
216
|
-
icon: "mdi:fast-forward"
|
217
|
-
}
|
218
|
-
@mqtt.publish(@ha_binary_path + "priming/config", priming_config
|
219
|
-
.merge(@hass_device)
|
220
|
-
.merge(@hass_availability)
|
221
|
-
.to_json, true)
|
222
|
-
|
223
|
-
#Circulation Pump
|
224
|
-
circ_config = {
|
225
|
-
name: "Hot Tub Circulation Pump",
|
226
|
-
state_topic: "#{@base_topic}/spa/circpump",
|
227
|
-
device_class: "running",
|
228
|
-
unique_id: "spa_circpump",
|
229
|
-
icon: "mdi:sync"
|
230
|
-
}
|
231
|
-
@mqtt.publish(@ha_binary_path + "circpump/config", circ_config
|
232
|
-
.merge(@hass_device)
|
233
|
-
.merge(@hass_availability)
|
234
|
-
.to_json, true)
|
235
|
-
|
236
|
-
# Filter 1 Cycle Running
|
237
|
-
filter1_config = {
|
238
|
-
name: "Hot Tub Filter 1 Cycle Running",
|
239
|
-
state_topic: "#{@base_topic}/spa/filter1",
|
240
|
-
device_class: "running",
|
241
|
-
unique_id: "spa_filtercycle1",
|
242
|
-
icon: "mdi:air-filter"
|
243
|
-
}
|
244
|
-
@mqtt.publish(@ha_binary_path + "filter1/config", filter1_config
|
245
|
-
.merge(@hass_device)
|
246
|
-
.merge(@hass_availability)
|
247
|
-
.to_json, true)
|
248
|
-
|
249
|
-
# Filter 2 Cycle Running
|
250
|
-
filter2_config = {
|
251
|
-
name: "Hot Tub Filter 2 Cycle Running",
|
252
|
-
state_topic: "#{@base_topic}/spa/filter2",
|
253
|
-
device_class: "running",
|
254
|
-
unique_id: "spa_filtercycle2",
|
255
|
-
icon: "mdi:air-filter"
|
256
|
-
}
|
257
|
-
@mqtt.publish(@ha_binary_path + "filter2/config", filter2_config
|
258
|
-
.merge(@hass_device)
|
259
|
-
.merge(@hass_availability)
|
260
|
-
.to_json, true)
|
261
|
-
|
262
|
-
# Heater Running
|
263
|
-
heater_config = {
|
264
|
-
name: "Hot Tub Heater",
|
265
|
-
state_topic: "#{@base_topic}/spa/heating",
|
266
|
-
device_class: "running",
|
267
|
-
unique_id: "spa_heating",
|
268
|
-
icon: "mdi:hot-tub"
|
269
|
-
}
|
270
|
-
@mqtt.publish(@ha_binary_path + "heating/config", heater_config
|
271
|
-
.merge(@hass_device)
|
272
|
-
.merge(@hass_availability)
|
273
|
-
.to_json, true)
|
274
|
-
|
275
|
-
# Heating Mode
|
276
|
-
heatingmode_config = {
|
277
|
-
name: "Hot Tub Heating Mode",
|
278
|
-
state_topic: "#{@base_topic}/spa/heatingmode",
|
279
|
-
command_topic: "#{@base_topic}/spa/heatingmode/set",
|
280
|
-
unique_id: "spa_heating_mode",
|
281
|
-
options: ["ready","rest","ready_in_rest"],
|
282
|
-
icon: "mdi:cog-play"
|
283
|
-
}
|
284
|
-
@mqtt.publish(@ha_selects_path + "heatingmode/config", heatingmode_config
|
285
|
-
.merge(@hass_device)
|
286
|
-
.merge(@hass_availability)
|
287
|
-
.to_json, true)
|
288
|
-
|
289
|
-
# Temperature Range
|
290
|
-
temperaturerange_config = {
|
291
|
-
name: "Hot Tub Temperature Range",
|
292
|
-
state_topic: "#{@base_topic}/spa/temperaturerange",
|
293
|
-
command_topic: "#{@base_topic}/spa/temperaturerange/set",
|
294
|
-
unique_id: "spa_temperaturerange_range",
|
295
|
-
options: ["high","low"],
|
296
|
-
icon: "mdi:thermometer-lines"
|
297
|
-
}
|
298
|
-
@mqtt.publish(@ha_selects_path + "temperaturerange/config", temperaturerange_config
|
299
|
-
.merge(@hass_device)
|
300
|
-
.merge(@hass_availability)
|
301
|
-
.to_json, true)
|
302
|
-
|
303
|
-
# Temperature Scale
|
304
|
-
temperaturescale_config = {
|
305
|
-
name: "Hot Tub Temperature Scale",
|
306
|
-
state_topic: "#{@base_topic}/spa/temperaturescale",
|
307
|
-
unique_id: "spa_temperaturescale"
|
308
|
-
}
|
309
|
-
@mqtt.publish(@ha_sensor_path + "temperaturescale/config", temperaturescale_config
|
310
|
-
.merge(@hass_device)
|
311
|
-
.merge(@hass_availability)
|
312
|
-
.to_json, true)
|
313
|
-
|
314
|
-
# Current Temperature
|
315
|
-
currenttemperature_config = {
|
316
|
-
name: "Hot Tub Current Temperature",
|
317
|
-
state_topic: "#{@base_topic}/spa/currenttemperature",
|
318
|
-
unique_id: "spa_currenttemperature",
|
319
|
-
device_class: "temperature"
|
320
|
-
}
|
321
|
-
@mqtt.publish(@ha_sensor_path + "currenttemperature/config", currenttemperature_config
|
322
|
-
.merge(@hass_device)
|
323
|
-
.merge(@hass_availability)
|
324
|
-
.to_json, true)
|
325
|
-
|
326
|
-
# Set Temperature - Assuming fahrenheit first
|
327
|
-
settemperature_config = {
|
328
|
-
name: "Hot Tub Set Temperature",
|
329
|
-
unique_id: "spa_settemperature",
|
330
|
-
state_topic: "#{@base_topic}/spa/settemperature",
|
331
|
-
command_topic: "#{@base_topic}/spa/settemperature/set",
|
332
|
-
min: 50,
|
333
|
-
max: 106,
|
334
|
-
unit_of_measurement: "°F",
|
335
|
-
icon: "mdi:thermometer"
|
336
|
-
}
|
337
|
-
@mqtt.publish(@ha_number_path + "settemperature/config", settemperature_config
|
338
|
-
.merge(@hass_device)
|
339
|
-
.merge(@hass_availability)
|
340
|
-
.to_json, true)
|
341
|
-
end
|
342
|
-
|
343
|
-
def publish_hass_discovery_settemp(scale)
|
344
|
-
return if scale == @last_scale
|
345
|
-
@last_scale = scale
|
346
|
-
|
347
|
-
# Update temp ranges when scale changes
|
348
|
-
settemperature_config = {
|
349
|
-
name: "Hot Tub Set Temperature",
|
350
|
-
unique_id: "spa_settemperature",
|
351
|
-
state_topic: "#{@base_topic}/spa/settemperature",
|
352
|
-
command_topic: "#{@base_topic}/spa/settemperature/set",
|
353
|
-
min: 50,
|
354
|
-
max: 106,
|
355
|
-
unit_of_measurement: "°F",
|
356
|
-
icon: "mdi:thermometer"
|
357
|
-
}
|
358
|
-
|
359
|
-
if scale == :celsius
|
360
|
-
settemperature_config[:min] = 10
|
361
|
-
settemperature_config[:max] = 40
|
362
|
-
settemperature_config[:unit_of_measurement] = "°C"
|
363
|
-
else
|
364
|
-
settemperature_config[:min] = 50
|
365
|
-
settemperature_config[:max] = 106
|
366
|
-
settemperature_config[:unit_of_measurement] = "°F"
|
367
|
-
end
|
368
|
-
|
369
|
-
@mqtt.publish(@ha_number_path + "settemperature/config", settemperature_config
|
370
|
-
.merge(@hass_device)
|
371
|
-
.merge(@hass_availability)
|
372
|
-
.to_json, true)
|
373
|
-
end
|
374
|
-
|
375
|
-
def publish_hass_discovery_pumps(i, speeds)
|
376
|
-
pump_config = {
|
377
|
-
name: "Hot Tub Pump #{i}",
|
378
|
-
unique_id: "spa_pump#{i}",
|
379
|
-
state_topic: "#{@base_topic}/spa/pump#{i}",
|
380
|
-
command_topic: "#{@base_topic}/spa/pump#{i}/set",
|
381
|
-
payload_on: "toggle",
|
382
|
-
payload_off: "toggle",
|
383
|
-
state_on: "2",
|
384
|
-
state_off: "0",
|
385
|
-
icon: "mdi:chart-bubble"
|
386
|
-
}
|
387
|
-
@mqtt.publish(@ha_switch_path + "pump#{i}/config", pump_config
|
388
|
-
.merge(@hass_device)
|
389
|
-
.merge(@hass_availability)
|
390
|
-
.to_json, true)
|
391
|
-
end
|
392
|
-
|
393
|
-
def publish_hass_discovery_things(type, i)
|
394
|
-
#Things - Lights and such
|
395
|
-
thing_config = {
|
396
|
-
name: "Hot Tub #{type} #{i}",
|
397
|
-
unique_id: "spa_#{type}#{i}",
|
398
|
-
state_topic: "#{@base_topic}/spa/#{type}#{i}",
|
399
|
-
command_topic: "#{@base_topic}/spa/#{type}#{i}/set",
|
400
|
-
payload_on: "true",
|
401
|
-
payload_off: "false",
|
402
|
-
state_on: "true",
|
403
|
-
state_off: "false"
|
404
|
-
}
|
405
|
-
case type
|
406
|
-
when :light
|
407
|
-
thing_config[:icon] = "mdi:car-parking-lights"
|
408
|
-
when :mister
|
409
|
-
thing_config[:icon] = "mdi:sprinkler-fire"
|
410
|
-
when :blower
|
411
|
-
thing_config[:icon] = "mdi:chart-bubble"
|
412
|
-
end
|
413
|
-
@mqtt.publish(@ha_switch_path+ "#{type}#{i}/config", thing_config
|
414
|
-
.merge(@hass_device)
|
415
|
-
.merge(@hass_availability)
|
416
|
-
.to_json, true)
|
417
|
-
end
|
418
|
-
|
419
|
-
def publish_basic_attributes
|
420
|
-
publish("$homie", "4.0.0")
|
421
|
-
publish("$name", "BWA Spa")
|
422
|
-
publish("$state", "init")
|
423
|
-
publish("$nodes", "spa")
|
424
|
-
|
425
|
-
publish("spa/$name", "BWA Spa")
|
426
|
-
publish("spa/$type", "spa")
|
427
|
-
publish_nodes
|
428
|
-
|
429
|
-
publish("spa/hold/$name", "In Hold mode")
|
430
|
-
publish("spa/hold/$datatype", "boolean")
|
431
|
-
publish("spa/hold/$settable", "true")
|
432
|
-
subscribe("spa/hold/set")
|
433
|
-
|
434
|
-
publish("spa/priming/$name", "Is the pump priming")
|
435
|
-
publish("spa/priming/$datatype", "boolean")
|
436
|
-
|
437
|
-
publish("spa/heatingmode/$name", "Current heating mode")
|
438
|
-
publish("spa/heatingmode/$datatype", "enum")
|
439
|
-
publish("spa/heatingmode/$format", "ready,rest,ready_in_rest")
|
440
|
-
publish("spa/heatingmode/$settable", "true")
|
441
|
-
subscribe("spa/heatingmode/set")
|
442
|
-
|
443
|
-
publish("spa/temperaturescale/$name", "Temperature scale")
|
444
|
-
publish("spa/temperaturescale/$datatype", "enum")
|
445
|
-
publish("spa/temperaturescale/$format", "fahrenheit,celsius")
|
446
|
-
publish("spa/temperaturescale/$settable", "true")
|
447
|
-
subscribe("spa/temperaturescale/set")
|
448
|
-
|
449
|
-
publish("spa/24htime/$name", "Clock is 24 hour time")
|
450
|
-
publish("spa/24htime/$datatype", "boolean")
|
451
|
-
publish("spa/24htime/$settable", "true")
|
452
|
-
subscribe("spa/24htime/set")
|
453
|
-
|
454
|
-
publish("spa/heating/$name", "Heater is currently running")
|
455
|
-
publish("spa/heating/$datatype", "boolean")
|
456
|
-
|
457
|
-
publish("spa/temperaturerange/$name", "Current temperature range")
|
458
|
-
publish("spa/temperaturerange/$datatype", "enum")
|
459
|
-
publish("spa/temperaturerange/$format", "high,low")
|
460
|
-
publish("spa/temperaturerange/$settable", "true")
|
461
|
-
subscribe("spa/temperaturerange/set")
|
462
|
-
|
463
|
-
publish("spa/currenttemperature/$name", "Current temperature")
|
464
|
-
publish("spa/currenttemperature/$datatype", "float")
|
465
|
-
|
466
|
-
publish("spa/settemperature/$name", "Set Temperature")
|
467
|
-
publish("spa/settemperature/$datatype", "float")
|
468
|
-
publish("spa/settemperature/$settable", "true")
|
469
|
-
subscribe("spa/settemperature/set")
|
470
|
-
|
471
|
-
publish("spa/filter1/$name", "Filter cycle 1 is currently running")
|
472
|
-
publish("spa/filter1/$datatype", "boolean")
|
473
|
-
|
474
|
-
publish("spa/filter2/$name", "Filter cycle 2 is currently running")
|
475
|
-
publish("spa/filter2/$datatype", "boolean")
|
476
|
-
end
|
477
|
-
|
478
|
-
def publish_pump(i, speeds)
|
479
|
-
publish("spa/pump#{i}/$name", "Pump #{i} speed")
|
480
|
-
publish("spa/pump#{i}/$datatype", "integer")
|
481
|
-
publish("spa/pump#{i}/$format", "0:#{speeds}")
|
482
|
-
publish("spa/pump#{i}/$settable", "true")
|
483
|
-
subscribe("spa/pump#{i}/set")
|
484
|
-
|
485
|
-
@things << "pump#{i}"
|
486
|
-
publish_hass_discovery_pumps(i, speeds)
|
487
|
-
publish_nodes
|
488
|
-
end
|
489
|
-
|
490
|
-
def publish_thing(type, i)
|
491
|
-
publish("spa/#{type}#{i}/$name", "#{type} #{i}")
|
492
|
-
publish("spa/#{type}#{i}/$datatype", "boolean")
|
493
|
-
publish("spa/#{type}#{i}/$settable", "true")
|
494
|
-
subscribe("spa/#{type}#{i}/set")
|
495
|
-
|
496
|
-
@things << "#{type}#{i}"
|
497
|
-
publish_hass_discovery_things(type, i)
|
498
|
-
publish_nodes
|
499
|
-
end
|
500
|
-
|
501
|
-
def publish_mister
|
502
|
-
publish("spa/mister/$name", type)
|
503
|
-
publish("spa/mister/$datatype", "boolean")
|
504
|
-
publish("spa/mister/$settable", "true")
|
505
|
-
subscribe("spa/mister/set")
|
506
|
-
|
507
|
-
@things << "mister"
|
508
|
-
publish_nodes
|
509
|
-
end
|
510
|
-
|
511
|
-
def publish_blower(speeds)
|
512
|
-
publish("spa/blower/$name", "Blower speed")
|
513
|
-
publish("spa/blower/$datatype", "integer")
|
514
|
-
publish("spa/blower/$format", "0:#{speeds}")
|
515
|
-
publish("spa/blower/$settable", "true")
|
516
|
-
subscribe("spa/blower/set")
|
517
|
-
|
518
|
-
@things << "blower"
|
519
|
-
publish_nodes
|
520
|
-
end
|
521
|
-
|
522
|
-
def publish_circpump
|
523
|
-
publish("spa/circpump/$name", "Circ pump is currently running")
|
524
|
-
publish("spa/circpump/$datatype", "boolean")
|
525
|
-
@things << "circpump"
|
526
|
-
|
527
|
-
publish_nodes
|
528
|
-
end
|
529
|
-
|
530
|
-
def publish_filtercycles
|
531
|
-
publish("spa/filter1hour/$name", "Filter Cycle 1 Start Hour")
|
532
|
-
publish("spa/filter1hour/$datatype", "integer")
|
533
|
-
publish("spa/filter1hour/$format", "0:24")
|
534
|
-
publish("spa/filter1hour/$settable", "true")
|
535
|
-
|
536
|
-
publish("spa/filter1minute/$name", "Filter Cycle 1 Start Minutes")
|
537
|
-
publish("spa/filter1minute/$datatype", "integer")
|
538
|
-
publish("spa/filter1minute/$format", "0:59")
|
539
|
-
publish("spa/filter1minute/$settable", "true")
|
540
|
-
|
541
|
-
publish("spa/filter1durationhours/$name", "Filter Cycle 1 Duration Hours")
|
542
|
-
publish("spa/filter1durationhours/$datatype", "integer")
|
543
|
-
publish("spa/filter1durationhours/$format", "0:24")
|
544
|
-
publish("spa/filter1durationhours/$settable", "true")
|
545
|
-
|
546
|
-
publish("spa/filter1durationminutes/$name", "Filter Cycle 1 Duration Minutes")
|
547
|
-
publish("spa/filter1durationminutes/$datatype", "integer")
|
548
|
-
publish("spa/filter1durationminutes/$format", "0:59")
|
549
|
-
publish("spa/filter1durationminutes/$settable", "true")
|
550
|
-
|
551
|
-
publish("spa/filter2enabled/$name", "Filter Cycle 2 Enabled")
|
552
|
-
publish("spa/filter2enabled/$datatype", "boolean")
|
553
|
-
publish("spa/filter2enabled/$settable", "true")
|
554
|
-
|
555
|
-
publish("spa/filter2hour/$name", "Filter Cycle 2 Start Hour")
|
556
|
-
publish("spa/filter2hour/$datatype", "integer")
|
557
|
-
publish("spa/filter2hour/$format", "0:24")
|
558
|
-
publish("spa/filter2hour/$settable", "true")
|
559
|
-
|
560
|
-
publish("spa/filter2minute/$name", "Filter Cycle 2 Start Minutes")
|
561
|
-
publish("spa/filter2minute/$datatype", "integer")
|
562
|
-
publish("spa/filter2minute/$format", "0:59")
|
563
|
-
publish("spa/filter2minute/$settable", "true")
|
564
|
-
|
565
|
-
publish("spa/filter2durationhours/$name", "Filter Cycle 2 Duration Hours")
|
566
|
-
publish("spa/filter2durationhours/$datatype", "integer")
|
567
|
-
publish("spa/filter2durationhours/$format", "0:24")
|
568
|
-
publish("spa/filter2durationhours/$settable", "true")
|
569
|
-
|
570
|
-
publish("spa/filter2durationminutes/$name", "Filter Cycle 2 Duration Minutes")
|
571
|
-
publish("spa/filter2durationminutes/$datatype", "integer")
|
572
|
-
publish("spa/filter2durationminutes/$format", "0:59")
|
573
|
-
publish("spa/filter2durationminutes/$settable", "true")
|
574
|
-
|
575
|
-
subscribe("spa/filter1hour/set")
|
576
|
-
subscribe("spa/filter1minute/set")
|
577
|
-
subscribe("spa/filter1durationhours/set")
|
578
|
-
subscribe("spa/filter1durationminutes/set")
|
579
|
-
subscribe("spa/filter2enabled/set")
|
580
|
-
subscribe("spa/filter2hour/set")
|
581
|
-
subscribe("spa/filter2minute/set")
|
582
|
-
subscribe("spa/filter2durationhours/set")
|
583
|
-
subscribe("spa/filter2durationminutes/set")
|
584
|
-
|
585
|
-
@things.merge(["filter1hour,filter1minute,filter1durationhours,filter1durationminutes,filter2enabled,filter2hour,filter2minute,filter2durationhours,filter2durationminutes"])
|
586
|
-
|
587
|
-
publish_nodes
|
588
|
-
end
|
589
|
-
|
590
|
-
def publish_nodes
|
591
|
-
publish("spa/$properties", (["hold,priming,heatingmode,temperaturescale,24htime,heating,temperaturerange,currenttemperature,settemperature,filter1,filter2"] + @things.to_a).join(','))
|
592
|
-
end
|
593
|
-
end
|
594
|
-
|
595
|
-
mqtt_uri = ARGV.shift
|
596
|
-
|
597
|
-
if ARGV.empty?
|
598
|
-
spas = BWA::Discovery.discover
|
599
|
-
if spas.empty?
|
600
|
-
BWA.logger.fatal "Could not find spa!"
|
601
|
-
$stderr.puts "Could not find spa!"
|
602
|
-
exit 1
|
603
|
-
end
|
604
|
-
spa_ip = "tcp://#{spas.first.first}/"
|
605
|
-
else
|
606
|
-
spa_ip = ARGV[0]
|
607
|
-
end
|
608
|
-
|
609
|
-
spa = BWA::Client.new(spa_ip)
|
610
|
-
|
611
|
-
spa.request_configuration
|
612
|
-
spa.request_filter_configuration
|
613
|
-
|
614
|
-
MQTTBridge.new(mqtt_uri, spa)
|