Class: PacketIO

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

Overview

PacketIO is used to wrap data in packets and send them over a serial port or some other IO

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(protocol, read, write = read, options = {}) ⇒ PacketIO

Takes two IO-Objects (uses “readchar” and “<<”) to read and write from



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
# File 'lib/serial_interface.rb', line 36

def initialize(protocol, read, write = read, options = {})
  @read, @write = read, write
  @on_receive = nil
  
  # Hashes contain SerialPackets that can be sent and received
  # 
  @sendable_packets = {}
  @receivable_packets = []

  @waiting_threads = []

  @protocol_handler = protocol.new(method(:send_callback),method(:receive_callback), options)

  # Create the receiver thread, but do not start it yet
  #
  @receiver_thread = Thread.new do 
    Thread.abort_on_exception = true
    Thread.stop
    
    loop do
      begin
        char = @read.readchar
        @protocol_handler.add_char_to_packet(char) if char
      rescue EOFError
        Thread.pass # there is currently nothing to read  
      end
    end if @read  # no need to loop, if there is nothing to read from
  end
end

Instance Attribute Details

#protocol_handlerObject

Returns the value of attribute protocol_handler.



32
33
34
# File 'lib/serial_interface.rb', line 32

def protocol_handler
  @protocol_handler
end

Instance Method Details

#add_receiver(hash = {}, &block) ⇒ Object

Add a type of packet, that should be checked for in the interface

If a packet is received



99
100
101
102
103
104
# File 'lib/serial_interface.rb', line 99

def add_receiver(hash = {}, &block)
  hash.each { |k,v|
    @receivable_packets << {:packet => v, :block => block}
  }
  self
end

#add_sender(hash = {}) ⇒ Object



88
89
90
91
92
93
# File 'lib/serial_interface.rb', line 88

def add_sender(hash = {})
  hash.each { |k,v|
    @sendable_packets[k] = v
  }
  self
end

#joinObject



136
137
138
139
# File 'lib/serial_interface.rb', line 136

def join
  @receiver_thread.join
  self
end

#on_receive(&block) ⇒ Object

The block given to this method is called with every received string



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

def on_receive(&block)
  @on_receive = block
end

#runObject

starts the receiver thread



131
132
133
134
# File 'lib/serial_interface.rb', line 131

def run
  @receiver_thread.wakeup
  self
end

#send_packet(data, *args) ⇒ Object

Data to be wrapped in a packet

there are different ways of using this method:

send_packet(sym, *data) send_packet(sym, options = {}, *data)

looks for a packet-class named sym and creates a new instance of this type
of packet
the optional hash is passed to the protocol layer

send_packet(string, options = {})

sends a raw string
the optional hash is passed to the protocol layer


121
122
123
124
125
126
127
# File 'lib/serial_interface.rb', line 121

def send_packet(data, *args)
  options = (Hash === args.first) ? options = args.shift : {}
  data = (Symbol === data) ? @sendable_packets[data].new(*args) : data
  
  @protocol_handler.send_packet(data.to_str, options)
  self
end

#wait_for_packet(num_packets = 1, timeout = 10) ⇒ Object

suspends the current thread, until num packets have been received the thread will be resumed after all callbacks were called



69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/serial_interface.rb', line 69

def wait_for_packet(num_packets = 1, timeout = 10)
  begin
    @waiting_threads << {:num => num_packets, :thread => Thread.current}
    sleep timeout
    raise Timeout::Error, "Timeout"
  rescue SerialProtocol::PacketReceived => e
  ensure
    # delete all occurrences of the current thread from the list of waiting threads,
    # as we are obviously not waiting anymore
    @waiting_threads.delete_if { |h| h[:thread] == Thread.current }
  end
end