class EISCP::Receiver

The EISCP::Receiver class is used to communicate with one or more receivers the network. A Receiver can be instantiated automatically using discovery, or by hostname and port.

receiver = EISCP::Receiver.new # find first receiver on LAN
receiver = EISCP::Receiver.new('192.168.1.12') # default port
receiver = EISCP::Receiver.new('192.168.1.12', 60129) # non standard port

Constants

DEFAULT_TIMEOUT

Default connection timeout value in seconds

ONKYO_PORT

Default Onkyo eISCP port

Attributes

area[RW]

Receiver’s region

host[RW]

Receiver’s IP address

mac_address[RW]

Receiver’s MAC address

model[RW]

Receiver’s model string

port[RW]

Receiver’s ISCP port

socket[R]

Receiver’s connection socket

state[RW]

State object

thread[R]

Receiver’s connection thread

Public Class Methods

new(host = nil, info_hash = {}, &block) click to toggle source

Create a new EISCP::Receiver object to communicate with a receiver. If no host is given, use auto discovery and create a receiver object using the first host to respond.

# File lib/eiscp/receiver.rb, line 49
def initialize(host = nil, info_hash = {}, &block)
  # Initialize state
  #
  @state = {}
  # This defines the behavior of CommandMethods by telling it what to do
  # with the Message object that results from a CommandMethod being called.
  # All we're doing here is calling #send_recv
  #
  command_method_proc = proc { |msg| send_recv msg }
  CommandMethods.generate(&command_method_proc)

  # This proc sets the four ECN attributes and initiates a connection to the
  # receiver.
  #
  set_attrs = lambda do |hash|
    @model = hash[:model]
    @port  = hash[:port]
    @area  = hash[:area]
    @mac_address = hash[:mac_address]
    connect(&block) if block_given?
  end

  # This lambda sets the host IP after resolving it
  #
  set_host = lambda do |hostname|
    @host = Resolv.getaddress hostname
  end

  # When no host is given, the first discovered host is returned.
  #
  # When a host is given without a hash ::discover will be used to find
  # a receiver that matches.
  #
  # Else, use the given host and hash to create a new Receiver object.
  # This is how ::discover creates Receivers.
  #
  if host.nil?
    first_found = Receiver.discover[0]
    set_host.call first_found.host
    set_attrs.call first_found.ecn_hash
  elsif info_hash.empty?
    set_host.call host
    Receiver.discover.each do |receiver|
      receiver.host == @host && set_attrs.call(receiver.ecn_hash)
    end
  else
    set_host.call host
    set_attrs.call info_hash
  end
end

Public Instance Methods

connect(&block) click to toggle source

This creates a socket conection to the receiver if one doesn’t exist, and updates or sets the callback block if one is passed.

# File lib/eiscp/receiver.rb, line 118
def connect(&block)
  @socket ||= TCPSocket.new(@host, @port)
  update_thread(&block)
rescue StandardError => e
  puts e
end
disconnect() click to toggle source

Disconnect from the receiver by closing the socket and killing the connection thread.

# File lib/eiscp/receiver.rb, line 128
def disconnect
  @thread.kill
  @socket.close
end
ecn_hash() click to toggle source

Return ECN hash with model, port, area, and MAC address

# File lib/eiscp/receiver.rb, line 164
def ecn_hash
  { model: @model,
    port: @port,
    area: @area,
    mac_address: @mac_address }
end
human_readable_state() click to toggle source

This will return a human-readable represantion of the receiver’s state.

# File lib/eiscp/receiver.rb, line 173
def human_readable_state
  hash = {}
  @state.dup.each do |c, v|
    hash[Dictionary.command_to_name(c).to_s] = (Dictionary.command_value_to_value_name(c, v) || v.to_s).to_s
  end
  hash
end
recv() click to toggle source

Reads the socket and returns and EISCP::Message

# File lib/eiscp/receiver.rb, line 147
def recv
  data = String.new
  data << @socket.gets until data.match(/\r\n$/)
  Parser.parse(data)
end
send(eiscp) click to toggle source

Sends an EISCP::Message object or string on the network

# File lib/eiscp/receiver.rb, line 135
def send(eiscp)
  connect if @socket.nil? || @socket.closed?
  case eiscp
  when EISCP::Message
    @socket.puts(eiscp.to_eiscp)
  when String
    @socket.puts eiscp
  end
end
send_recv(eiscp) click to toggle source

Sends an EISCP::Message object or string on the network and returns recieved data string.

# File lib/eiscp/receiver.rb, line 155
def send_recv(eiscp)
  eiscp = Parser.parse(eiscp) if eiscp.is_a? String
  send eiscp
  sleep DEFAULT_TIMEOUT
  Parser.parse("#{eiscp.command}#{@state[eiscp.command]}")
end
update_state() click to toggle source

Runs every command that supports the ‘QSTN’ value. This is a good way to get the sate of the receiver after connecting.

# File lib/eiscp/receiver.rb, line 184
def update_state
  Thread.new do
    Dictionary.commands.each do |zone, _commands|
      Dictionary.commands[zone].each do |command, info|
        info[:values].each do |value, _|
          next unless value == 'QSTN'

          send_recv(Parser.parse("#{command}QSTN"))
        end
      end
    end
  end
end

Private Instance Methods

update_thread() { |message| ... } click to toggle source

Manages the thread and uses the same block passed to through connect.

# File lib/eiscp/receiver.rb, line 102
def update_thread
  # Kill thread if it exists
  thread && @thread.kill
  @thread = Thread.new do
    loop do
      message = recv
      @state[message.command] = message.value
      yield(message) if block_given?
    end
  end
end