ladder_drive 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 248f3ac5ff9b3eefd59641efd96088ad33f1aec8
4
- data.tar.gz: 31b342a5fb099082eece265f137739862fc6eff4
3
+ metadata.gz: 11f39560e094ef9fc61411b71fc952aebbca6051
4
+ data.tar.gz: 3bedd76a016c2f5bd8848bbf1ff8610a569c13be
5
5
  SHA512:
6
- metadata.gz: c28787587a2a95656a5ab1b7887b551dd5fec15f2cd21aaaeb5c7b1b2979a8ebee73dee7948f92f931a14378929b724bd4e67ba97ec6f2cd5f89597b18914913
7
- data.tar.gz: 12722c48c7c1d2d197233fa438ee28d59b38650eed9e8d1ce1f671b3b96c0836f3f9f47e46c2d2ad9cdc446e811b3cb526e6ae747de989522938080a715f0b41
6
+ metadata.gz: ff72c950069f9b7bd6606547b4769b1956738b4c1f450782d3e0dc8f7b98c40769e8517c8cec93fead79ae65ae2e130ef795bb409efd05e1435c8d58124a5268
7
+ data.tar.gz: c498bcbc93242716a1fb697d0ee5ec5f6b2d46943b3e870a046312c720248003217dd557aebe3fdbb500ec2b99e8186c3ab78bbb98b98c4d3e705ab37712097d
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ladder_drive (0.3.1)
5
- activesupport (>= 4.2.7)
6
- thor
4
+ ladder_drive (0.4.0)
5
+ activesupport (~> 4.2, >= 4.2.7)
6
+ thor (~> 0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -180,6 +180,27 @@ OUT M1
180
180
  <!-- [![](http://img.youtube.com/vi/qGbicGLB7Gs/0.jpg)](https://youtu.be/qGbicGLB7Gs) -->
181
181
 
182
182
 
183
+ # Accessing a device values
184
+
185
+ You can use LadderDrive as a accessing tool for the PLC device.
186
+
187
+ You can read/write device like this.
188
+
189
+ ```
190
+ require 'ladder_drive'
191
+
192
+ plc = LadderDrive::Protocol::Mitsubishi::McProtocol.new host:"192.168.0.10"
193
+
194
+ plc["M0"] = true
195
+ plc["M0"] # => true
196
+ plc["M0", 10] # => [true, false, ..., false]
197
+
198
+ plc["D0"] = 123
199
+ plc["D0"] # => 123
200
+ plc["D0", 10] = [0, 1, 2, ..., 9]
201
+ plc["D0".."D9"] => [0, 1, 2, ..., 9]
202
+ ```
203
+
183
204
  # Information related ladder_drive
184
205
 
185
206
  - [My japanese diary [ladder_drive]](http://diary.itosoft.com/?category=ladder_drive)
data/README_jp.md CHANGED
@@ -183,6 +183,26 @@ OUT M1
183
183
 
184
184
  <!-- [![](http://img.youtube.com/vi/qGbicGLB7Gs/0.jpg)](https://youtu.be/qGbicGLB7Gs) -->
185
185
 
186
+ ## PLCデバイスへのアクセスツールとしての利用
187
+
188
+ LadderDriveはPLCデバイスの読み書きツールとしての利用もできます。
189
+ 下の様にとても簡単に読み書きできます。
190
+
191
+ ```
192
+ require 'ladder_drive'
193
+
194
+ plc = LadderDrive::Protocol::Mitsubishi::McProtocol.new host:"192.168.0.10"
195
+
196
+ plc["M0"] = true
197
+ plc["M0"] # => true
198
+ plc["M0", 10] # => [true, false, ..., false]
199
+
200
+ plc["D0"] = 123
201
+ plc["D0"] # => 123
202
+ plc["D0", 10] = [0, 1, 2, ..., 9]
203
+ plc["D0".."D9"] => [0, 1, 2, ..., 9]
204
+ ```
205
+
186
206
  ## エスカレーターに関する情報
187
207
 
188
208
  - [一往確認日記 [ladder_drive]](http://diary.itosoft.com/?category=ladder_drive)
data/ladder_drive.gemspec CHANGED
@@ -14,8 +14,8 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = "https://github.com/ito-soft-design/ladder_drive"
15
15
  spec.license = "MIT"
16
16
 
17
- spec.add_dependency "thor"
18
- spec.add_runtime_dependency "activesupport", ">=4.2.7"
17
+ spec.add_runtime_dependency 'thor', '~> 0'
18
+ spec.add_runtime_dependency 'activesupport', '~> 4.2', '>= 4.2.7'
19
19
 
20
20
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
21
  spec.bindir = "exe"
@@ -104,7 +104,7 @@ module LadderDrive
104
104
  end
105
105
 
106
106
  def bit_device?
107
- SUFFIXES_FOR_BIT.include? @suffix
107
+ suffixes_for_bit.include? @suffix
108
108
  end
109
109
 
110
110
  def + value
@@ -59,7 +59,7 @@ module Keyence
59
59
  values = values.map{|v| v == 0 ? false : true}
60
60
  values.each do |v|
61
61
  device.bool = v
62
- device = device_by_name (device+1).name
62
+ device += 1
63
63
  end
64
64
  values
65
65
  end
@@ -80,7 +80,7 @@ module Keyence
80
80
  @socket.puts(packet)
81
81
  res = receive
82
82
  raise res unless /OK/i =~ res
83
- device = device_by_name (device+1).name
83
+ device += 1
84
84
  end
85
85
  end
86
86
  alias :set_bit_to_device :set_bits_to_device
@@ -144,6 +144,46 @@ module Keyence
144
144
  packet.dup.chomp
145
145
  end
146
146
 
147
+ def available_bits_range suffix=nil
148
+ case suffix
149
+ when "TM"
150
+ 1..512
151
+ when "TM"
152
+ 1..12
153
+ when "T", "TC", "TS", "C", "CC", "CS"
154
+ 1..120
155
+ when "CTH"
156
+ 1..2
157
+ when "CTC"
158
+ 1..4
159
+ when "AT"
160
+ 1..8
161
+ else
162
+ 1..1000
163
+ end
164
+ end
165
+
166
+ def available_words_range suffix=nil
167
+ case suffix
168
+ when "TM"
169
+ 1..256
170
+ when "TM"
171
+ 1..12
172
+ when "T", "TC", "TS", "C", "CC", "CS"
173
+ 1..120
174
+ 1..120
175
+ when "CTH"
176
+ 1..2
177
+ when "CTC"
178
+ 1..4
179
+ when "AT"
180
+ 1..8
181
+ else
182
+ 1..500
183
+ end
184
+ end
185
+
186
+
147
187
  private
148
188
 
149
189
  def device_class
@@ -55,13 +55,24 @@ module Mitsubishi
55
55
  end
56
56
 
57
57
  def get_bits_from_device count, device
58
+ 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
59
+
58
60
  device = device_by_name device
59
61
  packet = make_packet(body_for_get_bits_from_deivce(count, device))
60
62
  @logger.debug("> #{dump_packet packet}")
61
63
  open
62
- @socket.write(packet.pack("c*"))
64
+ @socket.write(packet.pack("C*"))
63
65
  @socket.flush
64
66
  res = receive
67
+
68
+ # error checking
69
+ end_code = res[9,2].pack("C*").unpack("v").first
70
+ unless end_code == 0
71
+ error = res[11,2].pack("C*").unpack("v").first
72
+ 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})"
73
+ end
74
+
75
+ # get results
65
76
  bits = []
66
77
  count.times do |i|
67
78
  v = res[11 + i / 2]
@@ -76,14 +87,23 @@ module Mitsubishi
76
87
  end
77
88
 
78
89
  def set_bits_to_device bits, device
90
+ 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
91
+
79
92
  device = device_by_name device
80
93
  packet = make_packet(body_for_set_bits_to_device(bits, device))
81
94
  @logger.debug("> #{dump_packet packet}")
82
95
  open
83
- @socket.write(packet.pack("c*"))
96
+ @socket.write(packet.pack("C*"))
84
97
  @socket.flush
85
98
  res = receive
86
99
  @logger.debug("set #{bits} to:#{device.name}")
100
+
101
+ # error checking
102
+ end_code = res[9,2].pack("C*").unpack("v").first
103
+ unless end_code == 0
104
+ error = res[11,2].pack("C*").unpack("v").first
105
+ 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})"
106
+ end
87
107
  end
88
108
 
89
109
 
@@ -93,30 +113,50 @@ module Mitsubishi
93
113
  end
94
114
 
95
115
  def get_words_from_device(count, device)
116
+ 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
117
+
96
118
  device = device_by_name device
97
119
  packet = make_packet(body_for_get_words_from_deivce(count, device))
98
120
  @logger.debug("> #{dump_packet packet}")
99
121
  open
100
- @socket.write(packet.pack("c*"))
122
+ @socket.write(packet.pack("C*"))
101
123
  @socket.flush
102
124
  res = receive
125
+
126
+ # error checking
127
+ end_code = res[9,2].pack("C*").unpack("v").first
128
+ unless end_code == 0
129
+ error = res[11,2].pack("C*").unpack("v").first
130
+ 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})"
131
+ end
132
+
133
+ # get result
103
134
  words = []
104
135
  res[11, 2 * count].each_slice(2) do |pair|
105
- words << pair.pack("c*").unpack("v").first
136
+ words << pair.pack("C*").unpack("v").first
106
137
  end
107
138
  @logger.debug("get from: #{device.name} => #{words}")
108
139
  words
109
140
  end
110
141
 
111
142
  def set_words_to_device words, device
143
+ 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? words.size
144
+
112
145
  device = device_by_name device
113
146
  packet = make_packet(body_for_set_words_to_device(words, device))
114
147
  @logger.debug("> #{dump_packet packet}")
115
148
  open
116
- @socket.write(packet.pack("c*"))
149
+ @socket.write(packet.pack("C*"))
117
150
  @socket.flush
118
151
  res = receive
119
152
  @logger.debug("set #{words} to: #{device.name}")
153
+
154
+ # error checking
155
+ end_code = res[9,2].pack("C*").unpack("v").first
156
+ unless end_code == 0
157
+ error = res[11,2].pack("C*").unpack("v").first
158
+ 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})"
159
+ end
120
160
  end
121
161
 
122
162
 
@@ -143,7 +183,7 @@ module Mitsubishi
143
183
  next if c.nil? || c == ""
144
184
 
145
185
  res << c.bytes.first
146
- len = res[7,2].pack("c*").unpack("v*").first if res.length >= 9
186
+ len = res[7,2].pack("C*").unpack("v*").first if res.length >= 9
147
187
  break if (len + 9 == res.length)
148
188
  end
149
189
  end
@@ -154,6 +194,14 @@ module Mitsubishi
154
194
  res
155
195
  end
156
196
 
197
+ def available_bits_range device=nil
198
+ 1..(960 * 16)
199
+ end
200
+
201
+ def available_words_range device=nil
202
+ 1..960
203
+ end
204
+
157
205
  private
158
206
 
159
207
  def make_packet body
@@ -214,11 +262,11 @@ module Mitsubishi
214
262
  end
215
263
 
216
264
  def data_for_short value
217
- [value].pack("v").unpack("c*")
265
+ [value].pack("v").unpack("C*")
218
266
  end
219
267
 
220
268
  def data_for_int value
221
- [value].pack("V").unpack("c*")
269
+ [value].pack("V").unpack("C*")
222
270
  end
223
271
 
224
272
  def dump_packet packet
@@ -46,14 +46,14 @@ module Mitsubishi
46
46
  @number = b
47
47
  else
48
48
  if a.length == 12
49
- @suffix = [a[0,2].to_i(16), a[2,2].to_i(16)].pack "c*"
49
+ @suffix = [a[0,2].to_i(16), a[2,2].to_i(16)].pack "C*"
50
50
  @suffix.strip!
51
51
  @number = a[4,8].to_i(16)
52
52
  elsif /(X|Y)(.+)/i =~ a
53
53
  @suffix = $1.upcase
54
54
  @number = $2.to_i(p_adic_number)
55
55
  else
56
- /(M|L|S|B|F|T|C|D|W|R)(.+)/i =~ a
56
+ /(M|L|S|B|F|T|C|D|W|R|ZR)(.+)/i =~ a
57
57
  @suffix = $1.upcase
58
58
  @number = $2.to_i(p_adic_number)
59
59
  end
@@ -63,7 +63,7 @@ module Mitsubishi
63
63
 
64
64
  def p_adic_number
65
65
  case @suffix
66
- when "X", "Y", "B", "W", "SB", "SW", "DX", "DY", "ZR"
66
+ when "X", "Y", "B", "W", "SB", "SW", "DX", "DY"
67
67
  16
68
68
  else
69
69
  10
@@ -24,11 +24,6 @@
24
24
  dir = File.expand_path(File.dirname(__FILE__))
25
25
  $:.unshift dir unless $:.include? dir
26
26
 
27
- module LadderDrive
28
- module Protocol
29
- end
30
- end
31
-
32
27
  module LadderDrive
33
28
  module Protocol
34
29
 
@@ -67,12 +62,12 @@ module Protocol
67
62
  def get_bit_from_device device; end
68
63
  def get_bits_from_device count, device; end
69
64
  def set_bits_to_device bits, device; end
70
- def set_bit_to_device bit, device; set_bits_to_device bit, device; end
65
+ def set_bit_to_device bit, device; set_bits_to_device [bit], device; end
71
66
 
72
67
  def get_word_from_device device; end
73
68
  def get_words_from_device(count, device); end
74
69
  def set_words_to_device words, device; end
75
- def set_word_to_device word, device; set_words_to_device word, device; end
70
+ def set_word_to_device word, device; set_words_to_device [word], device; end
76
71
 
77
72
  def device_by_name name; nil; end
78
73
 
@@ -96,6 +91,99 @@ module Protocol
96
91
  end
97
92
  end
98
93
 
94
+ def available_bits_range device=nil
95
+ -Float::INFINITY..Float::INFINITY
96
+ end
97
+
98
+ def available_words_range device=nil
99
+ -Float::INFINITY..Float::INFINITY
100
+ end
101
+
102
+ def [] *args
103
+ case args.size
104
+ when 1
105
+ # protocol["DM0"]
106
+ # protocol["DM0".."DM9"]
107
+ case args[0]
108
+ when String
109
+ self[args[0], 1].first
110
+ when Range
111
+ self[args[0].first, args[0].count]
112
+ else
113
+ raise ArgumentError.new("#{args[0]} must be String or Range.")
114
+ end
115
+ when 2
116
+ # protocol["DM0", 10]
117
+ d = device_by_name args[0]
118
+ c = args[1]
119
+ if d.bit_device?
120
+ a = []
121
+ b = available_bits_range(d).last
122
+ until c == 0
123
+ n_c = [b, c].min
124
+ a += get_bits_from_device(n_c, d)
125
+ d += n_c
126
+ c -= n_c
127
+ end
128
+ a
129
+ else
130
+ a = []
131
+ b = available_words_range(d).last
132
+ until c == 0
133
+ n_c = [b, c].min
134
+ a += get_words_from_device(n_c, d)
135
+ d += n_c
136
+ c -= n_c
137
+ end
138
+ a
139
+ end
140
+ else
141
+ raise ArgumentError.new("wrong number of arguments (given #{args.size}, expected 1 or 2)")
142
+ end
143
+ end
144
+
145
+ def []= *args
146
+ case args.size
147
+ when 2
148
+ # protocol["DM0"] = 0
149
+ # protocol["DM0".."DM9"] = [0, 1, .., 9]
150
+ v = args[1]
151
+ v = [v] unless v.is_a? Array
152
+ case args[0]
153
+ when String
154
+ self[args[0], 1] = v
155
+ when Range
156
+ self[args[0].first, args[0].count] = v
157
+ else
158
+ raise ArgumentError.new("#{args[1]} must be String or Array.")
159
+ end
160
+ when 3
161
+ # protocol["DM0", 10] = [0, 1, .., 9]
162
+ d = device_by_name args[0]
163
+ c = args[1]
164
+ values = args[2]
165
+ values = [values] unless values.is_a? Array
166
+ raise ArgumentError.new("Count #{c} is not match #{args[2].size}.") unless c == values.size
167
+ if d.bit_device?
168
+ a = []
169
+ values.each_slice(available_bits_range(d).last) do |sv|
170
+ set_bits_to_device(values, d)
171
+ d += sv.size
172
+ end
173
+ a
174
+ else
175
+ a = []
176
+ values.each_slice(available_words_range(d).last) do |sv|
177
+ set_words_to_device(values, d)
178
+ d += sv.size
179
+ end
180
+ a
181
+ end
182
+ else
183
+ raise ArgumentError.new("wrong number of arguments (given #{args.size}, expected 2 or 3)")
184
+ end
185
+ end
186
+
99
187
  end
100
188
 
101
189
  end
@@ -55,7 +55,7 @@ module LadderDrive
55
55
  def word_data
56
56
  data.each_slice(2).map do |pair|
57
57
  pair << 0 if pair.size == 1
58
- pair.pack("c*").unpack("n*")
58
+ pair.pack("C*").unpack("n*")
59
59
  end.flatten
60
60
  end
61
61
 
@@ -22,5 +22,5 @@
22
22
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
 
24
24
  module LadderDrive
25
- VERSION = "0.3.1"
25
+ VERSION = "0.4.0"
26
26
  end
@@ -152,7 +152,7 @@ module Emulator
152
152
  case d.suffix
153
153
  when "PRG"
154
154
  c.times do
155
- r << program_data[d.number * 2, 2].pack("c*").unpack("n").first
155
+ r << program_data[d.number * 2, 2].pack("C*").unpack("n").first
156
156
  d = device_by_name (d+1).name
157
157
  end
158
158
  else
@@ -169,7 +169,7 @@ module Emulator
169
169
  case d.suffix
170
170
  when "PRG"
171
171
  a[3, c].each do |v|
172
- program_data[d.number * 2, 2] = [v.to_i].pack("n").unpack("c*")
172
+ program_data[d.number * 2, 2] = [v.to_i].pack("n").unpack("C*")
173
173
  d = device_by_name (d+1).name
174
174
  end
175
175
  else
metadata CHANGED
@@ -1,33 +1,36 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ladder_drive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katsuyoshi Ito
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-05 00:00:00.000000000 Z
11
+ date: 2017-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.2'
31
34
  - - ">="
32
35
  - !ruby/object:Gem::Version
33
36
  version: 4.2.7
@@ -35,6 +38,9 @@ dependencies:
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '4.2'
38
44
  - - ">="
39
45
  - !ruby/object:Gem::Version
40
46
  version: 4.2.7