rmodbus 1.3.2 → 2.1.2
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 +5 -5
- data/NEWS.md +19 -0
- 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 +333 -0
- data/lib/rmodbus/client.rb +15 -10
- data/lib/rmodbus/debug.rb +12 -15
- 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 +89 -125
- data/lib/rmodbus/rtu_client.rb +22 -2
- data/lib/rmodbus/rtu_server.rb +16 -12
- data/lib/rmodbus/rtu_slave.rb +26 -3
- data/lib/rmodbus/rtu_via_tcp_server.rb +12 -19
- data/lib/rmodbus/server/slave.rb +18 -0
- data/lib/rmodbus/server.rb +227 -84
- data/lib/rmodbus/sp.rb +10 -12
- data/lib/rmodbus/tcp.rb +9 -10
- data/lib/rmodbus/tcp_client.rb +3 -0
- data/lib/rmodbus/tcp_server.rb +41 -35
- data/lib/rmodbus/tcp_slave.rb +19 -18
- data/lib/rmodbus/version.rb +3 -2
- data/lib/rmodbus.rb +20 -21
- metadata +63 -50
- data/Rakefile +0 -29
- data/examples/simple-xpca-gateway.rb +0 -84
- data/lib/rmodbus/rtu_via_tcp_client.rb +0 -26
- data/lib/rmodbus/rtu_via_tcp_slave.rb +0 -29
- data/lib/rmodbus/slave.rb +0 -308
- data/spec/client_spec.rb +0 -88
- data/spec/exception_spec.rb +0 -119
- 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 -30
- data/spec/rtu_via_tcp_client_spec.rb +0 -76
- data/spec/rtu_via_tcp_server_spec.rb +0 -16
- 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 -129
data/spec/proxy_spec.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
# -*- coding: ascii
|
2
|
-
require 'rmodbus'
|
3
|
-
|
4
|
-
describe Array do
|
5
|
-
before do
|
6
|
-
@slave = double('ModBus Slave')
|
7
|
-
@coil_proxy = ModBus::ReadWriteProxy.new(@slave, :coil)
|
8
|
-
@discrete_input_proxy = ModBus::ReadOnlyProxy.new(@slave, :discrete_input)
|
9
|
-
@holding_register_proxy = ModBus::ReadWriteProxy.new(@slave, :holding_register)
|
10
|
-
@input_register_proxy = ModBus::ReadOnlyProxy.new(@slave, :input_register)
|
11
|
-
end
|
12
|
-
|
13
|
-
# Handle all of the coil methods
|
14
|
-
it "should call read_coil" do
|
15
|
-
@slave.should_receive(:read_coil).with(0, 1)
|
16
|
-
@coil_proxy[0]
|
17
|
-
end
|
18
|
-
it "should call read_coils" do
|
19
|
-
@slave.should_receive(:read_coils).with(0, 2)
|
20
|
-
@coil_proxy[0..1]
|
21
|
-
end
|
22
|
-
it "should call write_coil" do
|
23
|
-
@slave.should_receive(:write_coil).with(0, 1)
|
24
|
-
@coil_proxy[0] = 1
|
25
|
-
end
|
26
|
-
it "should call write_coils" do
|
27
|
-
@slave.should_receive(:write_coils).with(0, [0, 0])
|
28
|
-
@coil_proxy[0..1] = [0, 0]
|
29
|
-
end
|
30
|
-
|
31
|
-
|
32
|
-
# Discrete input tests
|
33
|
-
it "should call read_discrete_input" do
|
34
|
-
@slave.should_receive(:read_discrete_input).with(0, 1)
|
35
|
-
@discrete_input_proxy[0]
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should call read_discrete_inputs" do
|
39
|
-
@slave.should_receive(:read_discrete_inputs).with(0, 2)
|
40
|
-
@discrete_input_proxy[0..1]
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
# Holding Register Tess
|
45
|
-
it "should call read_holding_register" do
|
46
|
-
@slave.should_receive(:read_holding_register).with(0, 1)
|
47
|
-
@holding_register_proxy[0]
|
48
|
-
end
|
49
|
-
it "should call read_holding_registers" do
|
50
|
-
@slave.should_receive(:read_holding_registers).with(0, 2)
|
51
|
-
@holding_register_proxy[0..1]
|
52
|
-
end
|
53
|
-
it "should call write_holding_register" do
|
54
|
-
@slave.should_receive(:write_holding_register).with(0, 1)
|
55
|
-
@holding_register_proxy[0] = 1
|
56
|
-
end
|
57
|
-
it "should call write_holding_registers" do
|
58
|
-
@slave.should_receive(:write_holding_registers).with(0, [0, 0])
|
59
|
-
@holding_register_proxy[0..1] = [0, 0]
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
# Input Register Tests
|
64
|
-
it "should call read_discrete_input" do
|
65
|
-
@slave.should_receive(:read_input_register).with(0, 1)
|
66
|
-
@input_register_proxy[0]
|
67
|
-
end
|
68
|
-
|
69
|
-
it "should call read_discrete_inputs" do
|
70
|
-
@slave.should_receive(:read_input_registers).with(0, 2)
|
71
|
-
@input_register_proxy[0..1]
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
@@ -1,92 +0,0 @@
|
|
1
|
-
# -*- coding: ascii
|
2
|
-
require 'rmodbus'
|
3
|
-
|
4
|
-
#Use public wrap method
|
5
|
-
class ModBus::Client
|
6
|
-
include ModBus::RTU
|
7
|
-
def test_read_method(msg)
|
8
|
-
io = TestIO.new(msg)
|
9
|
-
read_rtu_response(io)
|
10
|
-
end
|
11
|
-
|
12
|
-
end
|
13
|
-
|
14
|
-
class TestIO
|
15
|
-
def initialize(msg)
|
16
|
-
@msg = msg
|
17
|
-
end
|
18
|
-
|
19
|
-
def read(num)
|
20
|
-
result = @msg[0,num]
|
21
|
-
@msg = @msg[num..-1]
|
22
|
-
result
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe "#read_rtu_response" do
|
27
|
-
before do
|
28
|
-
@cl_mb = ModBus::Client.new
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should read response for 'read coils'" do
|
32
|
-
resp = make_resp("\x1\x3\xcd\x6b\x05")
|
33
|
-
@cl_mb.test_read_method(resp).should == resp
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should read response for 'read discrete inputs'" do
|
37
|
-
resp = make_resp("\x2\x3\xac\xdb\x35")
|
38
|
-
@cl_mb.test_read_method(resp).should == resp
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should read response for 'read holding registers'" do
|
42
|
-
resp = make_resp("\x3\x6\x2\x2b\x0\x0\x0\x64")
|
43
|
-
@cl_mb.test_read_method(resp).should == resp
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should read response for 'read input registers'" do
|
47
|
-
resp = make_resp("\x4\x2\x0\xa")
|
48
|
-
@cl_mb.test_read_method(resp).should == resp
|
49
|
-
end
|
50
|
-
|
51
|
-
it "should read response for 'write single coil'" do
|
52
|
-
resp = make_resp("\x5\x0\xac\xff\x0")
|
53
|
-
@cl_mb.test_read_method(resp).should == resp
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should read response for 'write single register'" do
|
57
|
-
resp = make_resp("\x6\x0\x1\x0\x3")
|
58
|
-
@cl_mb.test_read_method(resp).should == resp
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should read response for 'write multiple coils'" do
|
62
|
-
resp = make_resp("\xf\x0\x13\x0\xa")
|
63
|
-
@cl_mb.test_read_method(resp).should == resp
|
64
|
-
end
|
65
|
-
|
66
|
-
it "should read response for 'write multiple registers'" do
|
67
|
-
resp = make_resp("\x10\x0\x1\x0\x2")
|
68
|
-
@cl_mb.test_read_method(resp).should == resp
|
69
|
-
end
|
70
|
-
|
71
|
-
it "should read response 'mask write register'" do
|
72
|
-
resp = make_resp("\x16\x0\x4\x0\xf2\x0\x25")
|
73
|
-
@cl_mb.test_read_method(resp).should == resp
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should read exception codes" do
|
77
|
-
resp = make_resp("\x84\x3")
|
78
|
-
@cl_mb.test_read_method(resp).should == resp
|
79
|
-
end
|
80
|
-
|
81
|
-
it "should raise exception if function is illegal" do
|
82
|
-
resp = make_resp("\x1f\x0\x1\x0\x2")
|
83
|
-
lambda{ @cl_mb.test_read_method(resp)}.should raise_error {
|
84
|
-
ModBus::Errors::IllegalFunction
|
85
|
-
}
|
86
|
-
end
|
87
|
-
|
88
|
-
def make_resp(msg)
|
89
|
-
"\x1" + msg + "\x2\x2" # slave + msg + mock_crc
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
@@ -1,163 +0,0 @@
|
|
1
|
-
# -*- coding: ascii
|
2
|
-
require "spec_helper"
|
3
|
-
|
4
|
-
describe "response mismach" do
|
5
|
-
include RaiseResponseMatcher
|
6
|
-
before(:each) do
|
7
|
-
@slave = ModBus::Slave.new(1, nil)
|
8
|
-
@slave.raise_exception_on_mismatch = true
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should raise error if function code is mismatch" do
|
12
|
-
request = "\x1\x0\x13\x0\x12"
|
13
|
-
response = "\x2\x3\xcd\xb6\x5"
|
14
|
-
mock_query!(request, response)
|
15
|
-
|
16
|
-
lambda{ @slave.read_coils(0x13,0x12) }.should raise_response_mismatch(
|
17
|
-
"Function code is mismatch (expected 1, got 2)",
|
18
|
-
request, response)
|
19
|
-
end
|
20
|
-
|
21
|
-
describe "read coils" do
|
22
|
-
it "should raise error if count of byte is mismatch" do
|
23
|
-
request = "\x1\x0\x13\x0\x12"
|
24
|
-
response = "\x1\x2\xcd\xb6"
|
25
|
-
mock_query!(request, response)
|
26
|
-
|
27
|
-
lambda{ @slave.read_coils(0x13,0x12) }.should raise_response_mismatch(
|
28
|
-
"Byte count is mismatch (expected 3, got 2 bytes)",
|
29
|
-
request, response)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe "read discrete inputs" do
|
34
|
-
it "should raise error if count of byte is mismatch" do
|
35
|
-
request = "\x2\x0\x13\x0\x12"
|
36
|
-
response = "\x2\x2\xcd\xb6"
|
37
|
-
mock_query!(request, response)
|
38
|
-
|
39
|
-
lambda{ @slave.read_discrete_inputs(0x13,0x12) }.should raise_response_mismatch(
|
40
|
-
"Byte count is mismatch (expected 3, got 2 bytes)",
|
41
|
-
request, response)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe "read holding registesrs" do
|
46
|
-
it "should raise error if count of registers is mismatch" do
|
47
|
-
request = "\x3\x0\x8\x0\x1"
|
48
|
-
response = "\x3\x4\x0\xa\x0\xb"
|
49
|
-
mock_query!(request, response)
|
50
|
-
|
51
|
-
lambda{ @slave.read_holding_registers(0x8,0x1) }.should raise_response_mismatch(
|
52
|
-
"Register count is mismatch (expected 1, got 2 regs)",
|
53
|
-
request, response)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe "read input registesrs" do
|
58
|
-
it "should raise error if count of registers is mismatch" do
|
59
|
-
request = "\x4\x0\x8\x0\x2"
|
60
|
-
response = "\x4\x2\xa\x0"
|
61
|
-
mock_query!(request, response)
|
62
|
-
|
63
|
-
lambda{ @slave.read_input_registers(0x8,0x2) }.should raise_response_mismatch(
|
64
|
-
"Register count is mismatch (expected 2, got 1 regs)",
|
65
|
-
request, response)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
describe "write single coil" do
|
70
|
-
it "should raise error if address of coil is mismatch" do
|
71
|
-
request = "\x5\x0\x8\xff\x0"
|
72
|
-
response = "\x5\x0\x9\xff\x0"
|
73
|
-
mock_query!(request, response)
|
74
|
-
|
75
|
-
lambda{ @slave.write_coil(8,true) }.should raise_response_mismatch(
|
76
|
-
"Address is mismatch (expected 8, got 9)",
|
77
|
-
request, response)
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should raise error if value of coil is mismatch" do
|
81
|
-
request = "\x5\x0\x8\xff\x0"
|
82
|
-
response = "\x5\x0\x8\x0\x0"
|
83
|
-
mock_query!(request, response)
|
84
|
-
|
85
|
-
lambda{ @slave.write_coil(8,true) }.should raise_response_mismatch(
|
86
|
-
"Value is mismatch (expected 0xff00, got 0x0)",
|
87
|
-
request, response)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
describe "write single register" do
|
92
|
-
it "should raise error if address of register is mismatch" do
|
93
|
-
request = "\x6\x0\x8\xa\xb"
|
94
|
-
response = "\x6\x0\x9\xa\xb"
|
95
|
-
mock_query!(request, response)
|
96
|
-
|
97
|
-
lambda{ @slave.write_single_register(8,0x0a0b) }.should raise_response_mismatch(
|
98
|
-
"Address is mismatch (expected 8, got 9)",
|
99
|
-
request, response)
|
100
|
-
end
|
101
|
-
|
102
|
-
it "should raise error if value of register is mismatch" do
|
103
|
-
request = "\x6\x0\x8\xa\xb"
|
104
|
-
response = "\x6\x0\x8\x9\xb"
|
105
|
-
mock_query!(request, response)
|
106
|
-
|
107
|
-
lambda{ @slave.write_single_register(8,0x0a0b) }.should raise_response_mismatch(
|
108
|
-
"Value is mismatch (expected 0xa0b, got 0x90b)",
|
109
|
-
request, response)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
describe "write multiple coils" do
|
114
|
-
it "should raise error if address of first coil is mismatch" do
|
115
|
-
request = "\xf\x0\x13\x0\xa\2\xcd\x01"
|
116
|
-
response = "\xf\x0\x14\x0\xa"
|
117
|
-
mock_query!(request, response)
|
118
|
-
|
119
|
-
lambda{ @slave.write_coils(0x13,[1,0,1,1, 0,0,1,1, 1,0]) }.should raise_response_mismatch(
|
120
|
-
"Address is mismatch (expected 19, got 20)",
|
121
|
-
request, response)
|
122
|
-
end
|
123
|
-
|
124
|
-
it "should raise error if quantity of coils is mismatch" do
|
125
|
-
request = "\xf\x0\x13\x0\xa\2\xcd\x01"
|
126
|
-
response = "\xf\x0\x13\x0\x9"
|
127
|
-
mock_query!(request, response)
|
128
|
-
|
129
|
-
lambda{ @slave.write_coils(0x13,[1,0,1,1, 0,0,1,1, 1,0]) }.should raise_response_mismatch(
|
130
|
-
"Quantity is mismatch (expected 10, got 9)",
|
131
|
-
request, response)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
describe "write multiple registers" do
|
136
|
-
it "should raise error if address of first register is mismatch" do
|
137
|
-
request = "\x10\x0\x1\x0\x2\x4\x0\xa\x1\x2"
|
138
|
-
response = "\x10\x0\x2\x0\x2"
|
139
|
-
mock_query!(request, response)
|
140
|
-
|
141
|
-
lambda{ @slave.write_holding_registers(0x1,[0xa,0x102]) }.should raise_response_mismatch(
|
142
|
-
"Address is mismatch (expected 1, got 2)",
|
143
|
-
request, response)
|
144
|
-
end
|
145
|
-
|
146
|
-
it "should raise error if quantity of registers is mismatch" do
|
147
|
-
request = "\x10\x0\x1\x0\x2\x4\x0\xa\x1\x2"
|
148
|
-
response = "\x10\x0\x2\x0\x1"
|
149
|
-
mock_query!(request, response)
|
150
|
-
|
151
|
-
lambda{ @slave.write_holding_registers(0x1,[0xa,0x102]) }.should raise_response_mismatch(
|
152
|
-
"Quantity is mismatch (expected 2, got 1)",
|
153
|
-
request, response)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
|
158
|
-
private
|
159
|
-
def mock_query!(request, response)
|
160
|
-
@slave.should_receive(:send_pdu).with(request)
|
161
|
-
@slave.should_receive(:read_pdu).and_return(response)
|
162
|
-
end
|
163
|
-
end
|
data/spec/rtu_client_spec.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
# -*- coding: ascii
|
2
|
-
require 'rmodbus'
|
3
|
-
|
4
|
-
describe ModBus::RTUClient do
|
5
|
-
before do
|
6
|
-
@sp = double('Serial port')
|
7
|
-
|
8
|
-
SerialPort.should_receive(:new).with("/dev/port1", 9600, 8, 1, 0).and_return(@sp)
|
9
|
-
SerialPort.stub(:public_method_defined?).with(:flush_input).and_return(true)
|
10
|
-
|
11
|
-
@sp.stub(:read_timeout=)
|
12
|
-
@sp.stub(:class).and_return(SerialPort)
|
13
|
-
@sp.should_receive(:flow_control=).with(SerialPort::NONE)
|
14
|
-
@sp.stub(:flush_input)
|
15
|
-
|
16
|
-
@cl = ModBus::RTUClient.new("/dev/port1", 9600, :data_bits => 8, :stop_bits => 1, :parity => SerialPort::NONE)
|
17
|
-
@slave = @cl.with_slave(1)
|
18
|
-
@slave.read_retries = 1
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should ignore frame with other UID" do
|
22
|
-
request = "\x10\x0\x1\x0\x1\x2\xff\xff"
|
23
|
-
@sp.should_receive(:write).with("\1#{request}\xA6\x31")
|
24
|
-
@sp.should_receive(:read).with(2).and_return("\x2\x10")
|
25
|
-
@sp.should_receive(:read).with(6).and_return("\x0\x1\x0\x1\x1C\x08")
|
26
|
-
lambda {@slave.query(request)}.should raise_error(ModBus::Errors::ModBusTimeout)
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should ignored frame with incorrect CRC" do
|
30
|
-
request = "\x10\x0\x1\x0\x1\x2\xff\xff"
|
31
|
-
@sp.should_receive(:write).with("\1#{request}\xA6\x31")
|
32
|
-
@sp.should_receive(:read).with(2).and_return("\x2\x10")
|
33
|
-
@sp.should_receive(:read).with(6).and_return("\x0\x1\x0\x1\x1C\x08")
|
34
|
-
lambda {@slave.query(request)}.should raise_error(ModBus::Errors::ModBusTimeout)
|
35
|
-
end
|
36
|
-
|
37
|
-
it "should return value of registers"do
|
38
|
-
request = stab_valid_request
|
39
|
-
@slave.query(request).should == "\xff\xff"
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'should sugar connect method' do
|
43
|
-
port, baud = "/dev/port1", 4800
|
44
|
-
SerialPort.should_receive(:new).with(port, baud, 8, 1, SerialPort::NONE).and_return(@sp)
|
45
|
-
@sp.should_receive(:closed?).and_return(false)
|
46
|
-
@sp.should_receive(:close)
|
47
|
-
@sp.should_receive(:flow_control=).with(SerialPort::NONE)
|
48
|
-
ModBus::RTUClient.connect(port, baud) do |cl|
|
49
|
-
cl.port.should == port
|
50
|
-
cl.baud.should == baud
|
51
|
-
cl.data_bits.should == 8
|
52
|
-
cl.stop_bits.should == 1
|
53
|
-
cl.parity.should == SerialPort::NONE
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'should have closed? method' do
|
58
|
-
@sp.should_receive(:closed?).and_return(false)
|
59
|
-
@cl.closed?.should == false
|
60
|
-
|
61
|
-
@sp.should_receive(:closed?).and_return(false)
|
62
|
-
@sp.should_receive(:close)
|
63
|
-
|
64
|
-
@cl.close
|
65
|
-
|
66
|
-
@sp.should_receive(:closed?).and_return(true)
|
67
|
-
@cl.closed?.should == true
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'should give slave object in block' do
|
71
|
-
@cl.with_slave(1) do |slave|
|
72
|
-
slave.uid = 1
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def stab_valid_request
|
77
|
-
request = "\x3\x0\x1\x0\x1"
|
78
|
-
@sp.should_receive(:write).with("\1#{request}\xd5\xca")
|
79
|
-
@sp.should_receive(:read).with(2).and_return("\x1\x3")
|
80
|
-
@sp.should_receive(:read).with(1).and_return("\x2")
|
81
|
-
@sp.should_receive(:read).with(4).and_return("\xff\xff\xb9\xf4")
|
82
|
-
|
83
|
-
request
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
data/spec/rtu_server_spec.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
# -*- coding: ascii
|
2
|
-
require 'rmodbus'
|
3
|
-
|
4
|
-
describe ModBus::RTUServer do
|
5
|
-
before do
|
6
|
-
@sp = double('SerialPort')
|
7
|
-
SerialPort.should_receive(:new).with('/dev/ttyS0', 4800, 7, 2, SerialPort::NONE).and_return(@sp)
|
8
|
-
@sp.stub(:read_timeout=)
|
9
|
-
@sp.should_receive(:flow_control=).with(SerialPort::NONE)
|
10
|
-
|
11
|
-
@server = ModBus::RTUServer.new('/dev/ttyS0', 4800, 1, :data_bits => 7, :stop_bits => 2)
|
12
|
-
@server.coils = [1,0,1,1]
|
13
|
-
@server.discrete_inputs = [1,1,0,0]
|
14
|
-
@server.holding_registers = [1,2,3,4]
|
15
|
-
@server.input_registers = [1,2,3,4]
|
16
|
-
end
|
17
|
-
|
18
|
-
it "should be valid initialized " do
|
19
|
-
@server.coils.should == [1,0,1,1]
|
20
|
-
@server.discrete_inputs.should == [1,1,0,0]
|
21
|
-
@server.holding_registers.should == [1,2,3,4]
|
22
|
-
@server.input_registers.should == [1,2,3,4]
|
23
|
-
|
24
|
-
@server.port.should == '/dev/ttyS0'
|
25
|
-
@server.baud.should == 4800
|
26
|
-
@server.data_bits.should == 7
|
27
|
-
@server.stop_bits.should == 2
|
28
|
-
@server.parity.should == SerialPort::NONE
|
29
|
-
end
|
30
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
# -*- coding: ascii
|
2
|
-
require 'rmodbus'
|
3
|
-
|
4
|
-
describe ModBus::RTUViaTCPClient do
|
5
|
-
describe "method 'query'" do
|
6
|
-
before do
|
7
|
-
@sock = double('Socket')
|
8
|
-
TCPSocket.should_receive(:new).with("127.0.0.1", 10002).and_return(@sock)
|
9
|
-
@sock.stub(:read_timeout=)
|
10
|
-
@sock.stub(:flush)
|
11
|
-
|
12
|
-
@cl = ModBus::RTUViaTCPClient.new("127.0.0.1")
|
13
|
-
@slave = @cl.with_slave(1)
|
14
|
-
@slave.read_retries = 1
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should ignore frame with other UID" do
|
18
|
-
request = "\x10\x0\x1\x0\x1\x2\xff\xff"
|
19
|
-
@sock.should_receive(:write).with("\1#{request}\xA6\x31")
|
20
|
-
@sock.should_receive(:read).with(2).and_return("\x2\x10")
|
21
|
-
@sock.should_receive(:read).with(6).and_return("\x0\x1\x0\x1\x1C\x08")
|
22
|
-
lambda {@slave.query(request)}.should raise_error(ModBus::Errors::ModBusTimeout)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "should ignored frame with incorrect CRC" do
|
26
|
-
request = "\x10\x0\x1\x0\x1\x2\xff\xff"
|
27
|
-
@sock.should_receive(:write).with("\1#{request}\xA6\x31")
|
28
|
-
@sock.should_receive(:read).with(2).and_return("\x2\x10")
|
29
|
-
@sock.should_receive(:read).with(6).and_return("\x0\x1\x0\x1\x1C\x08")
|
30
|
-
lambda {@slave.query(request)}.should raise_error(ModBus::Errors::ModBusTimeout)
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should return value of registers"do
|
34
|
-
request = "\x3\x0\x1\x0\x1"
|
35
|
-
@sock.should_receive(:write).with("\1#{request}\xd5\xca")
|
36
|
-
@sock.should_receive(:read).with(2).and_return("\x1\x3")
|
37
|
-
@sock.should_receive(:read).with(1).and_return("\x2")
|
38
|
-
@sock.should_receive(:read).with(4).and_return("\xff\xff\xb9\xf4")
|
39
|
-
@slave.query(request).should == "\xff\xff"
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'should sugar connect method' do
|
43
|
-
ipaddr, port = '127.0.0.1', 502
|
44
|
-
TCPSocket.should_receive(:new).with(ipaddr, port).and_return(@sock)
|
45
|
-
@sock.should_receive(:closed?).and_return(false)
|
46
|
-
@sock.should_receive(:close)
|
47
|
-
ModBus::RTUViaTCPClient.connect(ipaddr, port) do |cl|
|
48
|
-
cl.ipaddr.should == ipaddr
|
49
|
-
cl.port.should == port
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'should have closed? method' do
|
54
|
-
@sock.should_receive(:closed?).and_return(false)
|
55
|
-
@cl.closed?.should == false
|
56
|
-
|
57
|
-
@sock.should_receive(:closed?).and_return(false)
|
58
|
-
@sock.should_receive(:close)
|
59
|
-
|
60
|
-
@cl.close
|
61
|
-
|
62
|
-
@sock.should_receive(:closed?).and_return(true)
|
63
|
-
@cl.closed?.should == true
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'should give slave object in block' do
|
67
|
-
@cl.with_slave(1) do |slave|
|
68
|
-
slave.uid = 1
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
it "should tune connection timeout" do
|
74
|
-
lambda { ModBus::RTUViaTCPClient.new('81.123.231.11', 1999, :connect_timeout => 0.001) }.should raise_error(ModBus::Errors::ModBusTimeout)
|
75
|
-
end
|
76
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# -*- coding: ascii
|
2
|
-
require "rmodbus"
|
3
|
-
|
4
|
-
describe ModBus::RTUViaTCPServer do
|
5
|
-
it "should have options :host" do
|
6
|
-
host = '192.168.0.1'
|
7
|
-
srv = ModBus::RTUViaTCPServer.new(1010, 1, :host => '192.168.0.1')
|
8
|
-
srv.host.should eql(host)
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should have options :max_connection" do
|
12
|
-
max_conn = 5
|
13
|
-
srv = ModBus::RTUViaTCPServer.new(1010, 1, :max_connection => 5)
|
14
|
-
srv.maxConnections.should eql(max_conn)
|
15
|
-
end
|
16
|
-
end
|
data/spec/slave_spec.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
# -*- coding: ascii
|
2
|
-
require 'rmodbus'
|
3
|
-
|
4
|
-
describe ModBus::Slave do
|
5
|
-
before do
|
6
|
-
@slave = ModBus::Client.new.with_slave(1)
|
7
|
-
|
8
|
-
@slave.stub(:query).and_return('')
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should support function 'read coils'" do
|
12
|
-
@slave.should_receive(:query).with("\x1\x0\x13\x0\x13").and_return("\xcd\x6b\x5")
|
13
|
-
@slave.read_coils(0x13,0x13).should == [1,0,1,1, 0,0,1,1, 1,1,0,1, 0,1,1,0, 1,0,1]
|
14
|
-
end
|
15
|
-
|
16
|
-
it "should support function 'read discrete inputs'" do
|
17
|
-
@slave.should_receive(:query).with("\x2\x0\xc4\x0\x16").and_return("\xac\xdb\x35")
|
18
|
-
@slave.read_discrete_inputs(0xc4,0x16).should == [0,0,1,1, 0,1,0,1, 1,1,0,1, 1,0,1,1, 1,0,1,0, 1,1]
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should support function 'read holding registers'" do
|
22
|
-
@slave.should_receive(:query).with("\x3\x0\x6b\x0\x3").and_return("\x2\x2b\x0\x0\x0\x64")
|
23
|
-
@slave.read_holding_registers(0x6b,0x3).should == [0x022b, 0x0000, 0x0064]
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should support function 'read input registers'" do
|
27
|
-
@slave.should_receive(:query).with("\x4\x0\x8\x0\x1").and_return("\x0\xa")
|
28
|
-
@slave.read_input_registers(0x8,0x1).should == [0x000a]
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should support function 'write single coil'" do
|
32
|
-
@slave.should_receive(:query).with("\x5\x0\xac\xff\x0").and_return("\xac\xff\x00")
|
33
|
-
@slave.write_single_coil(0xac,0x1).should == @slave
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should support function 'write single register'" do
|
37
|
-
@slave.should_receive(:query).with("\x6\x0\x1\x0\x3").and_return("\x1\x0\x3")
|
38
|
-
@slave.write_single_register(0x1,0x3).should == @slave
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should support function 'write multiple coils'" do
|
42
|
-
@slave.should_receive(:query).with("\xf\x0\x13\x0\xa\x2\xcd\x1").and_return("\x13\x0\xa")
|
43
|
-
@slave.write_multiple_coils(0x13,[1,0,1,1, 0,0,1,1, 1,0]).should == @slave
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should support function 'write multiple registers'" do
|
47
|
-
@slave.should_receive(:query).with("\x10\x0\x1\x0\x3\x6\x0\xa\x1\x2\xf\xf").and_return("\x1\x0\x3")
|
48
|
-
@slave.write_multiple_registers(0x1,[0x000a,0x0102, 0xf0f]).should == @slave
|
49
|
-
end
|
50
|
-
|
51
|
-
it "should support function 'mask write register'" do
|
52
|
-
@slave.should_receive(:query).with("\x16\x0\x4\x0\xf2\x0\2").and_return("\x4\x0\xf2\x0\x2")
|
53
|
-
@slave.mask_write_register(0x4, 0xf2, 0x2).should == @slave
|
54
|
-
end
|
55
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
# -*- coding: ascii
|
2
|
-
require "rmodbus"
|
3
|
-
|
4
|
-
class RaiseResponseMismatch
|
5
|
-
def initialize(message, request, response)
|
6
|
-
@expected_message, @expected_request, @expected_response = message, request, response
|
7
|
-
end
|
8
|
-
|
9
|
-
def matches?(given_block)
|
10
|
-
begin
|
11
|
-
given_block.call
|
12
|
-
rescue ModBus::Errors::ResponseMismatch => e
|
13
|
-
@actual_message = e.message
|
14
|
-
@actual_request = e.request
|
15
|
-
@actual_response = e.response
|
16
|
-
|
17
|
-
@with_expected_message = verify_message
|
18
|
-
@with_expected_request = @expected_request == @actual_request
|
19
|
-
@with_expected_response = @expected_response == @actual_response
|
20
|
-
end
|
21
|
-
@with_expected_message & @with_expected_request & @with_expected_response
|
22
|
-
end
|
23
|
-
|
24
|
-
def failure_message
|
25
|
-
unless @with_expected_message
|
26
|
-
return "Expected message '#{@expected_message}', got '#{@actual_message}'"
|
27
|
-
end
|
28
|
-
|
29
|
-
unless @with_expected_request
|
30
|
-
return "Expected request #{logging_bytes @expected_request}, got #{logging_bytes @actual_request}"
|
31
|
-
end
|
32
|
-
|
33
|
-
unless @with_expected_response
|
34
|
-
return "Expected response #{logging_bytes @expected_response}, got #{logging_bytes @actual_response}"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def verify_message
|
39
|
-
case @expected_message
|
40
|
-
when nil
|
41
|
-
true
|
42
|
-
when Regexp
|
43
|
-
@expected_message =~ @actual_message
|
44
|
-
else
|
45
|
-
@expected_message == @actual_message
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
module RaiseResponseMatcher
|
51
|
-
def raise_response_mismatch(message, request, response)
|
52
|
-
RaiseResponseMismatch.new(message, request, response)
|
53
|
-
end
|
54
|
-
end
|