Class: BWA::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/bwa/client.rb

Constant Summary collapse

HEATING_MODES =
%I{ready rest ready_in_rest}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri) ⇒ Client

Returns a new instance of Client.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/bwa/client.rb', line 7

def initialize(uri)
  uri = URI.parse(uri)
  if uri.scheme == 'tcp'
    require 'socket'
    @io = TCPSocket.new(uri.host, uri.port || 4217)
  elsif uri.scheme == 'telnet' || uri.scheme == 'rfc2217'
    require 'net/telnet/rfc2217'
    @io = Net::Telnet::RFC2217.new("Host" => uri.host, "Port" => uri.port || 23, "baud" => 115200)
    @queue = []
  else
    require 'serialport'
    @io = SerialPort.open(uri.path, "baud" => 115200)
    @queue = []
  end
  @buffer = ""
end

Instance Attribute Details

#last_control_configurationObject (readonly)

Returns the value of attribute last_control_configuration.



5
6
7
# File 'lib/bwa/client.rb', line 5

def last_control_configuration
  @last_control_configuration
end

#last_control_configuration2Object (readonly)

Returns the value of attribute last_control_configuration2.



5
6
7
# File 'lib/bwa/client.rb', line 5

def last_control_configuration2
  @last_control_configuration2
end

#last_filter_configurationObject (readonly)

Returns the value of attribute last_filter_configuration.



5
6
7
# File 'lib/bwa/client.rb', line 5

def last_filter_configuration
  @last_filter_configuration
end

#last_statusObject (readonly)

Returns the value of attribute last_status.



5
6
7
# File 'lib/bwa/client.rb', line 5

def last_status
  @last_status
end

Instance Method Details

#drain_message_queueObject



52
53
54
# File 'lib/bwa/client.rb', line 52

def drain_message_queue
  poll while messages_pending?
end

#messages_pending?Boolean

Returns:

  • (Boolean)


48
49
50
# File 'lib/bwa/client.rb', line 48

def messages_pending?
  !!IO.select([@io], nil, nil, 0)
end

#pollObject



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/bwa/client.rb', line 24

def poll
  message = bytes_read = nil
  loop do
    message, bytes_read = Message.parse(@buffer)
   # discard how much we read
   @buffer = @buffer[bytes_read..-1] if bytes_read
    unless message
      @buffer.concat(@io.readpartial(64 * 1024))
      next
    end
    break
  end

  if message.is_a?(Messages::Ready) && (msg = @queue&.shift)
    puts "wrote #{msg.unpack('H*').first}"
    @io.write(msg)
  end
  @last_status = message.dup if message.is_a?(Messages::Status)
  @last_filter_configuration = message.dup if message.is_a?(Messages::FilterCycles)
  @last_control_configuration = message.dup if message.is_a?(Messages::ControlConfiguration)
  @last_control_configuration2 = message.dup if message.is_a?(Messages::ControlConfiguration2)
  message
end

#request_configurationObject



68
69
70
# File 'lib/bwa/client.rb', line 68

def request_configuration
  send_message("\x0a\xbf\x04")
end

#request_control_infoObject



76
77
78
# File 'lib/bwa/client.rb', line 76

def request_control_info
  send_message("\x0a\xbf\x22\x02\x00\x00")
end

#request_control_info2Object



72
73
74
# File 'lib/bwa/client.rb', line 72

def request_control_info2
  send_message("\x0a\xbf\x22\x00\x00\x01")
end

#request_filter_configurationObject



80
81
82
# File 'lib/bwa/client.rb', line 80

def request_filter_configuration
  send_message("\x0a\xbf\x22\x01\x00\x00")
end

#send_message(message) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/bwa/client.rb', line 56

def send_message(message)
  length = message.length + 2
  full_message = "#{length.chr}#{message}".force_encoding(Encoding::ASCII_8BIT)
  checksum = CRC.checksum(full_message)
  full_message = "\x7e#{full_message}#{checksum.chr}\x7e".force_encoding(Encoding::ASCII_8BIT)
  if @queue
    @queue.push(full_message)
  else
    @io.write(full_message)
  end
end

#set_blower(desired) ⇒ Object



129
130
131
132
133
134
135
136
# File 'lib/bwa/client.rb', line 129

def set_blower(desired)
  return unless last_status && last_control_configuration2
  times = (desired - last_status.blower) % (last_control_configuration2.blower + 1)
  times.times do
    toggle_blower
    sleep(0.1)
  end
end

#set_heating_mode(desired) ⇒ Object

Raises:

  • (ArgumentError)


171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/bwa/client.rb', line 171

def set_heating_mode(desired)
  raise ArgumentError, "heating_mode must be :ready or :rest" unless %I{ready rest}.include?(desired)
  return unless last_status
  times = if last_status.heating_mode == :ready && desired == :rest ||
             last_status.heating_mode == :rest && desired == :ready ||
             last_status.heating_mode == :ready_in_rest && desired == :rest
      1
    elsif last_status.heating_mode == :ready_in_rest && desired == :ready
      2
    else
      0
    end
  times.times { toggle_heating_mode }
end

#set_mister(desired) ⇒ Object



123
124
125
126
127
# File 'lib/bwa/client.rb', line 123

def set_mister(desired)
  return unless last_status
  return if last_status.mister == desired
  toggle_mister
end

#set_pump(i, desired) ⇒ Object



104
105
106
107
108
109
110
111
# File 'lib/bwa/client.rb', line 104

def set_pump(i, desired)
  return unless last_status && last_control_configuration2
  times = (desired - last_status.pumps[i - 1]) % (last_control_configuration2.pumps[i - 1] + 1)
  times.times do
    toggle_pump(i)
    sleep(0.1)
  end
end

#set_temperature(desired) ⇒ Object

high range is 80-104 for F, 26-40 for C (by 0.5) low range is 50-80 for F, 10-26 for C (by 0.5)



140
141
142
143
# File 'lib/bwa/client.rb', line 140

def set_temperature(desired)
  desired *= 2 if last_status && last_status.temperature_scale == :celsius || desired < 50
  send_message("\x0a\xbf\x20#{desired.chr}")
end

#set_temperature_range(desired) ⇒ Object



160
161
162
163
164
# File 'lib/bwa/client.rb', line 160

def set_temperature_range(desired)
  return unless last_status
  return if last_status.temperature_range == desired
  toggle_temperature_range
end

#set_temperature_scale(scale) ⇒ Object

Raises:

  • (ArgumentError)


150
151
152
153
154
# File 'lib/bwa/client.rb', line 150

def set_temperature_scale(scale)
  raise ArgumentError, "scale must be :fahrenheit or :celsius" unless %I{fahrenheit :celsius}.include?(scale)
  arg = scale == :fahrenheit ? 0 : 1
  send_message("\x0a\xbf\x27\x01".force_encoding(Encoding::ASCII_8BIT) + arg.chr)
end

#set_time(hour, minute, twenty_four_hour_time = false) ⇒ Object



145
146
147
148
# File 'lib/bwa/client.rb', line 145

def set_time(hour, minute, twenty_four_hour_time = false)
  hour |= 0x80 if twenty_four_hour_time
  send_message("\x0a\xbf\x21".force_encoding(Encoding::ASCII_8BIT) + hour.chr + minute.chr)
end

#toggle_blowerObject



100
101
102
# File 'lib/bwa/client.rb', line 100

def toggle_blower
  toggle_item(0x0c)
end

#toggle_heating_modeObject



166
167
168
# File 'lib/bwa/client.rb', line 166

def toggle_heating_mode
  toggle_item(0x51)
end

#toggle_item(item) ⇒ Object



84
85
86
# File 'lib/bwa/client.rb', line 84

def toggle_item(item)
  send_message("\x0a\xbf\x11#{item.chr}\x00")
end

#toggle_light(i) ⇒ Object



92
93
94
# File 'lib/bwa/client.rb', line 92

def toggle_light(i)
  toggle_item(i + 0x10)
end

#toggle_misterObject



96
97
98
# File 'lib/bwa/client.rb', line 96

def toggle_mister
  toggle_item(0x0e)
end

#toggle_pump(i) ⇒ Object



88
89
90
# File 'lib/bwa/client.rb', line 88

def toggle_pump(i)
  toggle_item(i + 3)
end

#toggle_temperature_rangeObject



156
157
158
# File 'lib/bwa/client.rb', line 156

def toggle_temperature_range
  toggle_item(0x50)
end