rmodbus-ccutrer 2.0.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.md +14 -7
  3. data/README.md +8 -8
  4. data/examples/perfomance_rtu.rb +55 -56
  5. data/examples/perfomance_rtu_via_tcp.rb +54 -55
  6. data/examples/perfomance_tcp.rb +54 -55
  7. data/examples/simple_xpca_gateway.rb +85 -0
  8. data/examples/use_rtu_via_tcp_modbus.rb +14 -11
  9. data/examples/use_tcp_modbus.rb +14 -11
  10. data/lib/rmodbus/client/slave.rb +58 -70
  11. data/lib/rmodbus/client.rb +13 -10
  12. data/lib/rmodbus/debug.rb +10 -6
  13. data/lib/rmodbus/errors.rb +26 -2
  14. data/lib/rmodbus/ext.rb +72 -51
  15. data/lib/rmodbus/options.rb +4 -1
  16. data/lib/rmodbus/proxy.rb +14 -9
  17. data/lib/rmodbus/rtu.rb +38 -32
  18. data/lib/rmodbus/rtu_client.rb +5 -2
  19. data/lib/rmodbus/rtu_server.rb +9 -7
  20. data/lib/rmodbus/rtu_slave.rb +6 -2
  21. data/lib/rmodbus/rtu_via_tcp_server.rb +7 -5
  22. data/lib/rmodbus/server/slave.rb +4 -2
  23. data/lib/rmodbus/server.rb +97 -73
  24. data/lib/rmodbus/sp.rb +10 -12
  25. data/lib/rmodbus/tcp.rb +5 -2
  26. data/lib/rmodbus/tcp_client.rb +3 -0
  27. data/lib/rmodbus/tcp_server.rb +28 -26
  28. data/lib/rmodbus/tcp_slave.rb +17 -16
  29. data/lib/rmodbus/version.rb +3 -1
  30. data/lib/rmodbus.rb +20 -18
  31. metadata +50 -49
  32. data/Rakefile +0 -29
  33. data/examples/simple-xpca-gateway.rb +0 -84
  34. data/spec/client_spec.rb +0 -88
  35. data/spec/exception_spec.rb +0 -120
  36. data/spec/ext_spec.rb +0 -52
  37. data/spec/logging_spec.rb +0 -89
  38. data/spec/proxy_spec.rb +0 -74
  39. data/spec/read_rtu_response_spec.rb +0 -92
  40. data/spec/response_mismach_spec.rb +0 -163
  41. data/spec/rtu_client_spec.rb +0 -86
  42. data/spec/rtu_server_spec.rb +0 -31
  43. data/spec/rtu_via_tcp_client_spec.rb +0 -76
  44. data/spec/rtu_via_tcp_server_spec.rb +0 -89
  45. data/spec/slave_spec.rb +0 -55
  46. data/spec/spec_helper.rb +0 -54
  47. data/spec/tcp_client_spec.rb +0 -88
  48. data/spec/tcp_server_spec.rb +0 -158
data/lib/rmodbus/rtu.rb CHANGED
@@ -1,5 +1,7 @@
1
- require 'digest/crc16_modbus'
2
- require 'io/wait'
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/crc16_modbus"
4
+ require "io/wait"
3
5
 
4
6
  module ModBus
5
7
  module RTU
@@ -7,26 +9,25 @@ module ModBus
7
9
 
8
10
  # We have to read specific amounts of numbers of bytes from the network depending on the function code and content
9
11
  def read_rtu_response(io)
10
- # Read the slave_id and function code
12
+ # Read the slave_id and function code
11
13
  msg = read(io, 2)
12
- log logging_bytes(msg)
13
14
 
14
15
  function_code = msg.getbyte(1)
15
16
  case function_code
16
- when 1,2,3,4 then
17
- # read the third byte to find out how much more
18
- # we need to read + CRC
19
- msg += read(io, 1)
20
- msg += read(io, msg.getbyte(2)+2)
21
- when 5,6,15,16 then
22
- # We just read in an additional 6 bytes
23
- msg += read(io, 6)
24
- when 22 then
25
- msg += read(io, 8)
26
- when 0x80..0xff then
27
- msg += read(io, 3)
28
- else
29
- raise ModBus::Errors::IllegalFunction, "Illegal function: #{function_code}"
17
+ when 1, 2, 3, 4
18
+ # read the third byte to find out how much more
19
+ # we need to read + CRC
20
+ msg += read(io, 1)
21
+ msg + read(io, msg.getbyte(2) + 2)
22
+ when 5, 6, 15, 16
23
+ # We just read in an additional 6 bytes
24
+ msg + read(io, 6)
25
+ when 22
26
+ msg + read(io, 8)
27
+ when 0x80..0xff
28
+ msg + read(io, 3)
29
+ else
30
+ raise ModBus::Errors::IllegalFunction, "Illegal function: #{function_code}"
30
31
  end
31
32
  end
32
33
 
@@ -40,38 +41,43 @@ module ModBus
40
41
  end
41
42
 
42
43
  def read(io, len)
43
- result = ""
44
+ result = +""
44
45
  loop do
45
46
  this_iter = io.read(len - result.length)
46
47
  result.concat(this_iter) if this_iter
47
48
  return result if result.length == len
49
+
48
50
  io.wait_readable
49
51
  end
50
52
  end
51
53
 
52
54
  def read_rtu_request(io)
53
- # Every message is a minimum of 4 bytes (slave id, function code, crc16)
54
- msg = read(io, 4)
55
+ # Every message is a minimum of 4 bytes (slave id, function code, crc16)
56
+ msg = read(io, 4)
55
57
 
56
- # If msg is nil, then our client never sent us anything and it's time to disconnect
57
- return if msg.nil?
58
+ # If msg is nil, then our client never sent us anything and it's time to disconnect
59
+ return if msg.nil?
58
60
 
59
61
  loop do
60
62
  offset = 0
61
- crc = msg[-2..-1].unpack("S<").first
63
+ crc = msg[-2..].unpack1("S<")
62
64
 
63
65
  # scan the bytestream for a valid CRC
64
66
  loop do
65
67
  break if offset >= msg.length - 3
68
+
66
69
  calculated_crc = Digest::CRC16Modbus.checksum(msg[offset..-3])
67
70
  if crc == calculated_crc
68
71
  is_response = (msg.getbyte(offset + 1) & 0x80 == 0x80) ||
69
- (msg.getbyte(offset) == @last_req_uid &&
70
- msg.getbyte(offset + 1) == @last_req_func &&
71
- @last_req_timestamp && Time.now.to_f - @last_req_timestamp < 5)
72
+ (msg.getbyte(offset) == @last_req_uid &&
73
+ msg.getbyte(offset + 1) == @last_req_func &&
74
+ @last_req_timestamp && Time.now.to_f - @last_req_timestamp < 5)
72
75
 
73
- params = is_response ? parse_response(msg.getbyte(offset + 1), msg[(offset + 1)..-3]) :
74
- parse_request(msg.getbyte(offset + 1), msg[(offset + 1)..-3])
76
+ params = if is_response
77
+ parse_response(msg.getbyte(offset + 1), msg[(offset + 1)..-3])
78
+ else
79
+ parse_request(msg.getbyte(offset + 1), msg[(offset + 1)..-3])
80
+ end
75
81
 
76
82
  unless params.nil?
77
83
  if is_response
@@ -82,7 +88,7 @@ module ModBus
82
88
  @last_req_timestamp = Time.now.to_f
83
89
  end
84
90
  log "Server RX discarding #{offset} bytes: #{logging_bytes(msg[0...offset])}" if offset != 0
85
- log "Server RX (#{msg.size - offset} bytes): #{logging_bytes(msg[offset..-1])}"
91
+ log "Server RX (#{msg.size - offset} bytes): #{logging_bytes(msg[offset..])}"
86
92
  return [msg.getbyte(offset), msg.getbyte(offset + 1), params, msg[offset + 1..-3], is_response]
87
93
  end
88
94
  end
@@ -92,9 +98,9 @@ module ModBus
92
98
  msg.concat(read(io, 1))
93
99
  # maximum message size is 256, so that's as far as we have to
94
100
  # be able to see at once
95
- msg = msg[1..-1] if msg.length > 256
101
+ msg = msg[1..] if msg.length > 256
96
102
  end
97
- end
103
+ end
98
104
 
99
105
  def serve(io)
100
106
  loop do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ModBus
2
4
  # RTU client implementation
3
5
  # @example
@@ -23,15 +25,16 @@ module ModBus
23
25
  include TCP
24
26
 
25
27
  protected
28
+
26
29
  # Open serial port
27
30
  def open_connection(port_or_ipaddr, arg = nil, opts = {})
28
31
  if port_or_ipaddr.is_a?(IO) || port_or_ipaddr.respond_to?(:read)
29
32
  port_or_ipaddr
30
- elsif File.exist?(port_or_ipaddr) || port_or_ipaddr.start_with?('/dev') || port_or_ipaddr.start_with?('COM')
33
+ elsif File.exist?(port_or_ipaddr) || port_or_ipaddr.start_with?("/dev") || port_or_ipaddr.start_with?("COM")
31
34
  arg ||= 9600
32
35
  open_serial_port(port_or_ipaddr, arg, opts)
33
36
  else
34
- arg ||= 10002
37
+ arg ||= 10_002
35
38
  open_tcp_connection(port_or_ipaddr, arg, opts)
36
39
  end
37
40
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ModBus
2
4
  # RTU server implementation
3
5
  # @example
@@ -7,7 +9,7 @@ module ModBus
7
9
  # slave.discrete_inputs = [1,1,0,0]
8
10
  # slave.holding_registers = [1,2,3,4]
9
11
  # slave.input_registers = [1,2,3,4]
10
- # srv.debug = true
12
+ # srv.logger = Logger.new($stdout)
11
13
  # srv.start
12
14
  class RTUServer
13
15
  include Debug
@@ -18,13 +20,13 @@ module ModBus
18
20
  # Init RTU server
19
21
  # @param [Integer] uid slave device
20
22
  # @see SP#open_serial_port
21
- def initialize(port, baud=9600, opts = {})
23
+ def initialize(port, baud = 9600, opts = {})
22
24
  Thread.abort_on_exception = true
23
- if port.is_a?(IO) || port.respond_to?(:read)
24
- @sp = port
25
- else
26
- @sp = open_serial_port(port, baud, opts)
27
- end
25
+ @sp = if port.is_a?(IO) || port.respond_to?(:read)
26
+ port
27
+ else
28
+ open_serial_port(port, baud, opts)
29
+ end
28
30
  end
29
31
 
30
32
  # Start server
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ModBus
2
4
  # RTU slave implementation
3
5
  # @example
@@ -14,6 +16,7 @@ module ModBus
14
16
  include RTU
15
17
 
16
18
  private
19
+
17
20
  # overide method for RTU implamentaion
18
21
  # @see Slave#query
19
22
  def send_pdu(pdu)
@@ -34,13 +37,14 @@ module ModBus
34
37
  log "Rx (#{msg.size} bytes): " + logging_bytes(msg)
35
38
 
36
39
  if msg.getbyte(0) == @uid
37
- return msg[1..-3] if msg[-2,2].unpack('S<')[0] == crc16(msg[0..-3])
40
+ return msg[1..-3] if msg[-2, 2].unpack1("S<") == crc16(msg[0..-3])
41
+
38
42
  log "Ignore package: don't match CRC"
39
43
  else
40
44
  log "Ignore package: don't match uid ID"
41
45
  end
42
46
  loop do
43
- #waite timeout
47
+ # waite timeout
44
48
  sleep(0.1)
45
49
  end
46
50
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
- require 'gserver'
4
+ require "gserver"
3
5
  rescue
4
6
  warn "[WARNING] Install `gserver` gem for use RTUViaTCPServer"
5
7
  end
@@ -13,7 +15,7 @@ module ModBus
13
15
  # slave.discrete_inputs = [1,1,0,0]
14
16
  # slave.holding_registers = [1,2,3,4]
15
17
  # slave.input_registers = [1,2,3,4]
16
- # srv.debug = true
18
+ # srv.logger = Logger.new($stdout)
17
19
  # srv.start
18
20
  class RTUViaTCPServer < GServer
19
21
  include Debug
@@ -26,10 +28,10 @@ module ModBus
26
28
  # @param [Hash] opts options of server
27
29
  # @option opts [String] :host host of server default '127.0.0.1'
28
30
  # @option opts [Float, Integer] :max_connection max of TCP connection with server default 4
29
- def initialize(port = 10002, opts = {})
31
+ def initialize(port = 10_002, opts = {})
30
32
  opts[:host] = DEFAULT_HOST unless opts[:host]
31
33
  opts[:max_connection] = 4 unless opts[:max_connection]
32
- super(port, host = opts[:host], maxConnection = opts[:max_connection])
33
- end
34
+ super(port, opts[:host], opts[:max_connection])
35
+ end
34
36
  end
35
37
  end
@@ -1,4 +1,6 @@
1
- require 'timeout'
1
+ # frozen_string_literal: true
2
+
3
+ require "timeout"
2
4
 
3
5
  module ModBus
4
6
  module Server
@@ -8,7 +10,7 @@ module ModBus
8
10
  def initialize
9
11
  @coils = []
10
12
  @discrete_inputs = []
11
- @holding_registers =[]
13
+ @holding_registers = []
12
14
  @input_registers = []
13
15
  end
14
16
  end
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ModBus
2
4
  # Module for implementation ModBus server
3
5
  module Server
4
- autoload :Slave, 'rmodbus/server/slave'
6
+ autoload :Slave, "rmodbus/server/slave"
5
7
 
6
8
  attr_accessor :promiscuous, :request_callback, :response_callback
7
9
 
8
- Funcs = [1,2,3,4,5,6,15,16,22,23]
10
+ FUNCS = [1, 2, 3, 4, 5, 6, 15, 16, 22, 23].freeze
9
11
 
10
12
  def with_slave(uid)
11
13
  slave = slaves[uid] ||= Server::Slave.new
@@ -30,7 +32,7 @@ module ModBus
30
32
  end
31
33
  request_callback&.call(uid, func, params) unless is_response
32
34
 
33
- if uid == 0
35
+ if uid.zero?
34
36
  slaves.each_key { |specific_uid| exec_req(specific_uid, func, params, pdu) }
35
37
  return
36
38
  end
@@ -46,9 +48,10 @@ module ModBus
46
48
  return
47
49
  end
48
50
 
49
- unless Funcs.include?(func)
51
+ unless FUNCS.include?(func)
50
52
  log("Server RX unrecognized function #{func} to #{uid}")
51
53
  return unless slave
54
+
52
55
  return (func | 0x80).chr + 1.chr
53
56
  end
54
57
 
@@ -56,6 +59,7 @@ module ModBus
56
59
  @pending_response_req = params
57
60
 
58
61
  return unless slave
62
+
59
63
  pdu = process_func(func, slave, pdu, params)
60
64
  if response_callback
61
65
  res = parse_response(pdu.getbyte(0), pdu)
@@ -84,80 +88,87 @@ module ModBus
84
88
  end
85
89
 
86
90
  def parse_response(func, res)
87
- if func & 0x80 == 0x80 && Funcs.include?(func & 0x7f)
91
+ if func & 0x80 == 0x80 && FUNCS.include?(func & 0x7f)
88
92
  return nil unless res.length == 2
93
+
89
94
  return { err: res[1].ord }
90
95
  end
91
96
 
92
97
  case func
93
98
  when 1, 2
94
99
  return nil unless res.length == res[1].ord + 2
95
- res[2..-1].unpack_bits
100
+
101
+ res[2..].unpack_bits
96
102
  when 3, 4, 23
97
103
  return nil unless res.length == res[1].ord + 2
98
- res[2..-1].unpack('n*')
104
+
105
+ res[2..].unpack("n*")
99
106
  when 5, 6, 15, 16
100
107
  return nil unless res.length == 5
108
+
101
109
  {}
102
110
  when 22
103
111
  return nil unless res.length == 7
112
+
104
113
  {}
105
114
  end
106
115
  end
107
116
 
108
117
  def process_func(func, slave, req, params)
109
118
  case func
110
- when 1
111
- unless (err = validate_read_func(params, slave.coils, 2000))
112
- val = slave.coils[params[:addr],params[:quant]].pack_to_word
113
- pdu = func.chr + val.size.chr + val
114
- end
115
- when 2
116
- unless (err = validate_read_func(params, slave.discrete_inputs, 2000))
117
- val = slave.discrete_inputs[params[:addr],params[:quant]].pack_to_word
118
- pdu = func.chr + val.size.chr + val
119
- end
120
- when 3
121
- unless (err = validate_read_func(params, slave.holding_registers))
122
- pdu = func.chr + (params[:quant] * 2).chr + slave.holding_registers[params[:addr],params[:quant]].pack('n*')
123
- end
124
- when 4
125
- unless (err = validate_read_func(params, slave.input_registers))
126
- pdu = func.chr + (params[:quant] * 2).chr + slave.input_registers[params[:addr],params[:quant]].pack('n*')
127
- end
128
- when 5
129
- unless (err = validate_write_coil_func(params, slave))
130
- params[:val] = 1 if params[:val] == 0xff00
131
- slave.coils[params[:addr]] = params[:val]
132
- pdu = req
133
- end
134
- when 6
135
- unless (err = validate_write_register_func(params, slave))
136
- slave.holding_registers[params[:addr]] = params[:val]
137
- pdu = req
138
- end
139
- when 15
140
- unless (err = validate_write_multiple_coils_func(params, slave))
141
- slave.coils[params[:addr],params[:quant]] = params[:val][0,params[:quant]]
142
- pdu = req[0,5]
143
- end
144
- when 16
145
- unless (err = validate_write_multiple_registers_func(params, slave))
146
- slave.holding_registers[params[:addr],params[:quant]] = params[:val]
147
- pdu = req[0,5]
148
- end
149
- when 22
150
- unless (err = validate_write_register_func(params, slave))
151
- addr = params[:addr]
152
- and_mask = params[:and_mask]
153
- slave.holding_registers[addr] = (slave.holding_registers[addr] & and_mask) | (params[:or_mask] & ~and_mask)
154
- pdu = req
155
- end
156
- when 23
157
- unless (err = validate_read_write_multiple_registers_func(params, slave))
158
- slave.holding_registers[params[:write][:addr],params[:write][:quant]] = params[:write][:val]
159
- pdu = func.chr + (params[:read][:quant] * 2).chr + slave.holding_registers[params[:read][:addr],params[:read][:quant]].pack('n*')
160
- end
119
+ when 1
120
+ unless (err = validate_read_func(params, slave.coils, 2000))
121
+ val = slave.coils[params[:addr], params[:quant]].pack_bits
122
+ pdu = func.chr + val.size.chr + val
123
+ end
124
+ when 2
125
+ unless (err = validate_read_func(params, slave.discrete_inputs, 2000))
126
+ val = slave.discrete_inputs[params[:addr], params[:quant]].pack_bits
127
+ pdu = func.chr + val.size.chr + val
128
+ end
129
+ when 3
130
+ unless (err = validate_read_func(params, slave.holding_registers))
131
+ pdu = func.chr + (params[:quant] * 2).chr + slave.holding_registers[params[:addr],
132
+ params[:quant]].pack("n*")
133
+ end
134
+ when 4
135
+ unless (err = validate_read_func(params, slave.input_registers))
136
+ pdu = func.chr + (params[:quant] * 2).chr + slave.input_registers[params[:addr], params[:quant]].pack("n*")
137
+ end
138
+ when 5
139
+ unless (err = validate_write_coil_func(params, slave))
140
+ params[:val] = 1 if params[:val] == 0xff00
141
+ slave.coils[params[:addr]] = params[:val]
142
+ pdu = req
143
+ end
144
+ when 6
145
+ unless (err = validate_write_register_func(params, slave))
146
+ slave.holding_registers[params[:addr]] = params[:val]
147
+ pdu = req
148
+ end
149
+ when 15
150
+ unless (err = validate_write_multiple_coils_func(params, slave))
151
+ slave.coils[params[:addr], params[:quant]] = params[:val][0, params[:quant]]
152
+ pdu = req[0, 5]
153
+ end
154
+ when 16
155
+ unless (err = validate_write_multiple_registers_func(params, slave))
156
+ slave.holding_registers[params[:addr], params[:quant]] = params[:val]
157
+ pdu = req[0, 5]
158
+ end
159
+ when 22
160
+ unless (err = validate_write_register_func(params, slave))
161
+ addr = params[:addr]
162
+ and_mask = params[:and_mask]
163
+ slave.holding_registers[addr] = (slave.holding_registers[addr] & and_mask) | (params[:or_mask] & ~and_mask)
164
+ pdu = req
165
+ end
166
+ when 23
167
+ unless (err = validate_read_write_multiple_registers_func(params, slave))
168
+ slave.holding_registers[params[:write][:addr], params[:write][:quant]] = params[:write][:val]
169
+ pdu = func.chr + (params[:read][:quant] * 2).chr + slave.holding_registers[params[:read][:addr],
170
+ params[:read][:quant]].pack("n*")
171
+ end
161
172
  end
162
173
 
163
174
  if err
@@ -169,38 +180,45 @@ module ModBus
169
180
 
170
181
  def parse_read_func(req, expected_length = 5)
171
182
  return nil if expected_length && req.length != expected_length
172
- { quant: req[3,2].unpack('n')[0], addr: req[1,2].unpack('n')[0] }
183
+
184
+ { quant: req[3, 2].unpack1("n"), addr: req[1, 2].unpack1("n") }
173
185
  end
174
186
 
175
- def validate_read_func(params, field, quant_max=0x7d)
187
+ def validate_read_func(params, field, quant_max = 0x7d)
176
188
  return 3 unless params[:quant] <= quant_max
177
- return 2 unless params[:addr] + params[:quant] <= field.size
189
+
190
+ 2 unless params[:addr] + params[:quant] <= field.size
178
191
  end
179
192
 
180
193
  def parse_write_coil_func(req)
181
194
  return nil unless req.length == 5
182
- { addr: req[1,2].unpack('n')[0], val: req[3,2].unpack('n')[0] }
195
+
196
+ { addr: req[1, 2].unpack1("n"), val: req[3, 2].unpack1("n") }
183
197
  end
184
198
 
185
199
  def validate_write_coil_func(params, slave)
186
200
  return 2 unless params[:addr] <= slave.coils.size
187
- return 3 unless params[:val] == 0 or params[:val] == 0xff00
201
+
202
+ 3 unless params[:val].zero? || (params[:val] == 0xff00)
188
203
  end
189
204
 
190
205
  def parse_write_register_func(req)
191
206
  return nil unless req.length == 5
192
- { addr: req[1,2].unpack('n')[0], val: req[3,2].unpack('n')[0] }
207
+
208
+ { addr: req[1, 2].unpack1("n"), val: req[3, 2].unpack1("n") }
193
209
  end
194
210
 
195
211
  def validate_write_register_func(params, slave)
196
- return 2 unless params[:addr] <= slave.holding_registers.size
212
+ 2 unless params[:addr] <= slave.holding_registers.size
197
213
  end
198
214
 
199
215
  def parse_write_multiple_coils_func(req)
200
216
  return nil if req.length < 7
217
+
201
218
  params = parse_read_func(req, nil)
202
- return nil if req.length != 6 + (params[:quant] + 7) / 8
203
- params[:val] = req[6,params[:quant]].unpack_bits
219
+ return nil if req.length != 6 + ((params[:quant] + 7) / 8)
220
+
221
+ params[:val] = req[6, params[:quant]].unpack_bits
204
222
  params
205
223
  end
206
224
 
@@ -210,9 +228,11 @@ module ModBus
210
228
 
211
229
  def parse_write_multiple_registers_func(req)
212
230
  return nil if req.length < 8
231
+
213
232
  params = parse_read_func(req, nil)
214
- return nil if req.length != 6 + params[:quant] * 2
215
- params[:val] = req[6,params[:quant] * 2].unpack('n*')
233
+ return nil if req.length != 6 + (params[:quant] * 2)
234
+
235
+ params[:val] = req[6, params[:quant] * 2].unpack("n*")
216
236
  params
217
237
  end
218
238
 
@@ -222,24 +242,28 @@ module ModBus
222
242
 
223
243
  def parse_mask_write_register_func(req)
224
244
  return nil if req.length != 7
245
+
225
246
  {
226
- addr: req[1,2].unpack('n')[0],
227
- and_mask: req[3,2].unpack('n')[0],
228
- or_mask: req[5,2].unpack('n')[0]
247
+ addr: req[1, 2].unpack1("n"),
248
+ and_mask: req[3, 2].unpack1("n"),
249
+ or_mask: req[5, 2].unpack1("n")
229
250
  }
230
251
  end
231
252
 
232
253
  def parse_read_write_multiple_registers_func(req)
233
254
  return nil if req.length < 12
255
+
234
256
  params = { read: parse_read_func(req, nil),
235
- write: parse_write_multiple_registers_func(req[4..-1])}
257
+ write: parse_write_multiple_registers_func(req[4..]) }
236
258
  return nil if params[:write].nil?
259
+
237
260
  params
238
261
  end
239
262
 
240
263
  def validate_read_write_multiple_registers_func(params, slave)
241
264
  result = validate_read_func(params[:read], slave.holding_registers)
242
265
  return result if result
266
+
243
267
  validate_write_multiple_registers_func(params[:write], slave)
244
268
  end
245
269
  end
data/lib/rmodbus/sp.rb CHANGED
@@ -1,36 +1,34 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
- require 'serialport'
3
- rescue Exception => e
4
- warn "[WARNING] Install `serialport` gem for use RTU protocols"
4
+ require "ccutrer-serialport"
5
+ rescue LoadError
6
+ warn "[WARNING] Install `ccutrer-serialport` gem for use RTU protocols"
5
7
  end
6
8
 
7
9
  module ModBus
8
10
  module SP
9
11
  attr_reader :port, :baud, :data_bits, :stop_bits, :parity, :read_timeout
12
+
10
13
  # Open serial port
11
- # @param [String] port name serial ports ("/dev/ttyS0" POSIX, "com1" - Windows)
14
+ # @param [String] port name serial ports ("/dev/ttyS0")
12
15
  # @param [Integer] baud rate serial port (default 9600)
13
16
  # @param [Hash] opts the options of serial port
14
17
  #
15
18
  # @option opts [Integer] :data_bits from 5 to 8
16
19
  # @option opts [Integer] :stop_bits 1 or 2
17
- # @option opts [Integer] :parity NONE, EVEN or ODD
18
- # @option opts [Integer] :read_timeout default 100 ms
20
+ # @option opts [Integer] :parity :none, :even or :odd
19
21
  # @return [SerialPort] io serial port
20
22
  def open_serial_port(port, baud, opts = {})
21
23
  @port, @baud = port, baud
22
24
 
23
- @data_bits, @stop_bits, @parity, @read_timeout = 8, 1, SerialPort::NONE, 100
25
+ @data_bits, @stop_bits, @parity = 8, 1, :none
24
26
 
25
27
  @data_bits = opts[:data_bits] unless opts[:data_bits].nil?
26
28
  @stop_bits = opts[:stop_bits] unless opts[:stop_bits].nil?
27
29
  @parity = opts[:parity] unless opts[:parity].nil?
28
- @read_timeout = opts[:read_timeout] unless opts[:read_timeout].nil?
29
30
 
30
- io = SerialPort.new(@port, @baud, @data_bits, @stop_bits, @parity)
31
- io.flow_control = SerialPort::NONE
32
- io.read_timeout = @read_timeout
33
- io
31
+ CCutrer::SerialPort.new(@port, baud: @baud, data_bits: @data_bits, stop_bits: @stop_bits, parity: @parity)
34
32
  end
35
33
  end
36
34
  end
data/lib/rmodbus/tcp.rb CHANGED
@@ -1,9 +1,12 @@
1
- require 'socket'
1
+ # frozen_string_literal: true
2
+
3
+ require "socket"
2
4
 
3
5
  module ModBus
4
6
  module TCP
5
7
  include Errors
6
8
  attr_reader :ipaddr, :port
9
+
7
10
  # Open TCP socket
8
11
  #
9
12
  # @param [String] ipaddr IP address of remote server
@@ -22,7 +25,7 @@ module ModBus
22
25
  begin
23
26
  io = Socket.tcp(@ipaddr, @port, nil, nil, connect_timeout: timeout)
24
27
  rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT
25
- raise ModBusTimeout.new, 'Timed out attempting to create connection'
28
+ raise ModBusTimeout.new, "Timed out attempting to create connection"
26
29
  end
27
30
 
28
31
  io
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ModBus
2
4
  # TCP client implementation
3
5
  # @example
@@ -13,6 +15,7 @@ module ModBus
13
15
  include TCP
14
16
 
15
17
  protected
18
+
16
19
  # Open TCP\IP connection
17
20
  def open_connection(ipaddr, port = 502, opts = {})
18
21
  open_tcp_connection(ipaddr, port, opts)