Class: Cosmos::Win32SerialDriver

Inherits:
Object
  • Object
show all
Defined in:
lib/cosmos/io/win32_serial_driver.rb

Overview

Serial driver for use on Windows serial ports

Instance Method Summary collapse

Constructor Details

#initialize(port_name = 'COM1', baud_rate = 9600, parity = :NONE, stop_bits = 1, write_timeout = 10.0, read_timeout = nil, read_polling_period = 0.01, read_max_length = 1000) ⇒ Win32SerialDriver

Returns a new instance of Win32SerialDriver.

Parameters:

  • port_name (String) (defaults to: 'COM1')

    Name of the serial port

  • baud_rate (Integer) (defaults to: 9600)

    Serial port baud rate

  • parity (Symbol) (defaults to: :NONE)

    Must be one of :EVEN, :ODD or :NONE

  • stop_bits (Integer) (defaults to: 1)

    Number of stop bits

  • write_timeout (Float|nil) (defaults to: 10.0)

    Number of seconds to wait for the write to complete or nil to block

  • read_timeout (Float|nil) (defaults to: nil)

    Number of seconds to wait for the read to complete or nil to block

Raises:

  • (ArgumentError)


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/cosmos/io/win32_serial_driver.rb', line 20

def initialize(port_name = 'COM1',
               baud_rate = 9600,
               parity = :NONE,
               stop_bits = 1,
               write_timeout = 10.0,
               read_timeout = nil,
               read_polling_period = 0.01,
               read_max_length = 1000)

  # Verify Parameters
  port_name = '\\\\.\\' + port_name if port_name =~ /^COM[0-9]{2,3}$/

  raise(ArgumentError, "Invalid baud rate: #{baud_rate}") unless baud_rate.between?(Win32::BAUD_RATES[0], Win32::BAUD_RATES[-1])

  raise(ArgumentError, "Invalid parity: #{parity}") if parity and !SerialDriver::VALID_PARITY.include?(parity)
  case parity
  when SerialDriver::ODD
    parity = Win32::ODDPARITY
  when SerialDriver::EVEN
    parity = Win32::EVENPARITY
  when SerialDriver::NONE
    parity = Win32::NOPARITY
  end

  raise(ArgumentError, "Invalid stop bits: #{stop_bits}") unless [1,2].include?(stop_bits)
  if stop_bits == 1
    stop_bits = Win32::ONESTOPBIT
  else
    stop_bits = Win32::TWOSTOPBITS
  end

  @write_timeout = write_timeout
  @read_timeout = read_timeout
  @read_polling_period = read_polling_period
  @read_max_length = read_max_length

  # Open the Comm Port
  @handle = Win32.create_file(port_name,
                              Win32::GENERIC_READ | Win32::GENERIC_WRITE,
                              0,
                              Win32::NULL,
                              Win32::OPEN_EXISTING,
                              Win32::FILE_ATTRIBUTE_NORMAL)

  # Configure the Comm Port
  dcb = Win32.get_comm_state(@handle)
  dcb.write('BaudRate', baud_rate)
  dcb.write('ByteSize', 8)
  dcb.write('Parity',   parity)
  dcb.write('StopBits', stop_bits)
  Win32.set_comm_state(@handle, dcb)

  # Configure Timeouts
  Win32.set_comm_timeouts(@handle, 4294967295, 0, 0, 0, 0)
end

Instance Method Details

#closeObject

Disconnects the driver from the comm port



77
78
79
80
81
82
83
# File 'lib/cosmos/io/win32_serial_driver.rb', line 77

def close
  if @handle
    # Close the Comm Port
    Win32.close_handle(@handle)
    @handle = nil
  end
end

#closed?Boolean

Returns Whether the serial port has been closed.

Returns:

  • (Boolean)

    Whether the serial port has been closed



86
87
88
89
90
91
92
# File 'lib/cosmos/io/win32_serial_driver.rb', line 86

def closed?
  if @handle
    false
  else
    true
  end
end

#readString

Returns Binary data read from the serial port.

Returns:

  • (String)

    Binary data read from the serial port



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/cosmos/io/win32_serial_driver.rb', line 109

def read
  data = ''
  sleep_time = 0.0

  loop do
    loop do
      buffer = Win32.read_file(@handle, @read_max_length - data.length)
      data << buffer
      break if buffer.length <= 0 or data.length >= @read_max_length
    end
    break if data.length > 0
    if @read_timeout and sleep_time >= @read_timeout
      raise Timeout::Error, "Read Timeout"
    end
    sleep(@read_polling_period)
    sleep_time += @read_polling_period
  end

  data
end

#read_nonblockString

Returns Binary data read from the serial port.

Returns:

  • (String)

    Binary data read from the serial port



131
132
133
134
135
136
137
138
139
140
141
# File 'lib/cosmos/io/win32_serial_driver.rb', line 131

def read_nonblock
  data = ''

  loop do
    buffer = Win32.read_file(@handle, @read_max_length - data.length)
    data << buffer
    break if buffer.length <= 0 or data.length >= @read_max_length
  end

  data
end

#write(data) ⇒ Object

Parameters:

  • data (String)

    Binary data to write to the serial port



95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/cosmos/io/win32_serial_driver.rb', line 95

def write(data)
  # Write the data
  time = Time.now
  bytes_to_write = data.length
  while (bytes_to_write > 0)
    bytes_written = Win32.write_file(@handle, data, data.length)
    raise "Error writing to comm port" if bytes_written <= 0
    bytes_to_write -= bytes_written
    data = data[bytes_written..-1]
    raise Timeout::Error, "Write Timeout" if @write_timeout and (Time.now - time > @write_timeout) and bytes_to_write > 0
  end
end