rmodbus-ccutrer 2.0.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)