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.
- checksums.yaml +4 -4
- data/NEWS.md +14 -7
- data/README.md +8 -8
- data/examples/perfomance_rtu.rb +55 -56
- data/examples/perfomance_rtu_via_tcp.rb +54 -55
- data/examples/perfomance_tcp.rb +54 -55
- data/examples/simple_xpca_gateway.rb +85 -0
- data/examples/use_rtu_via_tcp_modbus.rb +14 -11
- data/examples/use_tcp_modbus.rb +14 -11
- data/lib/rmodbus/client/slave.rb +58 -70
- data/lib/rmodbus/client.rb +13 -10
- data/lib/rmodbus/debug.rb +10 -6
- data/lib/rmodbus/errors.rb +26 -2
- data/lib/rmodbus/ext.rb +72 -51
- data/lib/rmodbus/options.rb +4 -1
- data/lib/rmodbus/proxy.rb +14 -9
- data/lib/rmodbus/rtu.rb +38 -32
- data/lib/rmodbus/rtu_client.rb +5 -2
- data/lib/rmodbus/rtu_server.rb +9 -7
- data/lib/rmodbus/rtu_slave.rb +6 -2
- data/lib/rmodbus/rtu_via_tcp_server.rb +7 -5
- data/lib/rmodbus/server/slave.rb +4 -2
- data/lib/rmodbus/server.rb +97 -73
- data/lib/rmodbus/sp.rb +10 -12
- data/lib/rmodbus/tcp.rb +5 -2
- data/lib/rmodbus/tcp_client.rb +3 -0
- data/lib/rmodbus/tcp_server.rb +28 -26
- data/lib/rmodbus/tcp_slave.rb +17 -16
- data/lib/rmodbus/version.rb +3 -1
- data/lib/rmodbus.rb +20 -18
- metadata +50 -49
- data/Rakefile +0 -29
- data/examples/simple-xpca-gateway.rb +0 -84
- data/spec/client_spec.rb +0 -88
- data/spec/exception_spec.rb +0 -120
- data/spec/ext_spec.rb +0 -52
- data/spec/logging_spec.rb +0 -89
- data/spec/proxy_spec.rb +0 -74
- data/spec/read_rtu_response_spec.rb +0 -92
- data/spec/response_mismach_spec.rb +0 -163
- data/spec/rtu_client_spec.rb +0 -86
- data/spec/rtu_server_spec.rb +0 -31
- data/spec/rtu_via_tcp_client_spec.rb +0 -76
- data/spec/rtu_via_tcp_server_spec.rb +0 -89
- data/spec/slave_spec.rb +0 -55
- data/spec/spec_helper.rb +0 -54
- data/spec/tcp_client_spec.rb +0 -88
- data/spec/tcp_server_spec.rb +0 -158
data/lib/rmodbus/tcp_server.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
begin
|
2
|
-
require
|
4
|
+
require "gserver"
|
3
5
|
rescue
|
4
6
|
warn "[WARNING] Install `gserver` gem for use TCPServer"
|
5
7
|
end
|
@@ -13,11 +15,11 @@ 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.
|
18
|
+
# srv.logger = Logger.new($stdout)
|
17
19
|
# srv.start
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
class TCPServer < GServer
|
21
|
+
include Debug
|
22
|
+
include Server
|
21
23
|
|
22
24
|
# Init server
|
23
25
|
# @param [Integer] port listen port
|
@@ -25,11 +27,11 @@ module ModBus
|
|
25
27
|
# @param [Hash] opts options of server
|
26
28
|
# @option opts [String] :host host of server default '127.0.0.1'
|
27
29
|
# @option opts [Float, Integer] :max_connection max of TCP connection with server default 4
|
28
|
-
|
30
|
+
def initialize(port = 502, opts = {})
|
29
31
|
opts[:host] = DEFAULT_HOST unless opts[:host]
|
30
32
|
opts[:max_connection] = 4 unless opts[:max_connection]
|
31
|
-
|
32
|
-
|
33
|
+
super(port, opts[:host], opts[:max_connection])
|
34
|
+
end
|
33
35
|
|
34
36
|
# set the default param
|
35
37
|
def with_slave(uid = 255)
|
@@ -39,29 +41,29 @@ module ModBus
|
|
39
41
|
# Serve requests
|
40
42
|
# @param [TCPSocket] io socket
|
41
43
|
def serve(io)
|
42
|
-
|
44
|
+
until stopped?
|
43
45
|
header = io.read(7)
|
44
|
-
tx_id = header[0,2]
|
45
|
-
proto_id = header[2,2]
|
46
|
-
len = header[4,2].
|
46
|
+
tx_id = header[0, 2]
|
47
|
+
proto_id = header[2, 2]
|
48
|
+
len = header[4, 2].unpack1("n")
|
47
49
|
unit_id = header.getbyte(6)
|
48
|
-
|
49
|
-
|
50
|
-
|
50
|
+
next unless proto_id == "\x00\x00"
|
51
|
+
|
52
|
+
req = io.read(len - 1)
|
53
|
+
log "Server RX (#{req.size} bytes): #{logging_bytes(req)}"
|
51
54
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
+
func = req.getbyte(0)
|
56
|
+
params = parse_request(func, req)
|
57
|
+
pdu = exec_req(unit_id, func, params, req)
|
55
58
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
59
|
+
if pdu
|
60
|
+
resp = "#{tx_id}\x00\x00#{(pdu.size + 1).to_word}#{unit_id.chr}#{pdu}"
|
61
|
+
log "Server TX (#{resp.size} bytes): #{logging_bytes(resp)}"
|
62
|
+
io.write resp
|
63
|
+
else
|
64
|
+
log "Ignored server RX (invalid unit ID #{unit_id}, #{req.size} bytes): #{logging_bytes(req)}"
|
63
65
|
end
|
64
66
|
end
|
65
67
|
end
|
66
|
-
|
68
|
+
end
|
67
69
|
end
|
data/lib/rmodbus/tcp_slave.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ModBus
|
2
4
|
# TCP slave implementation
|
3
5
|
# @example
|
@@ -16,16 +18,17 @@ module ModBus
|
|
16
18
|
# @see Slave::initialize
|
17
19
|
def initialize(uid, io)
|
18
20
|
@transaction = 0
|
19
|
-
super
|
21
|
+
super
|
20
22
|
end
|
21
23
|
|
22
24
|
private
|
25
|
+
|
23
26
|
# overide method for RTU over TCP implamentaion
|
24
27
|
# @see Slave#query
|
25
28
|
def send_pdu(pdu)
|
26
|
-
@transaction = 0 if @transaction.next >
|
29
|
+
@transaction = 0 if @transaction.next > 65_535
|
27
30
|
@transaction += 1
|
28
|
-
msg = @transaction.to_word
|
31
|
+
msg = "#{@transaction.to_word}\x00\x00#{(pdu.size + 1).to_word}#{@uid.chr}#{pdu}"
|
29
32
|
@io.write msg
|
30
33
|
|
31
34
|
log "Tx (#{msg.size} bytes): " + logging_bytes(msg)
|
@@ -36,19 +39,17 @@ module ModBus
|
|
36
39
|
def read_pdu
|
37
40
|
loop do
|
38
41
|
header = @io.read(7)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
51
|
-
end
|
42
|
+
next unless header
|
43
|
+
|
44
|
+
trn = header[0, 2].unpack1("n")
|
45
|
+
len = header[4, 2].unpack1("n")
|
46
|
+
msg = @io.read(len - 1)
|
47
|
+
|
48
|
+
log "Rx (#{(header + msg).size} bytes): " + logging_bytes(header + msg)
|
49
|
+
|
50
|
+
return msg if trn == @transaction
|
51
|
+
|
52
|
+
log "Transaction number mismatch. A packet is ignored."
|
52
53
|
end
|
53
54
|
end
|
54
55
|
end
|
data/lib/rmodbus/version.rb
CHANGED
data/lib/rmodbus.rb
CHANGED
@@ -1,21 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rmodbus/ext"
|
4
|
+
require "rmodbus/proxy"
|
5
|
+
require "rmodbus/version"
|
4
6
|
|
5
7
|
module ModBus
|
6
|
-
autoload :Errors,
|
7
|
-
autoload :Debug,
|
8
|
-
autoload :Options,
|
9
|
-
autoload :SP,
|
10
|
-
autoload :RTU,
|
11
|
-
autoload :TCP,
|
12
|
-
autoload :Client,
|
13
|
-
autoload :Server,
|
14
|
-
autoload :TCPSlave,
|
15
|
-
autoload :TCPClient,
|
16
|
-
autoload :TCPServer,
|
17
|
-
autoload :RTUSlave,
|
18
|
-
autoload :RTUClient,
|
19
|
-
autoload :RTUServer,
|
20
|
-
autoload :RTUViaTCPServer,
|
8
|
+
autoload :Errors, "rmodbus/errors"
|
9
|
+
autoload :Debug, "rmodbus/debug"
|
10
|
+
autoload :Options, "rmodbus/options"
|
11
|
+
autoload :SP, "rmodbus/sp"
|
12
|
+
autoload :RTU, "rmodbus/rtu"
|
13
|
+
autoload :TCP, "rmodbus/tcp"
|
14
|
+
autoload :Client, "rmodbus/client"
|
15
|
+
autoload :Server, "rmodbus/server"
|
16
|
+
autoload :TCPSlave, "rmodbus/tcp_slave"
|
17
|
+
autoload :TCPClient, "rmodbus/tcp_client"
|
18
|
+
autoload :TCPServer, "rmodbus/tcp_server"
|
19
|
+
autoload :RTUSlave, "rmodbus/rtu_slave"
|
20
|
+
autoload :RTUClient, "rmodbus/rtu_client"
|
21
|
+
autoload :RTUServer, "rmodbus/rtu_server"
|
22
|
+
autoload :RTUViaTCPServer, "rmodbus/rtu_via_tcp_server"
|
21
23
|
end
|
metadata
CHANGED
@@ -1,113 +1,127 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rmodbus-ccutrer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- A.Timin, J. Sanders, K. Reynolds, F. Luizão, C. Cutrer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '2.2'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '2.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: ccutrer-serialport
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '1.1'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '1.1'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: gserver
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '0.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '13.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '13.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '3.11'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '3.11'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rubocop-inst
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '1.
|
89
|
+
version: '1.0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '1.
|
96
|
+
version: '1.0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: rubocop-rake
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0.
|
103
|
+
version: '0.6'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0.
|
110
|
+
version: '0.6'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop-rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '3.0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '3.0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: digest-crc
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,7 +137,7 @@ dependencies:
|
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '0.1'
|
125
139
|
description:
|
126
|
-
email:
|
140
|
+
email: cody@cutrer.us
|
127
141
|
executables: []
|
128
142
|
extensions: []
|
129
143
|
extra_rdoc_files:
|
@@ -132,11 +146,10 @@ extra_rdoc_files:
|
|
132
146
|
files:
|
133
147
|
- NEWS.md
|
134
148
|
- README.md
|
135
|
-
- Rakefile
|
136
149
|
- examples/perfomance_rtu.rb
|
137
150
|
- examples/perfomance_rtu_via_tcp.rb
|
138
151
|
- examples/perfomance_tcp.rb
|
139
|
-
- examples/
|
152
|
+
- examples/simple_xpca_gateway.rb
|
140
153
|
- examples/use_rtu_via_tcp_modbus.rb
|
141
154
|
- examples/use_tcp_modbus.rb
|
142
155
|
- lib/rmodbus.rb
|
@@ -160,25 +173,13 @@ files:
|
|
160
173
|
- lib/rmodbus/tcp_server.rb
|
161
174
|
- lib/rmodbus/tcp_slave.rb
|
162
175
|
- lib/rmodbus/version.rb
|
163
|
-
|
164
|
-
- spec/exception_spec.rb
|
165
|
-
- spec/ext_spec.rb
|
166
|
-
- spec/logging_spec.rb
|
167
|
-
- spec/proxy_spec.rb
|
168
|
-
- spec/read_rtu_response_spec.rb
|
169
|
-
- spec/response_mismach_spec.rb
|
170
|
-
- spec/rtu_client_spec.rb
|
171
|
-
- spec/rtu_server_spec.rb
|
172
|
-
- spec/rtu_via_tcp_client_spec.rb
|
173
|
-
- spec/rtu_via_tcp_server_spec.rb
|
174
|
-
- spec/slave_spec.rb
|
175
|
-
- spec/spec_helper.rb
|
176
|
-
- spec/tcp_client_spec.rb
|
177
|
-
- spec/tcp_server_spec.rb
|
178
|
-
homepage: https://github.com/ccutrer/rmodbus
|
176
|
+
homepage: https://github.com/rmodbus/rmodbus
|
179
177
|
licenses:
|
180
178
|
- BSD-3-Clause
|
181
|
-
metadata:
|
179
|
+
metadata:
|
180
|
+
changelog_uri: https://github.com/rmodbus/rmodbus/blob/main/NEWS.md
|
181
|
+
source_code_uri: https://github.com/rmodbus/rmodbus
|
182
|
+
rubygems_mfa_required: 'true'
|
182
183
|
post_install_message:
|
183
184
|
rdoc_options:
|
184
185
|
- "--title"
|
@@ -192,14 +193,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
192
193
|
requirements:
|
193
194
|
- - ">="
|
194
195
|
- !ruby/object:Gem::Version
|
195
|
-
version: '
|
196
|
+
version: '2.7'
|
196
197
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
198
|
requirements:
|
198
199
|
- - ">="
|
199
200
|
- !ruby/object:Gem::Version
|
200
201
|
version: '0'
|
201
202
|
requirements: []
|
202
|
-
rubygems_version: 3.
|
203
|
+
rubygems_version: 3.5.11
|
203
204
|
signing_key:
|
204
205
|
specification_version: 4
|
205
206
|
summary: RModBus - free implementation of protocol ModBus
|
data/Rakefile
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bundler'
|
5
|
-
begin
|
6
|
-
Bundler.setup(:default, :development)
|
7
|
-
rescue Bundler::BundlerError => e
|
8
|
-
$stderr.puts e.message
|
9
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
-
exit e.status_code
|
11
|
-
end
|
12
|
-
|
13
|
-
require 'rake'
|
14
|
-
require 'rspec/core'
|
15
|
-
require 'rspec/core/rake_task'
|
16
|
-
RSpec::Core::RakeTask.new(:spec) do |spec|
|
17
|
-
spec.pattern = FileList['spec/**/*_spec.rb']
|
18
|
-
begin
|
19
|
-
require 'serialport'
|
20
|
-
rescue LoadError => e
|
21
|
-
spec.pattern.exclude("spec/rtu_client_spec.rb", "spec/rtu_server_spec.rb")
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
task :default => :spec
|
26
|
-
|
27
|
-
task :pry do
|
28
|
-
sh "bundle exec pry -r ./lib/rmodbus.rb"
|
29
|
-
end
|
@@ -1,84 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
It's very simple example of implementation XPCA gateway (see http://www.xpca.org)
|
3
|
-
for communication with TCP ModBus devices
|
4
|
-
It receives REST requests (e.g http://127.0.0.1:4567/mb/127.0.0.1/8502/1/coils/6/17 )
|
5
|
-
and returns data in JSON format addr : data:
|
6
|
-
{"coils": {
|
7
|
-
"6":{
|
8
|
-
"value":0,
|
9
|
-
"timestamp":"2011-07-12 18:11:03 +0000",
|
10
|
-
"quality":"good"
|
11
|
-
},
|
12
|
-
"7":{
|
13
|
-
"value":0,
|
14
|
-
"timestamp":"2011-07-12 18:11:03 +0000",
|
15
|
-
"quality":"good"
|
16
|
-
}
|
17
|
-
...
|
18
|
-
}
|
19
|
-
|
20
|
-
This code requies gems: rmodbus, sinatra and json
|
21
|
-
2011 (c) Aleksey Timin
|
22
|
-
=end
|
23
|
-
|
24
|
-
require 'rubygems'
|
25
|
-
require 'rmodbus'
|
26
|
-
require 'sinatra'
|
27
|
-
require 'json'
|
28
|
-
|
29
|
-
# Launche TCP ModBus server for test
|
30
|
-
IP = '127.0.0.1'
|
31
|
-
PORT = 8502
|
32
|
-
|
33
|
-
@srv = ModBus::TCPServer.new(PORT,1)
|
34
|
-
|
35
|
-
@srv.holding_registers = Array.new(100) { |i| i = i + 1 }
|
36
|
-
@srv.input_registers = Array.new(100) { |i| i = i + 1 }
|
37
|
-
@srv.coils = Array.new(100) { |i| i = 0 }
|
38
|
-
@srv.discrete_inputs = Array.new(100) { |i| i = 0 }
|
39
|
-
|
40
|
-
@srv.start
|
41
|
-
|
42
|
-
|
43
|
-
# Calc a GET request
|
44
|
-
# @example
|
45
|
-
# http://127.0.0.1:4567/mb/127.0.0.1/8502/1/coils/6/17
|
46
|
-
#
|
47
|
-
# HTTP route: GET http://localhost/mb/:ip/:port/:slave/:dataplace/:firstaddr/:lastaddr
|
48
|
-
#
|
49
|
-
# :ip - ip addr of ModBus TCP Server
|
50
|
-
# :port - port of ModBUs TCP Server
|
51
|
-
# :slave - id of slave device
|
52
|
-
# :dataplace - valid values: coils, discrete_inputs, input_registers, holding_registers
|
53
|
-
# :firstaddr - first addr of registers(contacts)
|
54
|
-
# :lastaddr - last addr of registers(contacts)
|
55
|
-
get '/mb/:ip/:port/:slave/:dataplace/:firstaddr/:lastaddr' do
|
56
|
-
resp = {}
|
57
|
-
begin
|
58
|
-
data = []
|
59
|
-
ModBus::TCPClient.new(params[:ip].to_s, params[:port].to_i) do |cl|
|
60
|
-
cl.with_slave(params[:slave].to_i) do |slave|
|
61
|
-
slave.debug = true
|
62
|
-
dataplace = slave.send params[:dataplace]
|
63
|
-
data = dataplace[params[:firstaddr].to_i .. params[:lastaddr].to_i]
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
resp = { params[:dataplace] => {}}
|
68
|
-
data.each_with_index do |v,i|
|
69
|
-
resp[params[:dataplace]][params[:firstaddr].to_i + i] = {
|
70
|
-
:value => v,
|
71
|
-
:timestamp => Time.now.utc.strftime("%Y-%m-%d %H:%M:%S %z"),
|
72
|
-
:quality => "good"
|
73
|
-
}
|
74
|
-
end
|
75
|
-
rescue Exception => e
|
76
|
-
resp = { :error => {
|
77
|
-
:type => e.class,
|
78
|
-
:message => e.message }
|
79
|
-
}
|
80
|
-
end
|
81
|
-
|
82
|
-
content_type "application/json"
|
83
|
-
resp.to_json
|
84
|
-
end
|
data/spec/client_spec.rb
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
# -*- coding: ascii
|
2
|
-
require 'rmodbus'
|
3
|
-
|
4
|
-
describe ModBus::Client do
|
5
|
-
before do
|
6
|
-
@cl = ModBus::Client.new
|
7
|
-
end
|
8
|
-
|
9
|
-
it "should give object provider for slave" do
|
10
|
-
slave = @cl.with_slave(1)
|
11
|
-
slave.uid.should eq(1)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should give object provider for slave in block" do
|
15
|
-
@cl.with_slave(1) do |slave|
|
16
|
-
slave.uid.should eq(1)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should connect with TCP server" do
|
21
|
-
ModBus::Client.connect do |cl|
|
22
|
-
cl.should be_instance_of(ModBus::Client)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
it ":new alias :connect" do
|
27
|
-
ModBus::Client.new do |cl|
|
28
|
-
cl.should be_instance_of(ModBus::Client)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
it "should close the connection when an exception is raised in the given block" do
|
33
|
-
expect {
|
34
|
-
ModBus::Client.new do |client|
|
35
|
-
client.should_receive(:close)
|
36
|
-
raise
|
37
|
-
end
|
38
|
-
}.to raise_error
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'should common for all slaves :debug flag' do
|
42
|
-
@cl.debug = true
|
43
|
-
@cl.with_slave(1) do |slave_1|
|
44
|
-
slave_1.debug.should be_truthy
|
45
|
-
end
|
46
|
-
@cl.with_slave(2) do |slave_2|
|
47
|
-
slave_2.debug = false
|
48
|
-
slave_2.debug.should be_falsey
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'should common for all slaves :raise_exception_on_mismatch flag' do
|
53
|
-
@cl.raise_exception_on_mismatch = true
|
54
|
-
@cl.with_slave(1) do |slave_1|
|
55
|
-
slave_1.raise_exception_on_mismatch.should be_truthy
|
56
|
-
end
|
57
|
-
|
58
|
-
@cl.with_slave(2) do |slave_2|
|
59
|
-
slave_2.raise_exception_on_mismatch = false
|
60
|
-
slave_2.raise_exception_on_mismatch.should be_falsey
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'should common for all slaves :read_retries options' do
|
65
|
-
@cl.read_retries = 5
|
66
|
-
@cl.with_slave(1) do |slave_1|
|
67
|
-
slave_1.read_retries.should eql(5)
|
68
|
-
end
|
69
|
-
|
70
|
-
@cl.with_slave(2) do |slave_2|
|
71
|
-
slave_2.read_retries = 15
|
72
|
-
slave_2.read_retries.should eql(15)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
it 'should common for all slaves :read_retry_timeout options' do
|
77
|
-
@cl.read_retry_timeout = 5
|
78
|
-
@cl.with_slave(1) do |slave_1|
|
79
|
-
slave_1.read_retry_timeout.should eql(5)
|
80
|
-
end
|
81
|
-
|
82
|
-
@cl.with_slave(2) do |slave_2|
|
83
|
-
slave_2.read_retry_timeout = 15
|
84
|
-
slave_2.read_retry_timeout.should eql(15)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
end
|