Class: LadderDrive::Protocol::Mitsubishi::McProtocol

Inherits:
Protocol
  • Object
show all
Defined in:
lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb

Constant Summary

Constants inherited from Protocol

Protocol::TIMEOUT

Instance Attribute Summary

Attributes inherited from Protocol

#host, #port

Instance Method Summary collapse

Methods inherited from Protocol

#[], #[]=, #destination_ipv4, #get_bit_from_device, #get_from_devices, #get_word_from_device, #log_level, #log_level=, #self_ipv4, #set_bit_to_device, #set_to_devices, #set_word_to_device

Constructor Details

#initialize(options = {}) ⇒ McProtocol

Returns a new instance of McProtocol.



30
31
32
33
34
35
36
# 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

Instance Method Details

#available_bits_range(device = nil) ⇒ Object



189
190
191
# 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) ⇒ Object



193
194
195
# File 'lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb', line 193

def available_words_range device=nil
  1..960
end

#closeObject



48
49
50
51
# File 'lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb', line 48

def close
  @socket.close if @socket
  @socket = nil
end

#device_by_name(name) ⇒ Object



154
155
156
157
158
159
160
161
162
163
164
165
# 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) ⇒ Object

Raises:

  • (ArgumentError)


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# 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) ⇒ Object

Raises:

  • (ArgumentError)


106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# 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

#openObject



38
39
40
41
42
# File 'lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb', line 38

def open
  open!
rescue
  nil
end

#open!Object



44
45
46
# File 'lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb', line 44

def open!
  @socket ||= TCPSocket.open(@host, @port)
end

#receiveObject



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# 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) ⇒ Object

Raises:

  • (ArgumentError)


85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# 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) ⇒ Object

Raises:

  • (ArgumentError)


133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# 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