class O3D3XX::PCIC

Public Class Methods

new() click to toggle source
# File lib/o3d3xx/pcic.rb, line 58
def initialize()
  @remote = nil
  @protocol = 3
  @logger = Logger.new(STDOUT)
  @logger.level = Logger::WARN
end

Public Instance Methods

async_result(state=false) click to toggle source
# File lib/o3d3xx/pcic.rb, line 154
def async_result(state=false)
  data = "p%d" % [ state ? 1 : 0 ]
  res = true
  transfer(data)
  res
end
async_trigger() click to toggle source
# File lib/o3d3xx/pcic.rb, line 142
def async_trigger()
  return transfer("t")
end
connect(host="192.168.0.69",port="50010") click to toggle source
# File lib/o3d3xx/pcic.rb, line 64
def connect(host="192.168.0.69",port="50010")
  unless @remote == nil
    disconnect()
  end
  @remote = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
  @protocol = 3
  begin
    timeout(3) do
      @remote.connect(Socket.pack_sockaddr_in(port, host))
    end
  rescue
    @logger.fatal("Unable to connect to tcp://#{host}:#{port}")
    @remote = nil
    return false
  end
  #@protocol = detect_protocol()
  #set_version(3)
end
detect_protocol() click to toggle source
# File lib/o3d3xx/pcic.rb, line 86
def detect_protocol()
  proto = nil
  begin
    result = nil
    @logger.debug("detect_protocol ")
    begin
      timeout(11) do
        send_v3("V?")
        result = @remote.recvfrom(20)
        @logger.debug("Received: #{result} ")
      end
    rescue Timeout::Error => e
      @logger.fatal("Timeout while receiving data occurred: #{e.message}")
      return
    end
    test = result.join()
    proto = nil
    proto = 1 if test =~ /(\?)|(\d{2} \d{2} \d{2})\r\n/
    proto = 2 if test =~ /\d{4}(\?)|(\d{2} \d{2} \d{2})\r\n/
    proto = 3 if test =~ /\d{4}L\d{9}\r\n\d{4}/
    proto = 4 if test =~ /L\d{9}\r\n(\?)|(\d{2} \d{2} \d{2})\r\n/
    # If the device is in continuous mode and asynchronous messages are enabled
    # we have to pull the complete frame out of the socket. Otherwise every consecutive
    # PCIC call will fail due to the fact that we start in the middle of a frame.
    if(proto == 3 )
      ticket,length = test.match(/(\d{4})L(\d{9})\r\n/i).captures
      timeout(5) do
        # get the rest of the response
        trailer = @remote.read(length.to_i-4)
      end
      # recv_v3 handles asynchronous messages so let it handle them.
      dum = recv_v3() if '0000' == ticket
    end
    raise 'Unable to detect PCIC protocol' if proto == nil
  rescue Exception => e
    puts e.message
    puts e.backtrace.inspect
    raise('Timeout while detecting version')
    proto = nil
  end
  proto
end
device_info() click to toggle source
# File lib/o3d3xx/pcic.rb, line 139
def device_info()
  transfer("G?")
end
disconnect() click to toggle source
# File lib/o3d3xx/pcic.rb, line 82
def disconnect()
  @remote.close()
  @remote = nil
end
escape_pcic_string(data) click to toggle source
# File lib/o3d3xx/pcic.rb, line 228
def escape_pcic_string(data)
  result = ""
  result = data.gsub("\n","\\\\n").gsub("\r","\\\\r") unless data == nil
end
get_lastimage(img = 3) click to toggle source
# File lib/o3d3xx/pcic.rb, line 149
def get_lastimage(img = 3)
  transfer("I%02d?"%img)
end
help() click to toggle source
# File lib/o3d3xx/pcic.rb, line 136
def help()
  transfer("H?")
end
recv_v3() click to toggle source
# File lib/o3d3xx/pcic.rb, line 186
def recv_v3()
  data = nil
  async = false
  trailer = nil
  # The V3 response shall look like this
  # <4 Byte ticket >L<9 Byte Length in dec>\r\n<4 Byte ticket ><Response>\r\n
  # receive <ticket>L<length>\r\n to check if we in sync and how much
  # data we have to receive in the next step
  timeout(5) do
    data = @remote.read(16)
  end
  @logger.info("Header   : %{res}" % {:res => escape_pcic_string(data)})
  begin
    ticket,length = data.match(/(\d{4})L(\d{9})\r\n/i).captures
  rescue
    @logger.fatal(">>> rescue: #{data} <<<")
  end
  size = length.to_i
  @logger.info("Length   : %d " % size )
  if ticket == "0000"
    @logger.info('ASYNC reply Caught !!!!')
    async = true
  else
    async = false
  end
  timeout(5) do
    trailer = @remote.read(size)
  end
  if size < 80 and trailer.length < 80
    @logger.debug("Trailer  : %{res} <<<<" % {:res => escape_pcic_string(trailer)})
  else
    escaped = escape_pcic_string(trailer)
    @logger.debug("Trailer  : %{start} [...] %{stop}" % {:start => escaped[0..20], :stop => escaped[-20..-1]})
  end
  ticket_trailer = trailer[0..3]
  unless ticket_trailer == ticket
    raise "Ticket mismatch. Header ticket: #{ticket} trailer ticket: #{ticket_trailer}"
  end
  # remove ticket and trailing \r\n
  return async,ticket,trailer[4..-3]
end
send_v3(data) click to toggle source
# File lib/o3d3xx/pcic.rb, line 166
def send_v3(data)
  ticket = "%04d" % [1000+rand(8999)]
  length = "%09d" % [data.bytesize+6]
  sendbuf = "#{ticket}L#{length}\r\n#{ticket}#{data}\r\n"
  @logger.info("Request (#{@protocol}) : %{sendbuf}" % {:sendbuf => escape_pcic_string(sendbuf)})
  timeout(5) do
    @remote.send(sendbuf,0)
  end
end
set_version(version=3) click to toggle source
# File lib/o3d3xx/pcic.rb, line 128
def set_version(version=3)
  res = transfer("v%02d"%version)
  @protocol = version
  res
end
sync_trigger() click to toggle source
# File lib/o3d3xx/pcic.rb, line 145
def sync_trigger()
  transfer("T?")
end
transfer(data) click to toggle source
# File lib/o3d3xx/pcic.rb, line 160
def transfer(data)
  raise 'Protocol #{@protocol} currently not supported' if @protocol == 1
  raise 'Protocol #{@protocol} currently not supported' if @protocol == 2
  return transfer_v3(data) if @protocol == 3
  raise 'Protocol #{@protocol} currently not supported' if @protocol == 4
end
transfer_v3(data,omit_async=true) click to toggle source
# File lib/o3d3xx/pcic.rb, line 175
def transfer_v3(data,omit_async=true)
  send_v3(data)
  continue = true
  response = nil
  begin
    async,ticket,response = recv_v3()
    continue = false; continue = true if async and omit_async
  end while continue
  return response
end
version() click to toggle source
# File lib/o3d3xx/pcic.rb, line 133
def version()
  return transfer("V?")
end