balboa_worldwide_app 1.3.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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}"
|