class Modbus::Transaction::Client

Public Class Methods

new(conn, timeout) click to toggle source
Calls superclass method Modbus::Transaction::Base::new
# File lib/modbus/transaction/client.rb, line 14
def initialize(conn, timeout)
  super conn
  @timeout = timeout
end
recv_adu(buffer, conn) click to toggle source

Try to decode a response ADU from some recevied bytes and handle the ADU if decoding was successful.

@param buffer [String] The bytes received from the network. @param conn [Modbus::Connection::TCPClient] An EM connection object to work on. @return [true, false] True, if there where enough bytes in the buffer and decoding was successful.

# File lib/modbus/transaction/client.rb, line 26
def self.recv_adu(buffer, conn)
  adu = Modbus::TCPADU.new

  if adu.decode :response, buffer, conn
    transaction = conn.pick_pending_transaction adu.transaction_ident
    fail ClientError, "Transaction ident #{adu.transaction_ident} not found!" unless transaction
    transaction.handle_response adu
    return true
  else
    return false
  end
end

Public Instance Methods

handle_read_bits() click to toggle source
# File lib/modbus/transaction/client.rb, line 166
def handle_read_bits
  @response_adu.pdu.bit_values
end
handle_read_registers() click to toggle source
# File lib/modbus/transaction/client.rb, line 176
def handle_read_registers
  @response_adu.pdu.reg_values
end
handle_response(adu) click to toggle source

Handles a recevied ADU and calls the relevant callback. The corresponding request ADU is matched and cleaned up.

@param adu [Modbus::ADU] The ADU to handle.

# File lib/modbus/transaction/client.rb, line 149
def handle_response(adu)
  @response_adu = adu
  fail Modbus.find_exception(@response_adu.pdu.exception_code), "Request PDU: #{@request_adu.pdu.inspect}" if @response_adu.pdu.is_a? PDU::Exception

  transaction = TRANSACTIONS.find { |t| @response_adu.pdu.is_a? t[:response] }
  fail "Unknown PDU #{@response_adu.pdu.inspect}" unless transaction
  fail "Unexpected last sent PDU: #{@request_adu.pdu.inspect}" unless @request_adu.pdu.is_a? transaction[:request]

  value = send transaction[:handler]
  EM.cancel_timer @timeout_timer
  set_deferred_success @request_adu.pdu.start_addr, value

rescue => e
  set_deferred_failure "#{e.class} - #{e.message}"
end
handle_write_multiple_registers() click to toggle source
# File lib/modbus/transaction/client.rb, line 181
def handle_write_multiple_registers
  @response_adu.pdu.reg_count
end
handle_write_single_coil() click to toggle source
# File lib/modbus/transaction/client.rb, line 171
def handle_write_single_coil
  @response_adu.pdu.value
end
read_coils(start_addr, bit_count) click to toggle source

Sends a request for the modbus function 1 “read coils” asynchronusly. This method is non-blocking.

@param start_addr [Integer] The starting modbus register address to read registers from. @param bit_count [Integer] The number of input bits to read.

# File lib/modbus/transaction/client.rb, line 45
def read_coils(start_addr, bit_count)
  pdu            = PDU::ReadCoilsRequest.new
  pdu.start_addr = start_addr
  pdu.bit_count  = bit_count

  send_pdu pdu
end
read_holding_registers(start_addr, reg_count) click to toggle source

Sends a request for the modbus function “read holding registers” asynchronusly. This method is non-blocking.

@param start_addr [Integer] The starting modbus register address to read registers from. @param reg_count [Integer] The number of registers to read.

# File lib/modbus/transaction/client.rb, line 101
def read_holding_registers(start_addr, reg_count)
  pdu            = PDU::ReadHoldingRegistersRequest.new
  pdu.start_addr = start_addr
  pdu.reg_count  = reg_count

  send_pdu pdu
end
read_input_registers(start_addr, reg_count) click to toggle source

Sends a request for the modbus function 4 “read input registers” asynchronusly. This method is non-blocking.

@param start_addr [Integer] The starting modbus register address to read registers from. @param reg_count [Integer] The number of registers to read.

# File lib/modbus/transaction/client.rb, line 87
def read_input_registers(start_addr, reg_count)
  pdu            = PDU::ReadInputRegistersRequest.new
  pdu.start_addr = start_addr
  pdu.reg_count  = reg_count

  send_pdu pdu
end
read_input_status(start_addr, bit_count) click to toggle source

Sends a request for the modbus function 2 “read input status” asynchronusly. This method is non-blocking.

@param start_addr [Integer] The starting modbus register address to read registers from. @param bit_count [Integer] The number of input bits to read.

# File lib/modbus/transaction/client.rb, line 59
def read_input_status(start_addr, bit_count)
  pdu            = PDU::ReadInputStatusRequest.new
  pdu.start_addr = start_addr
  pdu.bit_count  = bit_count

  send_pdu pdu
end
send_pdu(pdu) click to toggle source

Constructs a ADU using a PDU and send it asynchronusly to the server. The created ADU is stored internally and is matched to the response when the response is available.

@param pdu [Modbus::PDU] The PDU to send. @return [Modbus::TCPADU] The sent ADU.

# File lib/modbus/transaction/client.rb, line 130
def send_pdu(pdu)
  @request_adu = TCPADU.new pdu, @conn.next_transaction_ident
  @conn.track_transaction self
  @conn.send_data @request_adu.encode

  @timeout_timer = EM.add_timer @timeout do
    @conn.pick_pending_transaction @request_adu.transaction_ident
    set_deferred_failure "Timeout #{@timeout}s expired"
  end

  self
end
transaction_ident() click to toggle source

Returns the transaction ident of this transaction which is consistent to the ident of the request PDU.

@return [Integer] The transaction ident.

# File lib/modbus/transaction/client.rb, line 190
def transaction_ident
  @request_adu.transaction_ident
end
transaction_time() click to toggle source

Returns the duration of a transaction.

@return [Float] Time time in seconds.

# File lib/modbus/transaction/client.rb, line 199
def transaction_time
  fail ClientError, 'Response ADU unknown. Can not calcluate transaction time.' unless @response_adu
  ((@response_adu.pdu.creation_time - @request_adu.pdu.creation_time) * 1000).round
end
write_multiple_registers(start_addr, reg_values) click to toggle source

Sends a request for the modbus function “write mutliple registers” asynchronusly. This method is non-blocking.

@param start_addr [Integer] The starting modbus register address to read registers from. @param reg_values [Integer] The register values to write.

# File lib/modbus/transaction/client.rb, line 115
def write_multiple_registers(start_addr, reg_values)
  pdu            = PDU::WriteMultipleRegistersRequest.new
  pdu.start_addr = start_addr
  pdu.reg_values = reg_values

  send_pdu pdu
end
write_single_coil(start_addr, value) click to toggle source

Sends a request for the modbus function 5 “write single coil” asynchronusly. This method is non-blocking.

@param start_addr [Integer] The address of the coil to write. @param value [Integer] The value to write.

# File lib/modbus/transaction/client.rb, line 73
def write_single_coil(start_addr, value)
  pdu            = PDU::WriteSingleCoilRequest.new
  pdu.start_addr = start_addr
  pdu.value      = value

  send_pdu pdu
end