balboa_worldwide_app 1.3.0 → 2.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.
- 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 +121 -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 +51 -44
- 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 +70 -24
- data/bin/bwa_client +0 -43
- data/bin/bwa_mqtt_bridge +0 -614
@@ -1,14 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BWA
|
2
4
|
module Messages
|
3
5
|
class ControlConfiguration < Message
|
4
|
-
MESSAGE_TYPE = "\xbf\x24".force_encoding(Encoding::ASCII_8BIT)
|
6
|
+
MESSAGE_TYPE = (+"\xbf\x24").force_encoding(Encoding::ASCII_8BIT)
|
5
7
|
MESSAGE_LENGTH = 21
|
6
8
|
|
7
9
|
attr_accessor :model, :version
|
8
10
|
|
9
11
|
def initialize
|
10
12
|
super
|
11
|
-
@model =
|
13
|
+
@model = ""
|
12
14
|
@version = 0
|
13
15
|
end
|
14
16
|
|
@@ -23,15 +25,17 @@ module BWA
|
|
23
25
|
end
|
24
26
|
|
25
27
|
class ControlConfiguration2 < Message
|
26
|
-
MESSAGE_TYPE = "\xbf\x2e".force_encoding(Encoding::ASCII_8BIT)
|
28
|
+
MESSAGE_TYPE = (+"\xbf\x2e").force_encoding(Encoding::ASCII_8BIT)
|
27
29
|
MESSAGE_LENGTH = 6
|
28
30
|
|
29
|
-
attr_accessor :pumps, :lights, :
|
31
|
+
attr_accessor :pumps, :lights, :circulation_pump, :blower, :mister, :aux
|
30
32
|
|
31
33
|
def initialize
|
34
|
+
super
|
35
|
+
|
32
36
|
self.pumps = Array.new(6, 0)
|
33
37
|
self.lights = Array.new(2, false)
|
34
|
-
self.
|
38
|
+
self.circulation_pump = false
|
35
39
|
self.blower = 0
|
36
40
|
self.mister = false
|
37
41
|
self.aux = Array.new(2, false)
|
@@ -51,7 +55,7 @@ module BWA
|
|
51
55
|
lights[1] = ((flags >> 6) & 0x03 != 0)
|
52
56
|
flags = data[3].ord
|
53
57
|
self.blower = flags & 0x03
|
54
|
-
self.
|
58
|
+
self.circulation_pump = ((flags >> 6) & 0x03 != 0)
|
55
59
|
flags = data[4].ord
|
56
60
|
self.mister = (flags & 0x30 != 0)
|
57
61
|
aux[0] = (flags & 0x01 != 0)
|
@@ -59,17 +63,16 @@ module BWA
|
|
59
63
|
end
|
60
64
|
|
61
65
|
def inspect
|
62
|
-
result = "#<BWA::Messages::ControlConfiguration2 "
|
63
66
|
items = []
|
64
67
|
|
65
68
|
items << "pumps=#{pumps.inspect}"
|
66
69
|
items << "lights=#{lights.inspect}"
|
67
|
-
items << "
|
70
|
+
items << "circulation_pump" if circulation_pump
|
68
71
|
items << "blower=#{blower}" if blower != 0
|
69
72
|
items << "mister" if mister
|
70
73
|
items << "aux=#{aux.inspect}"
|
71
74
|
|
72
|
-
|
75
|
+
"#<BWA::Messages::ControlConfiguration2 #{items.join(" ")}>"
|
73
76
|
end
|
74
77
|
end
|
75
78
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BWA
|
2
4
|
module Messages
|
3
5
|
class ControlConfigurationRequest < Message
|
4
|
-
MESSAGE_TYPE = "\xbf\x22".force_encoding(Encoding::ASCII_8BIT)
|
6
|
+
MESSAGE_TYPE = (+"\xbf\x22").force_encoding(Encoding::ASCII_8BIT)
|
5
7
|
MESSAGE_LENGTH = 3
|
6
8
|
|
7
9
|
attr_accessor :type
|
@@ -13,20 +15,20 @@ module BWA
|
|
13
15
|
|
14
16
|
def parse(data)
|
15
17
|
self.type = case data
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
when "\x02\x00\x00" then 1
|
19
|
+
when "\x00\x00\x01" then 2
|
20
|
+
when "\x01\x00\x00" then 3
|
21
|
+
else 0
|
22
|
+
end
|
21
23
|
end
|
22
24
|
|
23
25
|
def serialize
|
24
26
|
data = case type
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
when 1 then "\x02\x00\x00"
|
28
|
+
when 2 then "\x00\x00\x01"
|
29
|
+
when 3 then "\x01\x00\x00"
|
30
|
+
else "\x00\x00\x00"
|
31
|
+
end
|
30
32
|
super(data)
|
31
33
|
end
|
32
34
|
|
@@ -1,39 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BWA
|
2
4
|
module Messages
|
3
5
|
class FilterCycles < Message
|
4
|
-
|
5
|
-
|
6
|
-
|
6
|
+
attr_accessor :cycle1_start_hour, :cycle1_start_minute, :cycle1_duration,
|
7
|
+
:cycle2_enabled, :cycle2_start_hour, :cycle2_start_minute, :cycle2_duration
|
8
|
+
alias_method :cycle2_enabled?, :cycle2_enabled
|
7
9
|
|
8
|
-
MESSAGE_TYPE = "\xbf\x23".force_encoding(Encoding::ASCII_8BIT)
|
10
|
+
MESSAGE_TYPE = (+"\xbf\x23").force_encoding(Encoding::ASCII_8BIT)
|
9
11
|
MESSAGE_LENGTH = 8
|
10
12
|
|
11
13
|
def parse(data)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
14
|
+
self.cycle1_start_hour = data[0].ord
|
15
|
+
self.cycle1_start_minute = data[1].ord
|
16
|
+
hours = data[2].ord
|
17
|
+
minutes = data[3].ord
|
18
|
+
self.cycle1_duration = (hours * 60) + minutes
|
19
|
+
|
20
|
+
c2_hour = data[4].ord
|
21
|
+
self.cycle2_enabled = !!(c2_hour & 0x80 == 0x80)
|
22
|
+
self.cycle2_start_hour = c2_hour & 0x7f
|
23
|
+
self.cycle2_start_minute = data[5].ord
|
24
|
+
hours = data[6].ord
|
25
|
+
minutes = data[7].ord
|
26
|
+
self.cycle2_duration = (hours * 60) + minutes
|
27
|
+
end
|
28
|
+
|
29
|
+
def serialize
|
30
|
+
data = cycle1_start_hour.chr
|
31
|
+
data += cycle1_start_minute.chr
|
32
|
+
data += (cycle1_duration / 60).chr
|
33
|
+
data += (cycle1_duration % 60).chr
|
34
|
+
|
35
|
+
# The cycle2 start hour is merged with the cycle2 enable.
|
36
|
+
# The high order bit of the byte is a flag to indicate this so we have
|
37
|
+
# to do a bit of different processing to set that.
|
38
|
+
# Get the filter 2 start hour
|
39
|
+
start_hour = cycle2_start_hour
|
40
|
+
|
41
|
+
# Check to see if we want filter 2 enabled (either because it changed or from the current configuration)
|
42
|
+
start_hour |= 0x80 if cycle2_enabled
|
43
|
+
|
44
|
+
data += start_hour.chr
|
45
|
+
|
46
|
+
data += cycle2_start_minute.chr
|
47
|
+
data += (cycle2_duration / 60).chr
|
48
|
+
data += (cycle2_duration % 60).chr
|
49
|
+
|
50
|
+
super(data)
|
23
51
|
end
|
24
52
|
|
25
53
|
def inspect
|
26
|
-
result = "#<BWA::Messages::FilterCycles "
|
54
|
+
result = +"#<BWA::Messages::FilterCycles "
|
27
55
|
|
28
|
-
result << "
|
29
|
-
result << self.class.format_duration(
|
56
|
+
result << "cycle1 "
|
57
|
+
result << self.class.format_duration(cycle1_duration)
|
30
58
|
result << "@"
|
31
|
-
result << self.class.format_time(
|
59
|
+
result << self.class.format_time(cycle1_start_hour, cycle1_start_minute)
|
32
60
|
|
33
|
-
result << "
|
34
|
-
result << self.class.format_duration(
|
61
|
+
result << " cycle2(#{@cycle2_enabled ? "enabled" : "disabled"}) "
|
62
|
+
result << self.class.format_duration(cycle2_duration)
|
35
63
|
result << "@"
|
36
|
-
result << self.class.format_time(
|
64
|
+
result << self.class.format_time(cycle2_start_hour, cycle2_start_minute)
|
37
65
|
|
38
66
|
result << ">"
|
39
67
|
end
|
data/lib/bwa/messages/ready.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BWA
|
2
4
|
module Messages
|
3
|
-
class
|
4
|
-
MESSAGE_TYPE = "\xbf\x20".force_encoding(Encoding::ASCII_8BIT)
|
5
|
+
class SetTargetTemperature < Message
|
6
|
+
MESSAGE_TYPE = (+"\xbf\x20").force_encoding(Encoding::ASCII_8BIT)
|
5
7
|
MESSAGE_LENGTH = 1
|
6
8
|
|
7
9
|
attr_accessor :temperature
|
@@ -20,7 +22,7 @@ module BWA
|
|
20
22
|
end
|
21
23
|
|
22
24
|
def inspect
|
23
|
-
"#<BWA::Messages::
|
25
|
+
"#<BWA::Messages::SetTargetTemperature #{temperature}°>"
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BWA
|
2
4
|
module Messages
|
3
5
|
class SetTemperatureScale < Message
|
4
|
-
MESSAGE_TYPE = "\xbf\x27".force_encoding(Encoding::ASCII_8BIT)
|
6
|
+
MESSAGE_TYPE = (+"\xbf\x27").force_encoding(Encoding::ASCII_8BIT)
|
5
7
|
MESSAGE_LENGTH = 2
|
6
8
|
|
7
9
|
attr_accessor :scale
|
@@ -12,7 +14,7 @@ module BWA
|
|
12
14
|
end
|
13
15
|
|
14
16
|
def parse(data)
|
15
|
-
self.scale = data[1].ord
|
17
|
+
self.scale = data[1].ord.zero? ? :fahrenheit : :celsius
|
16
18
|
end
|
17
19
|
|
18
20
|
def serialize
|
@@ -22,7 +24,7 @@ module BWA
|
|
22
24
|
end
|
23
25
|
|
24
26
|
def inspect
|
25
|
-
"#<BWA::Messages::SetTemperatureScale
|
27
|
+
"#<BWA::Messages::SetTemperatureScale °#{scale.to_s[0].upcase}>"
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BWA
|
2
4
|
module Messages
|
3
5
|
class SetTime < Message
|
4
|
-
MESSAGE_TYPE = "\xbf\x21".force_encoding(Encoding::ASCII_8BIT)
|
6
|
+
MESSAGE_TYPE = (+"\xbf\x21").force_encoding(Encoding::ASCII_8BIT)
|
5
7
|
MESSAGE_LENGTH = 2
|
6
8
|
|
7
9
|
attr_accessor :hour, :minute, :twenty_four_hour_time
|
@@ -24,7 +26,7 @@ module BWA
|
|
24
26
|
end
|
25
27
|
|
26
28
|
def inspect
|
27
|
-
"#<BWA::Messages::SetTime #{Status.format_time(hour, minute, twenty_four_hour_time)}>"
|
29
|
+
"#<BWA::Messages::SetTime #{Status.format_time(hour, minute, twenty_four_hour_time: twenty_four_hour_time)}>"
|
28
30
|
end
|
29
31
|
end
|
30
32
|
end
|
data/lib/bwa/messages/status.rb
CHANGED
@@ -1,63 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BWA
|
2
4
|
module Messages
|
3
5
|
class Status < Message
|
4
6
|
attr_accessor :hold,
|
5
7
|
:priming,
|
6
8
|
:heating_mode,
|
7
|
-
:temperature_scale,
|
8
9
|
:twenty_four_hour_time,
|
9
|
-
:
|
10
|
+
:filter_cycles,
|
10
11
|
:heating,
|
11
12
|
:temperature_range,
|
12
13
|
:hour, :minute,
|
13
|
-
:
|
14
|
+
:circulation_pump,
|
14
15
|
:blower,
|
15
16
|
:pumps,
|
16
17
|
:lights,
|
17
18
|
:mister,
|
18
19
|
:aux,
|
19
|
-
:current_temperature,
|
20
|
+
:current_temperature,
|
21
|
+
:target_temperature
|
22
|
+
attr_reader :temperature_scale
|
23
|
+
alias_method :hold?, :hold
|
24
|
+
alias_method :priming?, :priming
|
25
|
+
alias_method :twenty_four_hour_time?, :twenty_four_hour_time
|
26
|
+
alias_method :heating?, :heating
|
20
27
|
|
21
|
-
MESSAGE_TYPE = "\xaf\x13".force_encoding(Encoding::ASCII_8BIT)
|
28
|
+
MESSAGE_TYPE = (+"\xaf\x13").force_encoding(Encoding::ASCII_8BIT)
|
22
29
|
# additional features have been added in later versions
|
23
|
-
MESSAGE_LENGTH = 24..32
|
30
|
+
MESSAGE_LENGTH = (24..32).freeze
|
24
31
|
|
25
32
|
def initialize
|
33
|
+
super
|
34
|
+
|
26
35
|
@src = 0xff
|
27
36
|
self.hold = false
|
28
37
|
self.priming = false
|
29
38
|
self.heating_mode = :ready
|
30
39
|
@temperature_scale = :fahrenheit
|
31
40
|
self.twenty_four_hour_time = false
|
32
|
-
self.
|
41
|
+
self.filter_cycles = Array.new(2, false)
|
33
42
|
self.heating = false
|
34
43
|
self.temperature_range = :high
|
35
44
|
self.hour = self.minute = 0
|
36
|
-
self.
|
45
|
+
self.circulation_pump = false
|
37
46
|
self.pumps = Array.new(6, 0)
|
38
47
|
self.lights = Array.new(2, false)
|
39
48
|
self.mister = false
|
40
49
|
self.aux = Array.new(2, false)
|
41
|
-
self.
|
50
|
+
self.target_temperature = 100
|
42
51
|
end
|
43
52
|
|
44
53
|
def parse(data)
|
45
54
|
flags = data[0].ord
|
46
|
-
self.hold = (flags & 0x05 != 0
|
55
|
+
self.hold = (flags & 0x05 != 0)
|
47
56
|
|
48
57
|
flags = data[1].ord
|
49
58
|
self.priming = (flags & 0x01 == 0x01)
|
50
59
|
flags = data[5].ord
|
51
60
|
self.heating_mode = case flags & 0x03
|
52
|
-
|
53
|
-
|
54
|
-
|
61
|
+
when 0x00 then :ready
|
62
|
+
when 0x01 then :rest
|
63
|
+
when 0x02 then :ready_in_rest
|
55
64
|
end
|
56
65
|
flags = data[9].ord
|
57
66
|
self.temperature_scale = (flags & 0x01 == 0x01) ? :celsius : :fahrenheit
|
58
67
|
self.twenty_four_hour_time = (flags & 0x02 == 0x02)
|
59
|
-
|
60
|
-
|
68
|
+
filter_cycles[0] = (flags & 0x04 != 0)
|
69
|
+
filter_cycles[1] = (flags & 0x08 != 0)
|
61
70
|
flags = data[10].ord
|
62
71
|
self.heating = (flags & 0x30 != 0)
|
63
72
|
self.temperature_range = (flags & 0x04 == 0x04) ? :high : :low
|
@@ -71,7 +80,7 @@ module BWA
|
|
71
80
|
pumps[5] = (flags >> 2) & 0x03
|
72
81
|
|
73
82
|
flags = data[13].ord
|
74
|
-
self.
|
83
|
+
self.circulation_pump = (flags & 0x02 == 0x02)
|
75
84
|
self.blower = (flags & 0x0C == 0x0C)
|
76
85
|
flags = data[14].ord
|
77
86
|
lights[0] = (flags & 0x03 != 0)
|
@@ -83,23 +92,22 @@ module BWA
|
|
83
92
|
self.hour = data[3].ord
|
84
93
|
self.minute = data[4].ord
|
85
94
|
self.current_temperature = data[2].ord
|
86
|
-
self.current_temperature = nil if
|
87
|
-
self.
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
95
|
+
self.current_temperature = nil if current_temperature == 0xff
|
96
|
+
self.target_temperature = data[20].ord
|
97
|
+
|
98
|
+
return unless temperature_scale == :celsius
|
99
|
+
|
100
|
+
self.current_temperature /= 2.0 if current_temperature
|
101
|
+
self.target_temperature /= 2.0 if target_temperature
|
92
102
|
end
|
93
103
|
|
94
104
|
def serialize
|
95
105
|
data = "\x00" * 24
|
96
106
|
data[0] = (hold ? 0x05 : 0x00).chr
|
97
107
|
data[1] = (priming ? 0x01 : 0x00).chr
|
98
|
-
data[5] =
|
99
|
-
|
100
|
-
|
101
|
-
when :ready_in_rest; 0x02
|
102
|
-
end).chr
|
108
|
+
data[5] = { ready: 0x00,
|
109
|
+
rest: 0x01,
|
110
|
+
ready_in_rest: 0x02 }[heating_mode].chr
|
103
111
|
flags = 0
|
104
112
|
flags |= 0x01 if temperature_scale == :celsius
|
105
113
|
flags |= 0x02 if twenty_four_hour_time
|
@@ -113,7 +121,7 @@ module BWA
|
|
113
121
|
flags |= pump2 * 4
|
114
122
|
data[11] = flags.chr
|
115
123
|
flags = 0
|
116
|
-
flags |= 0x02 if
|
124
|
+
flags |= 0x02 if circulation_pump
|
117
125
|
data[13] = flags.chr
|
118
126
|
flags = 0
|
119
127
|
flags |= 0x03 if light1
|
@@ -122,10 +130,10 @@ module BWA
|
|
122
130
|
data[4] = minute.chr
|
123
131
|
if temperature_scale == :celsius
|
124
132
|
data[2] = (current_temperature ? (current_temperature * 2).to_i : 0xff).chr
|
125
|
-
data[20] = (
|
133
|
+
data[20] = (target_temperature * 2).to_i.chr
|
126
134
|
else
|
127
135
|
data[2] = (current_temperature.to_i || 0xff).chr
|
128
|
-
data[20] =
|
136
|
+
data[20] = target_temperature.to_i.chr
|
129
137
|
end
|
130
138
|
|
131
139
|
super(data)
|
@@ -135,47 +143,46 @@ module BWA
|
|
135
143
|
if value != @temperature_scale
|
136
144
|
if value == :fahrenheit
|
137
145
|
if current_temperature
|
138
|
-
self.current_temperature *= 9.0/5
|
146
|
+
self.current_temperature *= 9.0 / 5
|
139
147
|
self.current_temperature += 32
|
140
148
|
self.current_temperature = current_temperature.round
|
141
149
|
end
|
142
|
-
self.
|
143
|
-
self.
|
144
|
-
self.
|
150
|
+
self.target_temperature *= 9.0 / 5
|
151
|
+
self.target_temperature += 32
|
152
|
+
self.target_temperature = target_temperature.round
|
145
153
|
else
|
146
154
|
if current_temperature
|
147
155
|
self.current_temperature -= 32
|
148
|
-
self.current_temperature *= 5.0/90
|
156
|
+
self.current_temperature *= 5.0 / 90
|
149
157
|
self.current_temperature = (current_temperature * 2).round / 2.0
|
150
158
|
end
|
151
|
-
self.
|
152
|
-
self.
|
153
|
-
self.
|
159
|
+
self.target_temperature -= 32
|
160
|
+
self.target_temperature *= 5.0 / 9
|
161
|
+
self.target_temperature = (target_temperature * 2).round / 2.0
|
154
162
|
end
|
155
163
|
end
|
156
164
|
@temperature_scale = value
|
157
165
|
end
|
158
166
|
|
159
167
|
def inspect
|
160
|
-
result = "#<BWA::Messages::Status "
|
161
168
|
items = []
|
162
169
|
|
163
170
|
items << "hold" if hold
|
164
171
|
items << "priming" if priming
|
165
|
-
items << self.class.format_time(hour, minute, twenty_four_hour_time)
|
166
|
-
items << "#{current_temperature ||
|
167
|
-
items << "
|
172
|
+
items << self.class.format_time(hour, minute, twenty_four_hour_time: twenty_four_hour_time)
|
173
|
+
items << "#{current_temperature || "--"}/#{target_temperature}°#{temperature_scale.to_s[0].upcase}"
|
174
|
+
items << "filter_cycles=#{filter_cycles.inspect}"
|
168
175
|
items << heating_mode
|
169
176
|
items << "heating" if heating
|
170
177
|
items << temperature_range
|
171
|
-
items << "
|
178
|
+
items << "circulation_pump" if circulation_pump
|
172
179
|
items << "blower" if blower
|
173
180
|
items << "pumps=#{pumps.inspect}"
|
174
181
|
items << "lights=#{lights.inspect}"
|
175
182
|
items << "aux=#{aux.inspect}"
|
176
183
|
items << "mister" if mister
|
177
184
|
|
178
|
-
|
185
|
+
"#<BWA::Messages::Status #{items.join(" ")}>"
|
179
186
|
end
|
180
187
|
end
|
181
188
|
end
|
@@ -1,8 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BWA
|
2
4
|
module Messages
|
3
5
|
class ToggleItem < Message
|
4
|
-
MESSAGE_TYPE = "\xbf\x11".force_encoding(Encoding::ASCII_8BIT)
|
6
|
+
MESSAGE_TYPE = (+"\xbf\x11").force_encoding(Encoding::ASCII_8BIT)
|
5
7
|
MESSAGE_LENGTH = 2
|
8
|
+
ITEMS = {
|
9
|
+
normal_operation: 0x01,
|
10
|
+
clear_notification: 0x03,
|
11
|
+
pump1: 0x04,
|
12
|
+
pump2: 0x05,
|
13
|
+
pump3: 0x06,
|
14
|
+
pump4: 0x07,
|
15
|
+
pump5: 0x08,
|
16
|
+
pump6: 0x09,
|
17
|
+
blower: 0x0c,
|
18
|
+
mister: 0x0e,
|
19
|
+
light1: 0x11,
|
20
|
+
light2: 0x12,
|
21
|
+
aux1: 0x16,
|
22
|
+
aux2: 0x17,
|
23
|
+
hold: 0x3c,
|
24
|
+
temperature_range: 0x50,
|
25
|
+
heating_mode: 0x51
|
26
|
+
}.freeze
|
6
27
|
|
7
28
|
attr_accessor :item
|
8
29
|
|
@@ -12,35 +33,16 @@ module BWA
|
|
12
33
|
end
|
13
34
|
|
14
35
|
def parse(data)
|
15
|
-
self.item =
|
16
|
-
when 0x04; :pump1
|
17
|
-
when 0x05; :pump2
|
18
|
-
when 0x0c; :blower
|
19
|
-
when 0x0e; :mister
|
20
|
-
when 0x11; :light1
|
21
|
-
when 0x3c; :hold
|
22
|
-
when 0x50; :temperature_range
|
23
|
-
when 0x51; :heating_mode
|
24
|
-
else; data[0].ord
|
25
|
-
end
|
36
|
+
self.item = ITEMS.invert[data[0].ord] || data[0].ord
|
26
37
|
end
|
27
38
|
|
28
39
|
def serialize
|
29
|
-
data = "\x00\x00"
|
30
|
-
if item.is_a? Integer
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
when :pump2; 0x05
|
36
|
-
when :blower; 0x0c
|
37
|
-
when :mister; 0x0e
|
38
|
-
when :light1; 0x11
|
39
|
-
when :hold; 0x3c
|
40
|
-
when :temperature_range; 0x50
|
41
|
-
when :heating_mode; 0x51
|
42
|
-
end).chr
|
43
|
-
end
|
40
|
+
data = +"\x00\x00"
|
41
|
+
data[0] = if item.is_a? Integer
|
42
|
+
item.chr
|
43
|
+
else
|
44
|
+
ITEMS[item].chr
|
45
|
+
end
|
44
46
|
super(data)
|
45
47
|
end
|
46
48
|
|
data/lib/bwa/proxy.rb
CHANGED
@@ -1,32 +1,31 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "socket"
|
4
|
+
require "bwa/logger"
|
5
|
+
require "bwa/message"
|
4
6
|
|
5
7
|
module BWA
|
6
8
|
class Proxy
|
7
|
-
def initialize(host, port: 4257
|
9
|
+
def initialize(host, port: 4257)
|
8
10
|
@host, @port = host, port
|
9
11
|
@listen_socket = TCPServer.open(port)
|
10
12
|
end
|
11
13
|
|
12
14
|
def run
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
shuffle_messages(server_socket, client_socket, "Server")
|
21
|
-
end
|
22
|
-
t1.join
|
23
|
-
t2.join
|
24
|
-
break
|
15
|
+
client_socket = @listen_socket.accept
|
16
|
+
server_socket = TCPSocket.new(@host, @port)
|
17
|
+
t1 = Thread.new do
|
18
|
+
shuffle_messages(client_socket, server_socket, "Client")
|
19
|
+
end
|
20
|
+
t2 = Thread.new do
|
21
|
+
shuffle_messages(server_socket, client_socket, "Server")
|
25
22
|
end
|
23
|
+
t1.join
|
24
|
+
t2.join
|
26
25
|
end
|
27
26
|
|
28
27
|
def shuffle_messages(socket1, socket2, tag)
|
29
|
-
leftover_data = "".force_encoding(Encoding::ASCII_8BIT)
|
28
|
+
leftover_data = (+"").force_encoding(Encoding::ASCII_8BIT)
|
30
29
|
loop do
|
31
30
|
if leftover_data.length < 2 || leftover_data.length < leftover_data[1].ord + 2
|
32
31
|
begin
|
@@ -42,7 +41,7 @@ module BWA
|
|
42
41
|
end
|
43
42
|
data_length = leftover_data[1].ord
|
44
43
|
data = leftover_data[0...(data_length + 2)]
|
45
|
-
leftover_data = leftover_data[(data_length + 2)..-1] ||
|
44
|
+
leftover_data = leftover_data[(data_length + 2)..-1] || ""
|
46
45
|
begin
|
47
46
|
message = Message.parse(data)
|
48
47
|
BWA.logger.info "#{tag}: #{message.inspect}"
|