balboa_worldwide_app 1.2.4 → 2.0.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.
- checksums.yaml +4 -4
- data/exe/bwa_client +41 -0
- data/exe/bwa_mqtt_bridge +394 -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 +151 -78
- data/lib/bwa/crc.rb +3 -1
- data/lib/bwa/discovery.rb +19 -17
- data/lib/bwa/logger.rb +57 -0
- data/lib/bwa/message.rb +85 -41
- data/lib/bwa/messages/configuration.rb +7 -1
- data/lib/bwa/messages/configuration_request.rb +3 -1
- data/lib/bwa/messages/control_configuration.rb +13 -9
- data/lib/bwa/messages/control_configuration_request.rb +22 -2
- data/lib/bwa/messages/filter_cycles.rb +50 -22
- data/lib/bwa/messages/ready.rb +7 -1
- data/lib/bwa/messages/{set_temperature.rb → set_target_temperature.rb} +6 -3
- data/lib/bwa/messages/set_temperature_scale.rb +6 -3
- data/lib/bwa/messages/set_time.rb +5 -2
- data/lib/bwa/messages/status.rb +61 -47
- data/lib/bwa/messages/toggle_item.rb +30 -18
- data/lib/bwa/proxy.rb +19 -19
- data/lib/bwa/server.rb +22 -19
- data/lib/bwa/version.rb +3 -1
- metadata +78 -25
- data/bin/bwa_client +0 -43
- data/bin/bwa_mqtt_bridge +0 -282
data/bin/bwa_mqtt_bridge
DELETED
@@ -1,282 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'mqtt'
|
4
|
-
require 'sd_notify'
|
5
|
-
|
6
|
-
require 'bwa/client'
|
7
|
-
require 'bwa/discovery'
|
8
|
-
|
9
|
-
class MQTTBridge
|
10
|
-
def initialize(mqtt_uri, bwa, device_id: "bwa", base_topic: "homie")
|
11
|
-
@base_topic = "#{base_topic}/#{device_id}"
|
12
|
-
@mqtt = MQTT::Client.new(mqtt_uri)
|
13
|
-
@mqtt.set_will("#{@base_topic}/$state", "lost", true)
|
14
|
-
@mqtt.connect
|
15
|
-
@bwa = bwa
|
16
|
-
@attributes = {}
|
17
|
-
@things = Set.new
|
18
|
-
|
19
|
-
publish_basic_attributes
|
20
|
-
|
21
|
-
# Tell systemd we've started up OK. Ignored if systemd not in use.
|
22
|
-
SdNotify.ready
|
23
|
-
|
24
|
-
bwa_thread = Thread.new do
|
25
|
-
loop do
|
26
|
-
begin
|
27
|
-
message = @bwa.poll
|
28
|
-
next if message.is_a?(BWA::Messages::Ready)
|
29
|
-
|
30
|
-
puts message.inspect unless message.is_a?(BWA::Messages::Status)
|
31
|
-
case message
|
32
|
-
when BWA::Messages::ControlConfiguration
|
33
|
-
publish("spa/$type", message.model)
|
34
|
-
when BWA::Messages::ControlConfiguration2
|
35
|
-
message.pumps.each_with_index do |speed, i|
|
36
|
-
publish_pump(i + 1, speed) if speed != 0
|
37
|
-
end
|
38
|
-
message.lights.each_with_index do |exists, i|
|
39
|
-
publish_thing("light", i + 1) if exists
|
40
|
-
end
|
41
|
-
message.aux.each_with_index do |exists, i|
|
42
|
-
publish_thing("aux", i + 1) if exists
|
43
|
-
end
|
44
|
-
publish_mister if message.mister
|
45
|
-
publish_blower(message.blower) if message.blower != 0
|
46
|
-
publish_circpump if message.circ_pump
|
47
|
-
publish("$state", "ready")
|
48
|
-
when BWA::Messages::Status
|
49
|
-
@bwa.request_control_info unless @bwa.last_control_configuration
|
50
|
-
@bwa.request_control_info2 unless @bwa.last_control_configuration2
|
51
|
-
|
52
|
-
# make sure time is in sync
|
53
|
-
now = Time.now
|
54
|
-
now_minutes = now.hour * 60 + now.min
|
55
|
-
spa_minutes = message.hour * 60 + message.minute
|
56
|
-
# check the difference in both directions
|
57
|
-
diff = [(spa_minutes - now_minutes) % 1440, 1440 - (spa_minutes - now_minutes) % 1440].min
|
58
|
-
|
59
|
-
# allow a skew of 1 minute, since the seconds will always be off
|
60
|
-
if diff > 1
|
61
|
-
@bwa.set_time(now.hour, now.min, message.twenty_four_hour_time)
|
62
|
-
end
|
63
|
-
publish_attribute("spa/priming", message.priming)
|
64
|
-
publish_attribute("spa/heatingmode", message.heating_mode)
|
65
|
-
publish_attribute("spa/temperaturescale", message.temperature_scale)
|
66
|
-
publish_attribute("spa/24htime", message.twenty_four_hour_time)
|
67
|
-
publish_attribute("spa/heating", message.heating)
|
68
|
-
publish_attribute("spa/temperaturerange", message.temperature_range)
|
69
|
-
publish_attribute("spa/currenttemperature", message.current_temperature)
|
70
|
-
publish_attribute("spa/currenttemperature/$unit", "º#{message.temperature_scale.to_s[0].upcase}")
|
71
|
-
publish_attribute("spa/settemperature", message.set_temperature)
|
72
|
-
publish_attribute("spa/settemperature/$unit", "º#{message.temperature_scale.to_s[0].upcase}")
|
73
|
-
if message.temperature_scale == :celsius
|
74
|
-
publish_attribute("spa/currenttemperature/$format", message.temperature_range == :high ? "26:40" : "10:26")
|
75
|
-
publish_attribute("spa/settemperature/$format", message.temperature_range == :high ? "26:40" : "10:26")
|
76
|
-
else
|
77
|
-
publish_attribute("spa/currenttemperature/$format", message.temperature_range == :high ? "80:104" : "26:40")
|
78
|
-
publish_attribute("spa/settemperature/$format", message.temperature_range == :high ? "80:104" : "26:40")
|
79
|
-
end
|
80
|
-
publish_attribute("spa/filter1", message.filter[0])
|
81
|
-
publish_attribute("spa/filter2", message.filter[1])
|
82
|
-
|
83
|
-
publish_attribute("spa/circpump", message.circ_pump) if @bwa.last_control_configuration2&.circ_pump
|
84
|
-
publish_attribute("spa/blower", message.blower) if @bwa.last_control_configuration2&.blower.to_i != 0
|
85
|
-
publish_attribute("spa/mister", message.mister) if @bwa.last_control_configuration2&.mister
|
86
|
-
(0..5).each do |i|
|
87
|
-
publish_attribute("spa/pump#{i + 1}", message.pumps[i]) if @bwa.last_control_configuration2&.pumps&.[](i).to_i != 0
|
88
|
-
end
|
89
|
-
(0..1).each do |i|
|
90
|
-
publish_attribute("spa/light#{i + 1}", message.lights[i]) if @bwa.last_control_configuration2&.lights&.[](i)
|
91
|
-
end
|
92
|
-
(0..1).each do |i|
|
93
|
-
publish_attribute("spa/aux#{i + 1}", message.lights[i]) if @bwa.last_control_configuration2&.aux&.[](i)
|
94
|
-
end
|
95
|
-
|
96
|
-
# Tell systemd we are still alive and kicking. Ignored if systemd not in use.
|
97
|
-
SdNotify.watchdog
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
@mqtt.get do |topic, value|
|
104
|
-
puts "got #{value.inspect} at #{topic}"
|
105
|
-
case topic[@base_topic.length + 1..-1]
|
106
|
-
when "spa/heatingmode/set"
|
107
|
-
next @bwa.toggle_heating_mode if value == 'toggle'
|
108
|
-
next unless %w{ready rest}.include?(value)
|
109
|
-
@bwa.set_heating_mode(value.to_sym)
|
110
|
-
when "spa/temperaturescale/set"
|
111
|
-
next unless %w{fahrenheit celsius}.include?(value)
|
112
|
-
@bwa.set_temperature_scale(value.to_sym)
|
113
|
-
when "spa/24htime/set"
|
114
|
-
next unless %w{true false}.include?(value)
|
115
|
-
now = Time.now
|
116
|
-
@bwa.set_time(now.hour, now.min, value == 'true')
|
117
|
-
when "spa/temperaturerange/set"
|
118
|
-
next @bwa.toggle_temperature_range if value == 'toggle'
|
119
|
-
next unless %w{low high}.include?(value)
|
120
|
-
@bwa.set_temperature_range(value.to_sym)
|
121
|
-
when %r{^spa/pump([1-6])/set$}
|
122
|
-
next @bwa.toggle_pump($1.to_i) if value == 'toggle'
|
123
|
-
@bwa.set_pump($1.to_i, value.to_i)
|
124
|
-
when %r{^spa/(light|aux)([12])/set$}
|
125
|
-
next @bwa.send(:"toggle_#{$1}", $2.to_i) if value == 'toggle'
|
126
|
-
next unless %w{true false}.include?(value)
|
127
|
-
@bwa.send(:"set_#{$1}", $2.to_i, value == 'true')
|
128
|
-
when "spa/mister/set"
|
129
|
-
next @bwa.toggle_mister if value == 'toggle'
|
130
|
-
next unless %w{true false}.include?(value)
|
131
|
-
@bwa.set_mister(value == 'true')
|
132
|
-
when "spa/blower/set"
|
133
|
-
next @bwa.toggle_blower if value == 'toggle'
|
134
|
-
@bwa.set_blower(value.to_i)
|
135
|
-
when "spa/settemperature/set"
|
136
|
-
@bwa.set_temperature(value.to_f)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
def publish(topic, value)
|
142
|
-
@mqtt.publish("#{@base_topic}/#{topic}", value, true)
|
143
|
-
end
|
144
|
-
|
145
|
-
def publish_attribute(attr, value)
|
146
|
-
if !@attributes.key?(attr) || @attributes[attr] != value
|
147
|
-
publish(attr, value.to_s)
|
148
|
-
@attributes[attr] = value
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def subscribe(topic)
|
153
|
-
@mqtt.subscribe("#{@base_topic}/#{topic}")
|
154
|
-
end
|
155
|
-
|
156
|
-
def publish_basic_attributes
|
157
|
-
publish("$homie", "4.0.0")
|
158
|
-
publish("$name", "BWA Spa")
|
159
|
-
publish("$state", "init")
|
160
|
-
publish("$nodes", "spa")
|
161
|
-
|
162
|
-
publish("spa/$name", "BWA Spa")
|
163
|
-
publish("spa/$type", "spa")
|
164
|
-
publish_nodes
|
165
|
-
|
166
|
-
publish("spa/priming/$name", "Is the pump priming")
|
167
|
-
publish("spa/priming/$datatype", "boolean")
|
168
|
-
|
169
|
-
publish("spa/heatingmode/$name", "Current heating mode")
|
170
|
-
publish("spa/heatingmode/$datatype", "enum")
|
171
|
-
publish("spa/heatingmode/$format", "ready,rest,ready_in_rest")
|
172
|
-
publish("spa/heatingmode/$settable", "true")
|
173
|
-
subscribe("spa/heatingmode/set")
|
174
|
-
|
175
|
-
publish("spa/temperaturescale/$name", "Temperature scale")
|
176
|
-
publish("spa/temperaturescale/$datatype", "enum")
|
177
|
-
publish("spa/temperaturescale/$format", "fahrenheit,celsius")
|
178
|
-
publish("spa/temperaturescale/$settable", "true")
|
179
|
-
subscribe("spa/temperaturescale/set")
|
180
|
-
|
181
|
-
publish("spa/24htime/$name", "Clock is 24 hour time")
|
182
|
-
publish("spa/24htime/$datatype", "boolean")
|
183
|
-
publish("spa/24htime/$settable", "true")
|
184
|
-
subscribe("spa/24htime/set")
|
185
|
-
|
186
|
-
publish("spa/heating/$name", "Heater is currently running")
|
187
|
-
publish("spa/heating/$datatype", "boolean")
|
188
|
-
|
189
|
-
publish("spa/temperaturerange/$name", "Current temperature range")
|
190
|
-
publish("spa/temperaturerange/$datatype", "enum")
|
191
|
-
publish("spa/temperaturerange/$format", "high,low")
|
192
|
-
publish("spa/temperaturerange/$settable", "true")
|
193
|
-
subscribe("spa/temperaturerange/set")
|
194
|
-
|
195
|
-
publish("spa/currenttemperature/$name", "Current temperature")
|
196
|
-
publish("spa/currenttemperature/$datatype", "float")
|
197
|
-
|
198
|
-
publish("spa/settemperature/$name", "Set Temperature")
|
199
|
-
publish("spa/settemperature/$datatype", "float")
|
200
|
-
publish("spa/settemperature/$settable", "true")
|
201
|
-
subscribe("spa/settemperature/set")
|
202
|
-
|
203
|
-
publish("spa/filter1/$name", "Filter cycle 1 is currently running")
|
204
|
-
publish("spa/filter1/$datatype", "boolean")
|
205
|
-
|
206
|
-
publish("spa/filter2/$name", "Filter cycle 2 is currently running")
|
207
|
-
publish("spa/filter2/$datatype", "boolean")
|
208
|
-
end
|
209
|
-
|
210
|
-
def publish_pump(i, speeds)
|
211
|
-
publish("spa/pump#{i}/$name", "Pump #{i} speed")
|
212
|
-
publish("spa/pump#{i}/$datatype", "integer")
|
213
|
-
publish("spa/pump#{i}/$format", "0:#{speeds}")
|
214
|
-
publish("spa/pump#{i}/$settable", "true")
|
215
|
-
subscribe("spa/pump#{i}/set")
|
216
|
-
|
217
|
-
@things << "pump#{i}"
|
218
|
-
publish_nodes
|
219
|
-
end
|
220
|
-
|
221
|
-
def publish_thing(type, i)
|
222
|
-
publish("spa/#{type}#{i}/$name", "#{type} #{i}")
|
223
|
-
publish("spa/#{type}#{i}/$datatype", "boolean")
|
224
|
-
publish("spa/#{type}#{i}/$settable", "true")
|
225
|
-
subscribe("spa/#{type}#{i}/set")
|
226
|
-
|
227
|
-
@things << "#{type}#{i}"
|
228
|
-
publish_nodes
|
229
|
-
end
|
230
|
-
|
231
|
-
def publish_mister
|
232
|
-
publish("spa/mister/$name", type)
|
233
|
-
publish("spa/mister/$datatype", "boolean")
|
234
|
-
publish("spa/mister/$settable", "true")
|
235
|
-
subscribe("spa/mister/set")
|
236
|
-
|
237
|
-
@things << "mister"
|
238
|
-
publish_nodes
|
239
|
-
end
|
240
|
-
|
241
|
-
def publish_blower(speeds)
|
242
|
-
publish("spa/blower/$name", "Blower speed")
|
243
|
-
publish("spa/blower/$datatype", "integer")
|
244
|
-
publish("spa/blower/$format", "0:#{speeds}")
|
245
|
-
publish("spa/blower/$settable", "true")
|
246
|
-
subscribe("spa/blower/set")
|
247
|
-
|
248
|
-
@things << "blower"
|
249
|
-
publish_nodes
|
250
|
-
end
|
251
|
-
|
252
|
-
def publish_circpump
|
253
|
-
publish("spa/circpump/$name", "Circ pump is currently running")
|
254
|
-
publish("spa/circpump/$datatype", "boolean")
|
255
|
-
@things << "circpump"
|
256
|
-
|
257
|
-
publish_nodes
|
258
|
-
end
|
259
|
-
|
260
|
-
def publish_nodes
|
261
|
-
publish("spa/$properties", (["priming,heatingmode,temperaturescale,24htime,heating,temperaturerange,currenttemperature,settemperature,filter1,filter2"] + @things.to_a).join(','))
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
mqtt_uri = ARGV.shift
|
266
|
-
|
267
|
-
if ARGV.empty?
|
268
|
-
spas = BWA::Discovery.discover
|
269
|
-
if spas.empty?
|
270
|
-
$stderr.puts "Could not find spa!"
|
271
|
-
exit 1
|
272
|
-
end
|
273
|
-
spa_ip = "tcp://#{spas.first.first}/"
|
274
|
-
else
|
275
|
-
spa_ip = ARGV[0]
|
276
|
-
end
|
277
|
-
|
278
|
-
spa = BWA::Client.new(spa_ip)
|
279
|
-
|
280
|
-
spa.request_configuration
|
281
|
-
|
282
|
-
MQTTBridge.new(mqtt_uri, spa)
|