class LadderDrive::Protocol::Omron::FinsTcpProtocol
Constants
- ETHERNET_CP1E
- ETHERNET_CP1H
- ETHERNET_CP1L
- ETHERNET_ETN21
Available ethernet module.
- IOFINS_DESTINATION_NODE_FROM_IP
- IOFINS_SOURCE_AUTO_NODE
- TIMEOUT
Attributes
destination_network[RW]
destination_node[RW]
destination_unit[RW]
ethernet_module[RW]
gateway_count[RW]
source_network[RW]
source_node[RW]
source_unit[RW]
tcp_error_code[RW]
Public Class Methods
new(options={})
click to toggle source
Calls superclass method
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 53 def initialize options={} super @socket = nil @host = options[:host] || "192.168.250.1" @port = options[:port] || 9600 @gateway_count = 3 @destination_network = 0 @destination_node = 0 @destination_unit = 0 @source_network = 0 @source_node = IOFINS_SOURCE_AUTO_NODE @source_unit = 0 @ethernet_module = ETHERNET_ETN21 @tcp_error_code = 0 prepare_device_map end
Public Instance Methods
available_bits_range(device=nil)
click to toggle source
max length:
CS1W-ETN21, CJ1W-ETN21 : 2012 CP1W-CIF41 option board : 540 (1004 if cpu is CP1L/H)
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 236 def available_bits_range device=nil case ethernet_module when ETHERNET_ETN21 1..(2012 - 8) when ETHERNET_CP1E 1..(540 - 8) when ETHERNET_CP1L, ETHERNET_CP1H 1..(1004 - 8) else 0..0 end end
available_words_range(device=nil)
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 249 def available_words_range device=nil case ethernet_module when ETHERNET_ETN21 1..((2012 - 8) / 2) when ETHERNET_CP1E 1..((540 - 8) / 2) when ETHERNET_CP1L, ETHERNET_CP1H 1..((1004 - 8) / 2) else 0..0 end end
close()
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 90 def close @socket.close if @socket @socket = nil end
create_fins_frame(packet)
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 105 def create_fins_frame packet packet = packet.flatten header = [ "FINS".bytes.to_a, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0].flatten header[4, 4] = int_to_a(packet.length + 8, 4) header + packet end
create_query_node()
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 99 def create_query_node header = [ "FINS".bytes.to_a, 0, 0, 0, 0xc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0].flatten header[19] = source_node == IOFINS_SOURCE_AUTO_NODE ? 0 : source_node header end
device_by_name(name)
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 262 def device_by_name name case name when String d = OmronDevice.new name d.valid? ? d : nil when EscDevice local_device_of name else # it may be already OmronDevice name end end
get_bits_from_device(count, device)
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 112 def get_bits_from_device(count, device) open raise ArgumentError.new("A count #{count} must be between #{available_bits_range.first} and #{available_bits_range.last} for #{__method__}") unless available_bits_range.include? count device = device_by_name device raise ArgumentError.new("#{device.name} is not bit device!") unless device.bit_device? command = [1, 1] command << device_to_a(device) command << int_to_a(count, 2) send_packet create_fins_frame(fins_header + command) res = receive count.times.inject([]) do |a, i| a << (res[16 + 10 + 4 + i] == 0 ? false : true) a end end
get_words_from_device(count, device)
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 132 def get_words_from_device(count, device) open raise ArgumentError.new("A count #{count} must be between #{available_words_range.first} and #{available_words_range.last} for #{__method__}") unless available_words_range.include? count device = device_by_name device device = device.channel_device command = [1, 1] command << device_to_a(device) command << int_to_a(count, 2) send_packet create_fins_frame(fins_header + command) res = receive count.times.inject([]) do |a, i| a << to_int(res[16 + 10 + 4 + i * 2, 2]) a end end
open()
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 72 def open open! rescue =>e p e nil end
open!()
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 79 def open! if @socket.nil? @socket = TCPSocket.open(@host, @port) if @socket source_node = IOFINS_SOURCE_AUTO_NODE query_node end end @socket end
query_node()
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 189 def query_node send_packet create_query_node res = receive self.source_node = res[19] end
receive()
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 202 def receive res = [] len = 0 begin Timeout.timeout(TIMEOUT) do loop do c = @socket.getc next if c.nil? || c == "" res << c.bytes.first next if res.length < 8 len = to_int(res[4, 4]) next if res.length < 8 + len tcp_command = to_int(res[8, 4]) case tcp_command when 3 # ERROR raise "Invalidate tcp header: #{res}" end break end end raise "Response error code: #{res[15]}" unless res[15] == 0 res end @logger.debug("< #{dump_packet res}") res end
send_packet(packet)
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 196 def send_packet packet @socket.write(packet.flatten.pack("c*")) @socket.flush @logger.debug("> #{dump_packet packet}") end
set_bits_to_device(bits, device)
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 151 def set_bits_to_device(bits, device) open count = bits.size raise ArgumentError.new("A count #{count} must be between #{available_bits_range.first} and #{available_bits_range.last} for #{__method__}") unless available_bits_range.include? count device = device_by_name device raise ArgumentError.new("#{device.name} is not bit device!") unless device.bit_device? command = [1, 2] command << device_to_a(device) command << int_to_a(count, 2) bits.each do |b| command << (b ? 1 : 0) end send_packet create_fins_frame(fins_header + command) res = receive end
set_words_to_device(words, device)
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 170 def set_words_to_device(words, device) open count = words.size raise ArgumentError.new("A count #{count} must be between #{available_words_range.first} and #{available_words_range.last} for #{__method__}") unless available_words_range.include? count device = device_by_name device device = device.channel_device command = [1, 2] command << device_to_a(device) command << int_to_a(count, 2) words.each do |w| command << int_to_a(w, 2) end send_packet create_fins_frame(fins_header + command) res = receive end
tcp_error?()
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 95 def tcp_error? tcp_error_code != 0 end
Private Instance Methods
device_code_of(device)
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 309 def device_code_of device @@bit_codes ||= { nil => 0x30, "" => 0x30, "W" => 0x31, "H" => 0x32, "A" => 0x33, "T" => 0x09, "C" => 0x09, "D" => 0x02, "E" => 0x0a, "TK" => 0x06 } @@word_codes ||= { nil => 0xB0, "" => 0xB0, "W" => 0xB1, "H" => 0xB2, "A" => 0xB3, "TIM" => 0x89, "CNT" => 0x89, "D" => 0x82, "E" => 0x98, "DR" => 0xbc } if device.bit_device? @@bit_codes[device.suffix] else @@word_codes[device.suffix] end end
device_to_a(device)
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 319 def device_to_a device a = [] a << device_code_of(device) a << int_to_a(device.channel, 2) a << (device.bit_device? ? (device.bit || 0) : 0) a.flatten end
dump_packet(packet)
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 368 def dump_packet packet a = packet.map{|e| e.to_s(16).rjust(2, '0') } "[#{a.join(', ')}]" end
fins_header()
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 277 def fins_header buf = [ 0x80, # ICF 0x00, # RSV 0x02, # GCT 0x00, # DNA 0x01, # DA1 0x00, # DA2 0x00, # SNA 0x01, # SA1 0x00, # SA2 0x00, # SID ] buf[2] = gateway_count - 1 buf[3] = destination_network if destination_node == IOFINS_DESTINATION_NODE_FROM_IP buf[4] = destination_ipv4.split(".").last.to_i else buf[4] = destination_node end buf[7] = source_node buf[8] = source_unit buf end
fins_tcp_cmnd_header()
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 303 def fins_tcp_cmnd_header header = [ "FINS".bytes.to_a, 0, 0, 0, 0xc, 0, 0, 0, 2, 0, 0, 0, 0].flatten header[19] = source_node == IOFINS_SOURCE_AUTO_NODE ? 0 : source_node header end
int_to_a(value, size)
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 351 def int_to_a value, size a = [] (size - 1).downto 0 do |i| a << ((value >> (i * 8)) & 0xff) end a end
prepare_device_map()
click to toggle source
FIXME: It's dummy currently.
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 329 def prepare_device_map @conv_dev_dict ||= begin h = {} [ ["X", "0.0", 1024], ["Y", "400.0", 1024], ["M", "M0.0", 1024], ["C", "C0", 256], ["T", "T0", 256], ["L", "H0.0", 1024], ["SC", "M400.0", 1024], ["D", "D0", 1024], ["H", "D1024", 1024], ["SD", "D2048", 1024], ["PRG", "D3072", 1024] # ..D4095 ].each do |s,d,c| h[s] = [OmronDevice.new(d), c] end h end end
to_int(a)
click to toggle source
# File lib/ladder_drive/protocol/omron/fins_tcp_protocol.rb, line 359 def to_int a v = 0 a.each do |e| v <<= 8 v += e end v end