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.
data/lib/bwa/client.rb CHANGED
@@ -1,28 +1,59 @@
1
- require 'uri'
1
+ # frozen_string_literal: true
2
2
 
3
- require 'bwa/logger'
4
- require 'bwa/message'
3
+ require "forwardable"
4
+ require "uri"
5
+
6
+ require "bwa/logger"
7
+ require "bwa/message"
5
8
 
6
9
  module BWA
7
10
  class Client
8
- attr_reader :last_status, :last_control_configuration, :last_control_configuration2, :last_filter_configuration
11
+ extend Forwardable
12
+
13
+ attr_reader :status, :control_configuration, :configuration, :filter_cycles
14
+
15
+ delegate model: :control_configuration
16
+ delegate %i[hold
17
+ hold?
18
+ priming
19
+ priming?
20
+ heating_mode
21
+ temperature_scale
22
+ twenty_four_hour_time
23
+ twenty_four_hour_time?
24
+ heating
25
+ heating?
26
+ temperature_range
27
+ current_temperature
28
+ target_temperature
29
+ circulation_pump
30
+ blower
31
+ mister
32
+ pumps
33
+ lights
34
+ aux] => :status
9
35
 
10
36
  def initialize(uri)
11
37
  uri = URI.parse(uri)
12
- if uri.scheme == 'tcp'
13
- require 'socket'
38
+ case uri.scheme
39
+ when "tcp"
40
+ require "socket"
14
41
  @io = TCPSocket.new(uri.host, uri.port || 4257)
15
- elsif uri.scheme == 'telnet' || uri.scheme == 'rfc2217'
16
- require 'net/telnet/rfc2217'
17
- @io = Net::Telnet::RFC2217.new("Host" => uri.host, "Port" => uri.port || 23, "baud" => 115200)
42
+ when "telnet", "rfc2217"
43
+ require "net/telnet/rfc2217"
44
+ @io = Net::Telnet::RFC2217.new("Host" => uri.host, "Port" => uri.port || 23, "baud" => 115_200)
18
45
  @queue = []
19
46
  else
20
- require 'ccutrer-serialport'
21
- @io = CCutrer::SerialPort.new(uri.path, baud: 115200)
47
+ require "ccutrer-serialport"
48
+ @io = CCutrer::SerialPort.new(uri.path, baud: 115_200)
22
49
  @queue = []
23
50
  end
24
51
  @src = 0x0a
25
- @buffer = ""
52
+ @buffer = +""
53
+ end
54
+
55
+ def full_configuration?
56
+ status && control_configuration && configuration && filter_cycles
26
57
  end
27
58
 
28
59
  def poll
@@ -45,18 +76,20 @@ module BWA
45
76
  end
46
77
 
47
78
  if message.is_a?(Messages::Ready) && (msg = @queue&.shift)
48
- BWA.logger.debug "wrote: #{BWA.raw2str(msg)}" unless BWA.verbosity < 1 && msg[3..4] == Messages::ControlConfigurationRequest::MESSAGE_TYPE
79
+ unless BWA.verbosity < 1 && msg[3..4] == Messages::ControlConfigurationRequest::MESSAGE_TYPE
80
+ BWA.logger.debug "wrote: #{BWA.raw2str(msg)}"
81
+ end
49
82
  @io.write(msg)
50
83
  end
51
- @last_status = message.dup if message.is_a?(Messages::Status)
52
- @last_filter_configuration = message.dup if message.is_a?(Messages::FilterCycles)
53
- @last_control_configuration = message.dup if message.is_a?(Messages::ControlConfiguration)
54
- @last_control_configuration2 = message.dup if message.is_a?(Messages::ControlConfiguration2)
84
+ @status = message.dup if message.is_a?(Messages::Status)
85
+ @filter_cycles = message.dup if message.is_a?(Messages::FilterCycles)
86
+ @control_configuration = message.dup if message.is_a?(Messages::ControlConfiguration)
87
+ @configuration = message.dup if message.is_a?(Messages::ControlConfiguration2)
55
88
  message
56
89
  end
57
90
 
58
91
  def messages_pending?
59
- !!IO.select([@io], nil, nil, 0)
92
+ !!@io.wait_readable(0)
60
93
  end
61
94
 
62
95
  def drain_message_queue
@@ -65,12 +98,16 @@ module BWA
65
98
 
66
99
  def send_message(message)
67
100
  message.src = @src
68
- BWA.logger.info " to spa: #{message.inspect}" unless BWA.verbosity < 1 && message.is_a?(Messages::ControlConfigurationRequest)
69
101
  full_message = message.serialize
102
+ unless BWA.verbosity < 1 && message.is_a?(Messages::ControlConfigurationRequest)
103
+ BWA.logger.info " to spa: #{message.inspect}"
104
+ end
70
105
  if @queue
71
106
  @queue.push(full_message)
72
107
  else
73
- BWA.logger.debug "wrote: #{BWA.raw2str(full_message)}" unless BWA.verbosity < 1 && message.is_a?(Messages::ControlConfigurationRequest)
108
+ unless BWA.verbosity < 1 && message.is_a?(Messages::ControlConfigurationRequest)
109
+ BWA.logger.debug "wrote: #{BWA.raw2str(full_message)}"
110
+ end
74
111
  @io.write(full_message)
75
112
  end
76
113
  end
@@ -95,12 +132,16 @@ module BWA
95
132
  send_message(Messages::ToggleItem.new(item))
96
133
  end
97
134
 
98
- def toggle_pump(i)
99
- toggle_item(i + 3)
135
+ def toggle_pump(index)
136
+ toggle_item(index + 0x04)
100
137
  end
101
138
 
102
- def toggle_light(i)
103
- toggle_item(i + 0x10)
139
+ def toggle_light(index)
140
+ toggle_item(index + 0x11)
141
+ end
142
+
143
+ def toggle_aux(index)
144
+ toggle_item(index + 0x16)
104
145
  end
105
146
 
106
147
  def toggle_mister
@@ -115,90 +156,77 @@ module BWA
115
156
  toggle_item(:hold)
116
157
  end
117
158
 
118
- def set_pump(i, desired)
119
- return unless last_status && last_control_configuration2
120
- times = (desired - last_status.pumps[i - 1]) % (last_control_configuration2.pumps[i - 1] + 1)
159
+ def set_pump(index, desired)
160
+ return unless status && configuration
161
+
162
+ desired = 0 if desired == false
163
+ desired = 1 if desired == true
164
+ times = (desired - status.pumps[index]) % (configuration.pumps[index] + 1)
121
165
  times.times do
122
- toggle_pump(i)
166
+ toggle_pump(index)
123
167
  sleep(0.1)
124
168
  end
125
169
  end
126
170
 
127
- %w{light aux}.each do |type|
171
+ %i[light aux].each do |type|
172
+ suffix = "s" if type == :light
128
173
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
129
- def set_#{type}(i, desired)
130
- return unless last_status
131
- return if last_status.#{type}s[i - 1] == desired
132
- toggle_#{type}(i)
174
+ def set_#{type}(index, desired)
175
+ return unless status
176
+ return if status.#{type}#{suffix}[index] == desired
177
+
178
+ toggle_#{type}(index)
133
179
  end
134
180
  RUBY
135
181
  end
136
182
 
137
- def set_mister(desired)
138
- return unless last_status
139
- return if last_status.mister == desired
183
+ def mister=(desired)
184
+ return unless status
185
+ return if status.mister == desired
186
+
140
187
  toggle_mister
141
188
  end
142
189
 
143
- def set_blower(desired)
144
- return unless last_status && last_control_configuration2
145
- times = (desired - last_status.blower) % (last_control_configuration2.blower + 1)
190
+ def blower=(desired)
191
+ return unless status && configuration
192
+
193
+ times = (desired - status.blower) % (configuration.blower + 1)
146
194
  times.times do
147
195
  toggle_blower
148
196
  sleep(0.1)
149
197
  end
150
198
  end
151
199
 
152
- def set_hold(desired)
153
- return unless last_status
154
- return if last_status.hold == desired
200
+ def hold=(desired)
201
+ return unless status
202
+ return if status.hold == desired
203
+
155
204
  toggle_hold
156
205
  end
157
206
 
158
207
  # high range is 80-106 for F, 26-40 for C (by 0.5)
159
208
  # low range is 50-99 for F, 10-26 for C (by 0.5)
160
- def set_temperature(desired)
161
- return unless last_status
162
- return if last_status.set_temperature == desired
209
+ def target_temperature=(desired)
210
+ return unless status
211
+ return if status.target_temperature == desired
163
212
 
164
- desired *= 2 if last_status && last_status.temperature_scale == :celsius || desired < 50
165
- send_message(Messages::SetTemperature.new(desired.round))
213
+ desired *= 2 if (status && status.temperature_scale == :celsius) || desired < 50
214
+ send_message(Messages::SetTargetTemperature.new(desired.round))
166
215
  end
167
216
 
168
- def set_time(hour, minute, twenty_four_hour_time = false)
217
+ def set_time(hour, minute, twenty_four_hour_time: false)
169
218
  send_message(Messages::SetTime.new(hour, minute, twenty_four_hour_time))
170
219
  end
171
220
 
172
- def set_temperature_scale(scale)
173
- raise ArgumentError, "scale must be :fahrenheit or :celsius" unless %I{fahrenheit :celsius}.include?(scale)
221
+ def temperature_scale=(scale)
222
+ raise ArgumentError, "scale must be :fahrenheit or :celsius" unless %I[fahrenheit celsius].include?(scale)
223
+
174
224
  send_message(Messages::SetTemperatureScale.new(scale))
175
225
  end
176
226
 
177
- def set_filtercycles(changedItem, changedValue)
178
- #changedItem - String name of item that was changed
179
- #changedValue - String value of the item that changed
180
- if @last_filter_configuration
181
- messagedata = if changedItem == "filter1hour" then changedValue.to_i.chr else @last_filter_configuration.filter1_hour.chr end
182
- messagedata += if changedItem == "filter1minute" then changedValue.to_i.chr else @last_filter_configuration.filter1_minute.chr end
183
- messagedata += if changedItem == "filter1durationhours" then changedValue.to_i.chr else @last_filter_configuration.filter1_duration_hours.chr end
184
- messagedata += if changedItem == "filter1durationminutes" then changedValue.to_i.chr else @last_filter_configuration.filter1_duration_minutes.chr end
185
-
186
- #The filter2 start hour is merged with the filter2 enable (who thought that was a good idea?) The high order bit of the byte is a flag
187
- #to indicate this so we have to do a bit of different processing to do that
188
- #Get the filter 2 start hour
189
- starthour = if changedItem == "filter2hour" then changedValue.to_i else @last_filter_configuration.filter2_hour end
190
- #Check to see if we want filter 2 enabled (either because it changed or from the current configuration)
191
- #If it is something that changed, we have to convert to boolean, if it is from the current config it already is a boolean
192
- starthour |= 0x80 if (if changedItem == "filter2enabled" then (changedValue == "true" ? true : false) else @last_filter_configuration.filter2_enabled end)
193
-
194
- messagedata += starthour.chr
195
-
196
- messagedata += if changedItem == "filter2minute" then changedValue.to_i.chr else @last_filter_configuration.filter2_minute.chr end
197
- messagedata += if changedItem == "filter2durationhours" then changedValue.to_i.chr else @last_filter_configuration.filter2_duration_hours.chr end
198
- messagedata += if changedItem == "filter2durationminutes" then changedValue.to_i.chr else @last_filter_configuration.filter2_duration_minutes.chr end
199
-
200
- send_message("\x0a\xbf\x23".force_encoding(Encoding::ASCII_8BIT) + messagedata)
201
- end
227
+ def update_filter_cycles(new_filter_cycles)
228
+ send_message(new_filter_cycles)
229
+ @filter_cycles = new_filter_cycles.dup
202
230
  request_filter_configuration
203
231
  end
204
232
 
@@ -206,9 +234,10 @@ module BWA
206
234
  toggle_item(0x50)
207
235
  end
208
236
 
209
- def set_temperature_range(desired)
210
- return unless last_status
211
- return if last_status.temperature_range == desired
237
+ def temperature_range=(desired)
238
+ return unless status
239
+ return if status.temperature_range == desired
240
+
212
241
  toggle_temperature_range
213
242
  end
214
243
 
@@ -216,19 +245,20 @@ module BWA
216
245
  toggle_item(:heating_mode)
217
246
  end
218
247
 
219
- HEATING_MODES = %I{ready rest ready_in_rest}.freeze
220
- def set_heating_mode(desired)
221
- raise ArgumentError, "heating_mode must be :ready or :rest" unless %I{ready rest}.include?(desired)
222
- return unless last_status
223
- times = if last_status.heating_mode == :ready && desired == :rest ||
224
- last_status.heating_mode == :rest && desired == :ready ||
225
- last_status.heating_mode == :ready_in_rest && desired == :rest
226
- 1
227
- elsif last_status.heating_mode == :ready_in_rest && desired == :ready
228
- 2
229
- else
230
- 0
231
- end
248
+ HEATING_MODES = %I[ready rest ready_in_rest].freeze
249
+ def heating_mode=(desired)
250
+ raise ArgumentError, "heating_mode must be :ready or :rest" unless %I[ready rest].include?(desired)
251
+ return unless status
252
+
253
+ times = if (status.heating_mode == :ready && desired == :rest) ||
254
+ (status.heating_mode == :rest && desired == :ready) ||
255
+ (status.heating_mode == :ready_in_rest && desired == :rest)
256
+ 1
257
+ elsif status.heating_mode == :ready_in_rest && desired == :ready
258
+ 2
259
+ else
260
+ 0
261
+ end
232
262
  times.times { toggle_heating_mode }
233
263
  end
234
264
  end
data/lib/bwa/crc.rb CHANGED
@@ -1,4 +1,6 @@
1
- require 'digest/crc'
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/crc"
2
4
 
3
5
  module BWA
4
6
  class CRC < Digest::CRC8
data/lib/bwa/discovery.rb CHANGED
@@ -1,27 +1,27 @@
1
- require 'socket'
2
- require 'bwa/logger'
1
+ # frozen_string_literal: true
2
+
3
+ require "socket"
4
+ require "bwa/logger"
3
5
 
4
6
  module BWA
5
7
  class Discovery
6
8
  class << self
7
- def discover(timeout = 5, exhaustive = false)
9
+ def discover(timeout = 5, exhaustive: false)
8
10
  socket = UDPSocket.new
9
11
  socket.bind("0.0.0.0", 0)
10
12
  socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
11
- socket.sendmsg("Discovery: Who is out there?", 0, Socket.sockaddr_in(30303, '255.255.255.255'))
13
+ socket.sendmsg("Discovery: Who is out there?", 0, Socket.sockaddr_in(30_303, "255.255.255.255"))
12
14
  spas = {}
13
15
  loop do
14
- if IO.select([socket], nil, nil, timeout)
15
- msg, ip = socket.recvfrom(64)
16
- ip = ip[2]
17
- name, mac = msg.split("\r\n")
18
- name.strip!
19
- if mac.start_with?("00-15-27-")
20
- spas[ip] = name
21
- break unless exhaustive
22
- end
23
- else
24
- break
16
+ break unless socket.wait_readable(timeout)
17
+
18
+ msg, ip = socket.recvfrom(64)
19
+ ip = ip[2]
20
+ name, mac = msg.split("\r\n")
21
+ name.strip!
22
+ if mac.start_with?("00-15-27-")
23
+ spas[ip] = name
24
+ break unless exhaustive
25
25
  end
26
26
  end
27
27
  spas
@@ -29,11 +29,12 @@ module BWA
29
29
 
30
30
  def advertise
31
31
  socket = UDPSocket.new
32
- socket.bind("0.0.0.0", 30303)
32
+ socket.bind("0.0.0.0", 30_303)
33
33
  msg = "BWGSPA\r\n00-15-27-00-00-01\r\n"
34
34
  loop do
35
35
  data, addr = socket.recvfrom(32)
36
- next unless data == 'Discovery: Who is out there?'
36
+ next unless data == "Discovery: Who is out there?"
37
+
37
38
  ip = addr.last
38
39
  BWA.logger.info "Advertising to #{ip}"
39
40
  socket.sendmsg(msg, 0, Socket.sockaddr_in(addr[1], ip))
data/lib/bwa/logger.rb CHANGED
@@ -1,4 +1,6 @@
1
- require 'logger'
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
2
4
 
3
5
  module BWA
4
6
  # This module logs to stdout by default, or you can provide a logger as BWA.logger.
@@ -23,10 +25,10 @@ module BWA
23
25
  attr_writer :logger, :verbosity
24
26
 
25
27
  def logger
26
- @logger ||= Logger.new(STDOUT).tap do |log|
27
- STDOUT.sync = true
28
- log.level = ENV.fetch("LOG_LEVEL","WARN")
29
- log.formatter = proc do |severity, datetime, progname, msg|
28
+ @logger ||= Logger.new($stdout).tap do |log|
29
+ $stdout.sync = true
30
+ log.level = ENV.fetch("LOG_LEVEL", "WARN")
31
+ log.formatter = proc do |severity, _datetime, _progname, msg|
30
32
  "#{severity[0..0]}, #{msg2logstr(msg)}\n"
31
33
  end
32
34
  end
@@ -42,14 +44,14 @@ module BWA
42
44
  when ::String
43
45
  msg
44
46
  when ::Exception
45
- "#{ msg.message } (#{ msg.class })\n#{ msg.backtrace.join("\n") if msg.backtrace }"
47
+ "#{msg.message} (#{msg.class})\n#{msg.backtrace&.join("\n")}"
46
48
  else
47
49
  msg.inspect
48
50
  end
49
51
  end
50
52
 
51
53
  def raw2str(data)
52
- data.unpack("H*").first.gsub!(/(..)/, "\\1 ").chop!
54
+ data.unpack1("H*").gsub!(/(..)/, "\\1 ").chop!
53
55
  end
54
56
  end
55
57
  end
data/lib/bwa/message.rb CHANGED
@@ -1,5 +1,7 @@
1
- require 'bwa/logger'
2
- require 'bwa/crc'
1
+ # frozen_string_literal: true
2
+
3
+ require "bwa/logger"
4
+ require "bwa/crc"
3
5
 
4
6
  module BWA
5
7
  class InvalidMessage < RuntimeError
@@ -19,53 +21,58 @@ module BWA
19
21
 
20
22
  class << self
21
23
  def inherited(klass)
24
+ super
25
+
22
26
  @messages ||= []
23
27
  @messages << klass
24
28
  end
25
29
 
26
30
  # Ignore (parse and throw away) messages of these types.
27
31
  IGNORED_MESSAGES = [
28
- "\xbf\x00".force_encoding(Encoding::ASCII_8BIT), # request for new clients
29
- "\xbf\xe1".force_encoding(Encoding::ASCII_8BIT),
30
- "\xbf\x07".force_encoding(Encoding::ASCII_8BIT), # nothing to send
31
- ]
32
+ (+"\xbf\x00").force_encoding(Encoding::ASCII_8BIT), # request for new clients
33
+ (+"\xbf\xe1").force_encoding(Encoding::ASCII_8BIT),
34
+ (+"\xbf\x07").force_encoding(Encoding::ASCII_8BIT) # nothing to send
35
+ ].freeze
32
36
 
33
37
  # Don't log messages of these types, even in DEBUG mode.
34
38
  # They are very frequent and would swamp the logs.
35
39
  def common_messages
36
- @COMMON_MESSAGES ||= begin
40
+ @common_messages ||= begin
37
41
  msgs = []
38
- msgs += [
39
- Messages::Status::MESSAGE_TYPE,
40
- "\xbf\xe1".force_encoding(Encoding::ASCII_8BIT),
41
- ] unless BWA.verbosity >= 1
42
- msgs += [
43
- "\xbf\x00".force_encoding(Encoding::ASCII_8BIT),
44
- "\xbf\xe1".force_encoding(Encoding::ASCII_8BIT),
45
- Messages::Ready::MESSAGE_TYPE,
46
- "\xbf\x07".force_encoding(Encoding::ASCII_8BIT),
47
- ] unless BWA.verbosity >= 2
42
+ unless BWA.verbosity >= 1
43
+ msgs += [
44
+ Messages::Status::MESSAGE_TYPE,
45
+ (+"\xbf\xe1").force_encoding(Encoding::ASCII_8BIT)
46
+ ]
47
+ end
48
+ unless BWA.verbosity >= 2
49
+ msgs += [
50
+ (+"\xbf\x00").force_encoding(Encoding::ASCII_8BIT),
51
+ (+"\xbf\xe1").force_encoding(Encoding::ASCII_8BIT),
52
+ Messages::Ready::MESSAGE_TYPE,
53
+ (+"\xbf\x07").force_encoding(Encoding::ASCII_8BIT)
54
+ ]
55
+ end
48
56
  msgs
49
57
  end
50
- @COMMON_MESSAGES
51
58
  end
52
59
 
53
60
  def parse(data)
54
61
  offset = -1
55
- message_type = length = message_class = nil
62
+ message_type = length = nil
56
63
  loop do
57
64
  offset += 1
58
65
  # Not enough data for a full message; return and hope for more
59
66
  return nil if data.length - offset < 5
60
67
 
61
68
  # Keep scanning until message start char
62
- next unless data[offset] == '~'
69
+ next unless data[offset] == "~"
63
70
 
64
71
  # Read length (safe since we have at least 5 chars)
65
72
  length = data[offset + 1].ord
66
73
 
67
74
  # No message is this short or this long; keep scanning
68
- next if length < 5 or length >= '~'.ord
75
+ next if (length < 5) || (length >= "~".ord)
69
76
 
70
77
  # don't have enough data for what this message wants;
71
78
  # return and hope for more (yes this might cause a
@@ -74,7 +81,7 @@ module BWA
74
81
  return nil if length + 2 > data.length - offset
75
82
 
76
83
  # Not properly terminated; keep scanning
77
- next unless data[offset + length + 1] == '~'
84
+ next unless data[offset + length + 1] == "~"
78
85
 
79
86
  # Not a valid checksum; keep scanning
80
87
  next unless CRC.checksum(data.slice(offset + 1, length - 1)) == data[offset + length].ord
@@ -84,8 +91,11 @@ module BWA
84
91
  end
85
92
 
86
93
  message_type = data.slice(offset + 3, 2)
87
- BWA.logger.debug "discarding invalid data prior to message #{BWA.raw2str(data[0...offset])}" unless offset == 0
88
- BWA.logger.debug " read: #{BWA.raw2str(data.slice(offset, length + 2))}" unless common_messages.include?(message_type)
94
+ BWA.logger.debug "discarding invalid data prior to message #{BWA.raw2str(data[0...offset])}" unless offset.zero?
95
+ unless common_messages.include?(message_type)
96
+ BWA.logger.debug " read: #{BWA.raw2str(data.slice(offset,
97
+ length + 2))}"
98
+ end
89
99
 
90
100
  src = data[offset + 2].ord
91
101
  klass = @messages.find { |k| k::MESSAGE_TYPE == message_type }
@@ -95,13 +105,18 @@ module BWA
95
105
 
96
106
  if klass
97
107
  valid_length = if klass::MESSAGE_LENGTH.respond_to?(:include?)
98
- klass::MESSAGE_LENGTH.include?(length - 5)
99
- else
100
- length - 5 == klass::MESSAGE_LENGTH
108
+ klass::MESSAGE_LENGTH.include?(length - 5)
109
+ else
110
+ length - 5 == klass::MESSAGE_LENGTH
111
+ end
112
+ unless valid_length
113
+ raise InvalidMessage.new("Unrecognized data length (#{length}) for message #{klass}",
114
+ data)
101
115
  end
102
- raise InvalidMessage.new("Unrecognized data length (#{length}) for message #{klass}", data) unless valid_length
103
116
  else
104
- BWA.logger.info "Unrecognized message type #{BWA.raw2str(message_type)}: #{BWA.raw2str(data.slice(offset, length + 2))}"
117
+ BWA.logger.info(
118
+ "Unrecognized message type #{BWA.raw2str(message_type)}: #{BWA.raw2str(data.slice(offset, length + 2))}"
119
+ )
105
120
  klass = Unrecognized
106
121
  end
107
122
 
@@ -113,53 +128,52 @@ module BWA
113
128
  [message, offset + length + 2]
114
129
  end
115
130
 
116
- def format_time(hour, minute, twenty_four_hour_time = true)
131
+ def format_time(hour, minute, twenty_four_hour_time: true)
117
132
  if twenty_four_hour_time
118
- print_hour = "%02d" % hour
133
+ format("%02d:%02d", hour, minute)
119
134
  else
120
135
  print_hour = hour % 12
121
- print_hour = 12 if print_hour == 0
122
- am_pm = (hour >= 12 ? "PM" : "AM")
136
+ print_hour = 12 if print_hour.zero?
137
+ format("%d:%02d%s", print_hour, minute, hour >= 12 ? "PM" : "AM")
123
138
  end
124
- "#{print_hour}:#{"%02d" % minute}#{am_pm}"
125
139
  end
126
140
 
127
- def format_duration(hours, minutes)
128
- "#{hours}:#{"%02d" % minutes}"
141
+ def format_duration(minutes)
142
+ format("%d:%02d", minutes / 60, minutes % 60)
129
143
  end
130
144
  end
131
145
 
132
- attr_reader :raw_data, :src
146
+ attr_reader :raw_data
133
147
 
134
148
  def initialize
135
149
  # most messages we're sending come from this address
136
150
  @src = 0x0a
137
151
  end
138
152
 
139
- def parse(_data)
140
- end
153
+ def parse(_data); end
141
154
 
142
155
  def serialize(message = "")
143
156
  length = message.length + 5
144
- full_message = "#{length.chr}#{src.chr}#{self.class::MESSAGE_TYPE}#{message}".force_encoding(Encoding::ASCII_8BIT)
157
+ full_message = (+"#{length.chr}#{src.chr}#{self.class::MESSAGE_TYPE}#{message}")
158
+ .force_encoding(Encoding::ASCII_8BIT)
145
159
  checksum = CRC.checksum(full_message)
146
- "\x7e#{full_message}#{checksum.chr}\x7e".force_encoding(Encoding::ASCII_8BIT)
160
+ (+"\x7e#{full_message}#{checksum.chr}\x7e").force_encoding(Encoding::ASCII_8BIT)
147
161
  end
148
162
 
149
163
  def inspect
150
- "#<#{self.class.name} #{raw_data.unpack("H*").first}>"
164
+ "#<#{self.class.name} #{raw_data.unpack1("H*")}>"
151
165
  end
152
166
  end
153
167
  end
154
168
 
155
- require 'bwa/messages/configuration'
156
- require 'bwa/messages/configuration_request'
157
- require 'bwa/messages/control_configuration'
158
- require 'bwa/messages/control_configuration_request'
159
- require 'bwa/messages/filter_cycles'
160
- require 'bwa/messages/ready'
161
- require 'bwa/messages/set_temperature'
162
- require 'bwa/messages/set_temperature_scale'
163
- require 'bwa/messages/set_time'
164
- require 'bwa/messages/status'
165
- require 'bwa/messages/toggle_item'
169
+ require "bwa/messages/configuration"
170
+ require "bwa/messages/configuration_request"
171
+ require "bwa/messages/control_configuration"
172
+ require "bwa/messages/control_configuration_request"
173
+ require "bwa/messages/filter_cycles"
174
+ require "bwa/messages/ready"
175
+ require "bwa/messages/set_target_temperature"
176
+ require "bwa/messages/set_temperature_scale"
177
+ require "bwa/messages/set_time"
178
+ require "bwa/messages/status"
179
+ require "bwa/messages/toggle_item"
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module BWA
2
4
  module Messages
3
5
  class Configuration < Message
4
- MESSAGE_TYPE = "\xbf\x94".force_encoding(Encoding::ASCII_8BIT)
6
+ MESSAGE_TYPE = (+"\xbf\x94").force_encoding(Encoding::ASCII_8BIT)
5
7
  MESSAGE_LENGTH = 25
6
8
 
7
9
  def inspect
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module BWA
2
4
  module Messages
3
5
  class ConfigurationRequest < Message
4
- MESSAGE_TYPE = "\xbf\x04".force_encoding(Encoding::ASCII_8BIT)
6
+ MESSAGE_TYPE = (+"\xbf\x04").force_encoding(Encoding::ASCII_8BIT)
5
7
  MESSAGE_LENGTH = 0
6
8
 
7
9
  def inspect