class SocketSwitcher::Port
Attributes
debug[RW]
timeout[RW]
Public Class Methods
new(specifier, debug: false, timeout: 2_000, attempts: 3)
click to toggle source
# File lib/socket_switcher/port.rb, line 5 def initialize(specifier, debug: false, timeout: 2_000, attempts: 3) @serial_port = SerialPort.new( specifier, "baud" => 9600, "data_bits" => 8, "stop_bits" => 1, "parity" => 0 ) @debug = debug @timeout = timeout @attempts = attempts @devices = {} @mutex = Mutex.new rescue => e raise SocketSwitcher::CommunicationError.wrap(nil, e) end
Public Instance Methods
device(number)
click to toggle source
# File lib/socket_switcher/port.rb, line 47 def device(number) @devices[number] ||= SocketSwitcher::Device.new(self, number) end
devices(range = nil)
click to toggle source
# File lib/socket_switcher/port.rb, line 38 def devices(range = nil) if range devices.select { |d| range.member?(d.number) } else ready? @devices.values end end
ready?()
click to toggle source
# File lib/socket_switcher/port.rb, line 26 def ready? request do |response| if response =~ /^RDY (\d+) (\d+)/ # initalize all devices ($1.to_i..$2.to_i).each { |i| device(i) } return true else try_again or return false end end end
Private Instance Methods
debug_output(message)
click to toggle source
# File lib/socket_switcher/port.rb, line 53 def debug_output(message) if debug STDERR.puts message end end
request(device = nil, state = nil, &block)
click to toggle source
# File lib/socket_switcher/port.rb, line 105 def request(device = nil, state = nil, &block) synchronize do begin @attempt = 1 loop do set_timeout catch :again do query = '' device && state and query << "#{device.number} #{state}" query << "\r\n" debug_output "<< #{query.inspect}" @serial_port.print(query) unless response = @serial_port.gets try_again SocketSwitcher::TryAgainError.for_device( device, "timeout after #@attempt attempts" ) end debug_output ">> #{response.inspect}" block[response] end end rescue => e unless SocketSwitcher::SocketSwitcherError === e e = SocketSwitcher::CommunicationError.wrap(device, e) end raise e end end end
set_state(device, state)
click to toggle source
# File lib/socket_switcher/port.rb, line 59 def set_state(device, state) request(device, state) do |response| case response when /^ACK/ return true when /^RDY/ try_again SocketSwitcher::TryAgainError.for_device( device, "not ready after #@attempt attempts" ) when /^NAK device/ raise SocketSwitcher::InvalidResponse.for_device( device, "invalid device number: #{device.number}") when /^NAK state/ raise SocketSwitcher::InvalidResponse.for_device( device, "invalid state number: #{state}") else try_again SocketSwitcher::TryAgainError.for_device( device, "unexpected response #{response.inspect} after #@attempt attempts") end end end
set_timeout()
click to toggle source
# File lib/socket_switcher/port.rb, line 97 def set_timeout @serial_port.read_timeout = @timeout begin @serial_port.write_timeout = @timeout rescue NotImplementedError end end
synchronize(&block)
click to toggle source
# File lib/socket_switcher/port.rb, line 81 def synchronize(&block) @mutex.synchronize(&block) end
try_again(exception = nil)
click to toggle source
# File lib/socket_switcher/port.rb, line 85 def try_again(exception = nil) if @attempt < @attempts @attempt += 1 sleep @timeout.to_f / 1000 throw :again elsif exception raise exception else return false end end