class LadderDrive::Protocol::Mitsubishi::McProtocol
Public Class Methods
new(options={})
click to toggle source
Calls superclass method
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 30 def initialize options={} super @socket = nil @host = options[:host] || "192.168.0.10" @port = options[:port] || 5010 prepare_device_map end
Public Instance Methods
available_bits_range(device=nil)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 189 def available_bits_range device=nil 1..(960 * 16) end
available_words_range(device=nil)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 193 def available_words_range device=nil 1..960 end
close()
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 48 def close @socket.close if @socket @socket = nil end
device_by_name(name)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 154 def device_by_name name case name when String d = QDevice.new name d.valid? ? d : nil when EscDevice local_device_of name else # it may be already QDevice name end end
get_bits_from_device(count, device)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 53 def get_bits_from_device count, device 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 packet = make_packet(body_for_get_bits_from_device(count, device)) @logger.debug("> #{dump_packet packet}") open @socket.write(packet.pack("C*")) @socket.flush res = receive # error checking end_code = res[9,2].pack("C*").unpack("v").first unless end_code == 0 error = res[11,2].pack("C*").unpack("v").first raise "return end code 0x#{end_code.to_s(16)} error code 0x#{error.to_s(16)} for get_bits_from_device(#{count}, #{device.name})" end # get results bits = [] count.times do |i| v = res[11 + i / 2] if i % 2 == 0 bits << ((v >> 4) != 0) else bits << ((v & 0xf) != 0) end end @logger.debug("get #{device.name} => #{bits}") bits end
get_words_from_device(count, device)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 106 def get_words_from_device(count, device) raise ArgumentError.new("A count #{count} must be between #{available_words_range.first} and #{available_words_range.last} for #{__method__}") unless available_bits_range.include? count device = device_by_name device packet = make_packet(body_for_get_words_from_device(count, device)) @logger.debug("> #{dump_packet packet}") open @socket.write(packet.pack("C*")) @socket.flush res = receive # error checking end_code = res[9,2].pack("C*").unpack("v").first unless end_code == 0 error = res[11,2].pack("C*").unpack("v").first raise "return end code 0x#{end_code.to_s(16)} error code 0x#{error.to_s(16)} for get_words_from_device(#{count}, #{device.name})" end # get result words = [] res[11, 2 * count].each_slice(2) do |pair| words << pair.pack("C*").unpack("v").first end @logger.debug("get from: #{device.name} => #{words}") words end
open()
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 38 def open open! rescue nil end
open!()
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 44 def open! @socket ||= TCPSocket.open(@host, @port) end
receive()
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 168 def receive res = [] len = 0 begin Timeout.timeout(TIMEOUT) do loop do c = @socket.read(1) next if c.nil? || c == "" res << c.bytes.first len = res[7,2].pack("C*").unpack("v*").first if res.length >= 9 break if (len + 9 == res.length) end end rescue Timeout::Error puts "*** ERROR: TIME OUT ***" end @logger.debug("< #{dump_packet res}") res end
set_bits_to_device(bits, device)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 85 def set_bits_to_device bits, device 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? bits.size device = device_by_name device packet = make_packet(body_for_set_bits_to_device(bits, device)) @logger.debug("> #{dump_packet packet}") open @socket.write(packet.pack("C*")) @socket.flush res = receive @logger.debug("set #{bits} to:#{device.name}") # error checking end_code = res[9,2].pack("C*").unpack("v").first unless end_code == 0 error = res[11,2].pack("C*").unpack("v").first raise "return end code 0x#{end_code.to_s(16)} error code 0x#{error.to_s(16)} for set_bits_to_device(#{bits}, #{device.name})" end end
set_words_to_device(words, device)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 133 def set_words_to_device words, device raise ArgumentError.new("A count of words #{words.size} must be between #{available_words_range.first} and #{available_words_range.last} for #{__method__}") unless available_bits_range.include? words.size device = device_by_name device packet = make_packet(body_for_set_words_to_device(words, device)) @logger.debug("> #{dump_packet packet}") open @socket.write(packet.pack("C*")) @socket.flush res = receive @logger.debug("set #{words} to: #{device.name}") # error checking end_code = res[9,2].pack("C*").unpack("v").first unless end_code == 0 error = res[11,2].pack("C*").unpack("v").first raise "return end code 0x#{end_code.to_s(16)} error code 0x#{error.to_s(16)} for set_words_to_device(#{words}, #{device.name})" end end
Private Instance Methods
body_for_get_bit_from_deivce(device)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 205 def body_for_get_bit_from_deivce device body_for_get_bits_from_device 1, device end
body_for_get_bits_from_device(count, device)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 209 def body_for_get_bits_from_device count, device body_for_get_words_from_device count, device, false end
body_for_get_words_from_device(count, device, word = true)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 213 def body_for_get_words_from_device count, device, word = true body = [0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00] body[2] = 1 unless word body[4..7] = data_for_device(device) body[8..9] = data_for_short count body end
body_for_set_bits_to_device(bits, device)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 222 def body_for_set_bits_to_device bits, device body = [0x01, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00] d = device bits = [bits] unless bits.is_a? Array bits.each_slice(2) do |pair| body << (pair.first ? 0x10 : 0x00) body[-1] |= (pair.last ? 0x1 : 0x00) if pair.size == 2 d = d.next_device end body[4..7] = data_for_device(device) body[8..9] = data_for_short bits.size body end
Also aliased as: body_for_set_bit_to_device
body_for_set_words_to_device(words, device)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 237 def body_for_set_words_to_device words, device body = [0x01, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00] d = device words = [words] unless words.is_a? Array words.each do |v| body += data_for_short v d = d.next_device end body[4..7] = data_for_device(device) body[8..9] = data_for_short words.size body end
data_for_device(device)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 250 def data_for_device device a = data_for_int device.number a[3] = device.suffix_code a end
data_for_int(value)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 260 def data_for_int value [value].pack("V").unpack("C*") end
data_for_short(value)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 256 def data_for_short value [value].pack("v").unpack("C*") end
dump_packet(packet)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 264 def dump_packet packet a = [] len = packet.length bytes = packet.dup len.times do |i| a << ("0" + bytes[i].to_s(16))[-2, 2] end "[" + a.join(", ") + "]" end
local_device_of(device)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 296 def local_device_of device return device if device.is_a? QDevice d, c = @conv_dev_dict[device.suffix] return nil unless device.number < c ld = QDevice.new(d.suffix, d.number + device.number) device_by_name ld.name end
make_packet(body)
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 199 def make_packet body header = [0x50, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00] header[7..8] = data_for_short(body.length + 2) header + body end
prepare_device_map()
click to toggle source
# File lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb, line 274 def prepare_device_map @conv_dev_dict ||= begin h = {} [ ["X", "X0", 1024], ["Y", "Y0", 1024], ["M", "M0", 1024], ["C", "C0", 256], ["T", "T0", 256], ["L", "L0", 1024], ["SC", "M1024", 1024], ["D", "D0", 1024], ["H", "D1024", 1024], ["SD", "D2048", 1024], ["PRG", "D3072", 1024] # ..D4095 ].each do |s,d,c| h[s] = [QDevice.new(d), c] end h end end