rmodbus 1.0.4 → 1.1.0
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.
- data/NEWS.md +22 -5
- data/README.md +3 -23
- data/Rakefile +3 -1
- data/lib/rmodbus/client.rb +12 -0
- data/lib/rmodbus/{common.rb → debug.rb} +4 -6
- data/lib/rmodbus/errors.rb +9 -3
- data/lib/rmodbus/ext.rb +7 -1
- data/lib/rmodbus/options.rb +21 -0
- data/lib/rmodbus/rtu.rb +28 -0
- data/lib/rmodbus/rtu_server.rb +2 -3
- data/lib/rmodbus/rtu_slave.rb +3 -20
- data/lib/rmodbus/rtu_via_tcp_server.rb +1 -1
- data/lib/rmodbus/rtu_via_tcp_slave.rb +9 -25
- data/lib/rmodbus/slave.rb +67 -12
- data/lib/rmodbus/sp.rb +2 -3
- data/lib/rmodbus/tcp_server.rb +52 -54
- data/lib/rmodbus/version.rb +2 -2
- data/lib/rmodbus.rb +6 -3
- data/spec/client_spec.rb +54 -7
- data/spec/exception_spec.rb +13 -15
- data/spec/logging_spec.rb +7 -6
- data/spec/read_rtu_response_spec.rb +3 -4
- data/spec/response_mismach_spec.rb +162 -0
- data/spec/rtu_client_spec.rb +4 -5
- data/spec/rtu_server_spec.rb +3 -4
- data/spec/rtu_via_tcp_client_spec.rb +5 -8
- data/spec/slave_spec.rb +2 -3
- data/spec/spec_helper.rb +54 -0
- data/spec/tcp_client_spec.rb +4 -6
- data/spec/tcp_server_spec.rb +11 -11
- metadata +45 -14
data/lib/rmodbus.rb
CHANGED
@@ -11,7 +11,8 @@
|
|
11
11
|
# GNU General Public License for more details.
|
12
12
|
require 'rmodbus/errors'
|
13
13
|
require 'rmodbus/ext'
|
14
|
-
require 'rmodbus/
|
14
|
+
require 'rmodbus/debug'
|
15
|
+
require 'rmodbus/options'
|
15
16
|
require 'rmodbus/rtu'
|
16
17
|
require 'rmodbus/tcp'
|
17
18
|
require 'rmodbus/slave'
|
@@ -21,12 +22,14 @@ require 'rmodbus/tcp_slave'
|
|
21
22
|
require 'rmodbus/tcp_client'
|
22
23
|
require 'rmodbus/tcp_server'
|
23
24
|
|
24
|
-
|
25
|
-
|
25
|
+
begin
|
26
|
+
require 'serialport'
|
26
27
|
require 'rmodbus/sp'
|
27
28
|
require 'rmodbus/rtu_slave'
|
28
29
|
require 'rmodbus/rtu_client'
|
29
30
|
require 'rmodbus/rtu_server'
|
31
|
+
rescue Exception => e
|
32
|
+
warn "[WARNING] Install `serialport` gem for use RTU protocols"
|
30
33
|
end
|
31
34
|
|
32
35
|
require 'rmodbus/rtu_via_tcp_slave'
|
data/spec/client_spec.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
require 'rmodbus'
|
2
|
-
include ModBus
|
3
2
|
|
4
|
-
describe Client do
|
3
|
+
describe ModBus::Client do
|
5
4
|
before do
|
6
|
-
@cl = Client.new
|
5
|
+
@cl = ModBus::Client.new
|
7
6
|
end
|
8
7
|
|
9
8
|
it "should give object provider for slave" do
|
@@ -18,14 +17,62 @@ describe Client do
|
|
18
17
|
end
|
19
18
|
|
20
19
|
it "should connect with TCP server" do
|
21
|
-
Client.connect do |cl|
|
22
|
-
cl.should be_instance_of(Client)
|
20
|
+
ModBus::Client.connect do |cl|
|
21
|
+
cl.should be_instance_of(ModBus::Client)
|
23
22
|
end
|
24
23
|
end
|
25
24
|
|
26
25
|
it ":new alias :connect" do
|
27
|
-
Client.new do |cl|
|
28
|
-
cl.should be_instance_of(Client)
|
26
|
+
ModBus::Client.new do |cl|
|
27
|
+
cl.should be_instance_of(ModBus::Client)
|
29
28
|
end
|
30
29
|
end
|
30
|
+
|
31
|
+
it 'should common for all slaves :debug flag' do
|
32
|
+
@cl.debug = true
|
33
|
+
@cl.with_slave(1) do |slave_1|
|
34
|
+
slave_1.debug.should be_true
|
35
|
+
end
|
36
|
+
@cl.with_slave(2) do |slave_2|
|
37
|
+
slave_2.debug = false
|
38
|
+
slave_2.debug.should be_false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should common for all slaves :raise_exception_on_mismatch flag' do
|
43
|
+
@cl.raise_exception_on_mismatch = true
|
44
|
+
@cl.with_slave(1) do |slave_1|
|
45
|
+
slave_1.raise_exception_on_mismatch.should be_true
|
46
|
+
end
|
47
|
+
|
48
|
+
@cl.with_slave(2) do |slave_2|
|
49
|
+
slave_2.raise_exception_on_mismatch = false
|
50
|
+
slave_2.raise_exception_on_mismatch.should be_false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should common for all slaves :read_retries options' do
|
55
|
+
@cl.read_retries = 5
|
56
|
+
@cl.with_slave(1) do |slave_1|
|
57
|
+
slave_1.read_retries.should eql(5)
|
58
|
+
end
|
59
|
+
|
60
|
+
@cl.with_slave(2) do |slave_2|
|
61
|
+
slave_2.read_retries = 15
|
62
|
+
slave_2.read_retries.should eql(15)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should common for all slaves :read_retry_timeout options' do
|
67
|
+
@cl.read_retry_timeout = 5
|
68
|
+
@cl.with_slave(1) do |slave_1|
|
69
|
+
slave_1.read_retry_timeout.should eql(5)
|
70
|
+
end
|
71
|
+
|
72
|
+
@cl.with_slave(2) do |slave_2|
|
73
|
+
slave_2.read_retry_timeout = 15
|
74
|
+
slave_2.read_retry_timeout.should eql(15)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
31
78
|
end
|
data/spec/exception_spec.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
require 'rmodbus'
|
2
2
|
|
3
|
-
include ModBus::Errors
|
4
|
-
|
5
3
|
describe ModBus::TCPClient do
|
6
4
|
before(:all) do
|
7
5
|
@srv = ModBus::TCPServer.new(1502, 1)
|
@@ -11,7 +9,7 @@ describe ModBus::TCPClient do
|
|
11
9
|
@srv.input_registers = [0] * 8
|
12
10
|
@srv.start
|
13
11
|
|
14
|
-
@cl = TCPClient.new('127.0.0.1', 1502)
|
12
|
+
@cl = ModBus::TCPClient.new('127.0.0.1', 1502)
|
15
13
|
@slave = @cl.with_slave(1)
|
16
14
|
end
|
17
15
|
|
@@ -21,11 +19,11 @@ describe ModBus::TCPClient do
|
|
21
19
|
end
|
22
20
|
|
23
21
|
it "should raise exception if illegal data address" do
|
24
|
-
lambda { @slave.read_coils(501, 34) }.should raise_error(IllegalDataAddress)
|
22
|
+
lambda { @slave.read_coils(501, 34) }.should raise_error(ModBus::Errors::IllegalDataAddress)
|
25
23
|
end
|
26
24
|
|
27
25
|
it "should raise exception if too many data" do
|
28
|
-
lambda { @slave.read_coils(0, 0x07D1) }.should raise_error(IllegalDataValue)
|
26
|
+
lambda { @slave.read_coils(0, 0x07D1) }.should raise_error(ModBus::Errors::IllegalDataValue)
|
29
27
|
end
|
30
28
|
|
31
29
|
# Read input status
|
@@ -34,11 +32,11 @@ describe ModBus::TCPClient do
|
|
34
32
|
end
|
35
33
|
|
36
34
|
it "should raise exception if illegal data address" do
|
37
|
-
lambda { @slave.read_discrete_inputs(50, 23) }.should raise_error(IllegalDataAddress)
|
35
|
+
lambda { @slave.read_discrete_inputs(50, 23) }.should raise_error(ModBus::Errors::IllegalDataAddress)
|
38
36
|
end
|
39
37
|
|
40
38
|
it "should raise exception if too many data" do
|
41
|
-
lambda { @slave.read_discrete_inputs(0, 0x07D1) }.should raise_error(IllegalDataValue)
|
39
|
+
lambda { @slave.read_discrete_inputs(0, 0x07D1) }.should raise_error(ModBus::Errors::IllegalDataValue)
|
42
40
|
end
|
43
41
|
|
44
42
|
# Read holding registers
|
@@ -47,12 +45,12 @@ describe ModBus::TCPClient do
|
|
47
45
|
end
|
48
46
|
|
49
47
|
it "should raise exception if illegal data address" do
|
50
|
-
lambda { @slave.read_holding_registers(402, 99) }.should raise_error(IllegalDataAddress)
|
48
|
+
lambda { @slave.read_holding_registers(402, 99) }.should raise_error(ModBus::Errors::IllegalDataAddress)
|
51
49
|
end
|
52
50
|
|
53
51
|
|
54
52
|
it "should raise exception if too many data" do
|
55
|
-
lambda { @slave.read_holding_registers(0, 0x007E) }.should raise_error(IllegalDataValue)
|
53
|
+
lambda { @slave.read_holding_registers(0, 0x007E) }.should raise_error(ModBus::Errors::IllegalDataValue)
|
56
54
|
end
|
57
55
|
|
58
56
|
# Read input registers
|
@@ -61,11 +59,11 @@ describe ModBus::TCPClient do
|
|
61
59
|
end
|
62
60
|
|
63
61
|
it "should raise exception if illegal data address" do
|
64
|
-
lambda { @slave.read_input_registers(402, 9) }.should raise_error(IllegalDataAddress)
|
62
|
+
lambda { @slave.read_input_registers(402, 9) }.should raise_error(ModBus::Errors::IllegalDataAddress)
|
65
63
|
end
|
66
64
|
|
67
65
|
it "should raise exception if too many data" do
|
68
|
-
lambda { @slave.read_input_registers(0, 0x007E) }.should raise_error(IllegalDataValue)
|
66
|
+
lambda { @slave.read_input_registers(0, 0x007E) }.should raise_error(ModBus::Errors::IllegalDataValue)
|
69
67
|
end
|
70
68
|
|
71
69
|
# Force single coil
|
@@ -75,7 +73,7 @@ describe ModBus::TCPClient do
|
|
75
73
|
end
|
76
74
|
|
77
75
|
it "should raise exception if illegal data address" do
|
78
|
-
lambda { @slave.write_single_coil(501, true) }.should raise_error(IllegalDataAddress)
|
76
|
+
lambda { @slave.write_single_coil(501, true) }.should raise_error(ModBus::Errors::IllegalDataAddress)
|
79
77
|
end
|
80
78
|
|
81
79
|
# Preset single register
|
@@ -85,7 +83,7 @@ describe ModBus::TCPClient do
|
|
85
83
|
end
|
86
84
|
|
87
85
|
it "should raise exception if illegal data address" do
|
88
|
-
lambda { @slave.write_single_register(501, 0x0AA0) }.should raise_error(IllegalDataAddress)
|
86
|
+
lambda { @slave.write_single_register(501, 0x0AA0) }.should raise_error(ModBus::Errors::IllegalDataAddress)
|
89
87
|
end
|
90
88
|
|
91
89
|
# Force multiple coils
|
@@ -95,7 +93,7 @@ describe ModBus::TCPClient do
|
|
95
93
|
end
|
96
94
|
|
97
95
|
it "should raise exception if illegal data address" do
|
98
|
-
lambda { @slave.write_multiple_coils(501, [1,0]) }.should raise_error(IllegalDataAddress)
|
96
|
+
lambda { @slave.write_multiple_coils(501, [1,0]) }.should raise_error(ModBus::Errors::IllegalDataAddress)
|
99
97
|
end
|
100
98
|
|
101
99
|
# Preset multiple registers
|
@@ -105,7 +103,7 @@ describe ModBus::TCPClient do
|
|
105
103
|
end
|
106
104
|
|
107
105
|
it "should raise exception if illegal data address" do
|
108
|
-
lambda { @slave.write_multiple_registers(501, [1, 2]) }.should raise_error(IllegalDataAddress)
|
106
|
+
lambda { @slave.write_multiple_registers(501, [1, 2]) }.should raise_error(ModBus::Errors::IllegalDataAddress)
|
109
107
|
end
|
110
108
|
|
111
109
|
after(:all) do
|
data/spec/logging_spec.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'rmodbus'
|
2
|
-
include ModBus
|
3
2
|
|
4
|
-
describe TCPClient do
|
3
|
+
describe ModBus::TCPClient do
|
5
4
|
before(:each) do
|
6
5
|
@uid = 1
|
7
6
|
@sock = mock("Socket")
|
@@ -10,7 +9,7 @@ describe TCPClient do
|
|
10
9
|
TCPSocket.should_receive(:new).with('127.0.0.1', 1502).and_return(@sock)
|
11
10
|
@sock.stub!(:read).with(0).and_return('')
|
12
11
|
|
13
|
-
@slave = TCPClient.new('127.0.0.1', 1502).with_slave(@uid)
|
12
|
+
@slave = ModBus::TCPClient.new('127.0.0.1', 1502).with_slave(@uid)
|
14
13
|
end
|
15
14
|
|
16
15
|
it 'should log rec\send bytes' do
|
@@ -36,15 +35,16 @@ describe TCPClient do
|
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
39
|
-
|
40
|
-
|
38
|
+
begin
|
39
|
+
require "serialport"
|
40
|
+
describe ModBus::RTUClient do
|
41
41
|
before do
|
42
42
|
@sp = mock('Serial port')
|
43
43
|
SerialPort.should_receive(:new).with("/dev/port1", 9600, 7, 2, SerialPort::ODD).and_return(@sp)
|
44
44
|
|
45
45
|
@sp.stub!(:read_timeout=)
|
46
46
|
|
47
|
-
@slave = RTUClient.new("/dev/port1", 9600, :data_bits => 7, :stop_bits => 2, :parity => SerialPort::ODD).with_slave(1)
|
47
|
+
@slave = ModBus::RTUClient.new("/dev/port1", 9600, :data_bits => 7, :stop_bits => 2, :parity => SerialPort::ODD).with_slave(1)
|
48
48
|
@slave.read_retries = 0
|
49
49
|
end
|
50
50
|
|
@@ -62,4 +62,5 @@ unless RUBY_PLATFORM == "java"
|
|
62
62
|
@slave.query(request).should == "\xff\xff"
|
63
63
|
end
|
64
64
|
end
|
65
|
+
rescue LoadError
|
65
66
|
end
|
@@ -1,9 +1,8 @@
|
|
1
1
|
require 'rmodbus'
|
2
|
-
include ModBus
|
3
2
|
|
4
3
|
#Use public wrap method
|
5
|
-
class Client
|
6
|
-
include RTU
|
4
|
+
class ModBus::Client
|
5
|
+
include ModBus::RTU
|
7
6
|
def test_read_method(msg)
|
8
7
|
io = TestIO.new(msg)
|
9
8
|
read_rtu_response(io)
|
@@ -25,7 +24,7 @@ end
|
|
25
24
|
|
26
25
|
describe "#read_rtu_response" do
|
27
26
|
before do
|
28
|
-
@cl_mb = Client.new
|
27
|
+
@cl_mb = ModBus::Client.new
|
29
28
|
end
|
30
29
|
|
31
30
|
it "should read response for 'read coils'" do
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "response mismach" do
|
4
|
+
include RaiseResponseMatcher
|
5
|
+
before(:each) do
|
6
|
+
@slave = ModBus::Slave.new(1, nil)
|
7
|
+
@slave.raise_exception_on_mismatch = true
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should raise error if function code is mismatch" do
|
11
|
+
request = "\x1\x0\x13\x0\x12"
|
12
|
+
response = "\x2\x3\xcd\xb6\x5"
|
13
|
+
mock_query!(request, response)
|
14
|
+
|
15
|
+
lambda{ @slave.read_coils(0x13,0x12) }.should raise_response_mismatch(
|
16
|
+
"Function code is mismatch (expected 1, got 2)",
|
17
|
+
request, response)
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "read coils" do
|
21
|
+
it "should raise error if count of byte is mismatch" do
|
22
|
+
request = "\x1\x0\x13\x0\x12"
|
23
|
+
response = "\x1\x2\xcd\xb6"
|
24
|
+
mock_query!(request, response)
|
25
|
+
|
26
|
+
lambda{ @slave.read_coils(0x13,0x12) }.should raise_response_mismatch(
|
27
|
+
"Byte count is mismatch (expected 3, got 2 bytes)",
|
28
|
+
request, response)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "read discrete inputs" do
|
33
|
+
it "should raise error if count of byte is mismatch" do
|
34
|
+
request = "\x2\x0\x13\x0\x12"
|
35
|
+
response = "\x2\x2\xcd\xb6"
|
36
|
+
mock_query!(request, response)
|
37
|
+
|
38
|
+
lambda{ @slave.read_discrete_inputs(0x13,0x12) }.should raise_response_mismatch(
|
39
|
+
"Byte count is mismatch (expected 3, got 2 bytes)",
|
40
|
+
request, response)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "read holding registesrs" do
|
45
|
+
it "should raise error if count of registers is mismatch" do
|
46
|
+
request = "\x3\x0\x8\x0\x1"
|
47
|
+
response = "\x3\x4\x0\xa\x0\xb"
|
48
|
+
mock_query!(request, response)
|
49
|
+
|
50
|
+
lambda{ @slave.read_holding_registers(0x8,0x1) }.should raise_response_mismatch(
|
51
|
+
"Register count is mismatch (expected 1, got 2 regs)",
|
52
|
+
request, response)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "read input registesrs" do
|
57
|
+
it "should raise error if count of registers is mismatch" do
|
58
|
+
request = "\x4\x0\x8\x0\x2"
|
59
|
+
response = "\x4\x2\xa\x0"
|
60
|
+
mock_query!(request, response)
|
61
|
+
|
62
|
+
lambda{ @slave.read_input_registers(0x8,0x2) }.should raise_response_mismatch(
|
63
|
+
"Register count is mismatch (expected 2, got 1 regs)",
|
64
|
+
request, response)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "write single coil" do
|
69
|
+
it "should raise error if address of coil is mismatch" do
|
70
|
+
request = "\x5\x0\x8\xff\x0"
|
71
|
+
response = "\x5\x0\x9\xff\x0"
|
72
|
+
mock_query!(request, response)
|
73
|
+
|
74
|
+
lambda{ @slave.write_coil(8,true) }.should raise_response_mismatch(
|
75
|
+
"Address is mismatch (expected 8, got 9)",
|
76
|
+
request, response)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should raise error if value of coil is mismatch" do
|
80
|
+
request = "\x5\x0\x8\xff\x0"
|
81
|
+
response = "\x5\x0\x8\x0\x0"
|
82
|
+
mock_query!(request, response)
|
83
|
+
|
84
|
+
lambda{ @slave.write_coil(8,true) }.should raise_response_mismatch(
|
85
|
+
"Value is mismatch (expected 0xff00, got 0x0)",
|
86
|
+
request, response)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "write single register" do
|
91
|
+
it "should raise error if address of register is mismatch" do
|
92
|
+
request = "\x6\x0\x8\xa\xb"
|
93
|
+
response = "\x6\x0\x9\xa\xb"
|
94
|
+
mock_query!(request, response)
|
95
|
+
|
96
|
+
lambda{ @slave.write_single_register(8,0x0a0b) }.should raise_response_mismatch(
|
97
|
+
"Address is mismatch (expected 8, got 9)",
|
98
|
+
request, response)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should raise error if value of register is mismatch" do
|
102
|
+
request = "\x6\x0\x8\xa\xb"
|
103
|
+
response = "\x6\x0\x8\x9\xb"
|
104
|
+
mock_query!(request, response)
|
105
|
+
|
106
|
+
lambda{ @slave.write_single_register(8,0x0a0b) }.should raise_response_mismatch(
|
107
|
+
"Value is mismatch (expected 0xa0b, got 0x90b)",
|
108
|
+
request, response)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "write multiple coils" do
|
113
|
+
it "should raise error if address of first coil is mismatch" do
|
114
|
+
request = "\xf\x0\x13\x0\xa\2\xcd\x01"
|
115
|
+
response = "\xf\x0\x14\x0\xa"
|
116
|
+
mock_query!(request, response)
|
117
|
+
|
118
|
+
lambda{ @slave.write_coils(0x13,[1,0,1,1, 0,0,1,1, 1,0]) }.should raise_response_mismatch(
|
119
|
+
"Address is mismatch (expected 19, got 20)",
|
120
|
+
request, response)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should raise error if quantity of coils is mismatch" do
|
124
|
+
request = "\xf\x0\x13\x0\xa\2\xcd\x01"
|
125
|
+
response = "\xf\x0\x13\x0\x9"
|
126
|
+
mock_query!(request, response)
|
127
|
+
|
128
|
+
lambda{ @slave.write_coils(0x13,[1,0,1,1, 0,0,1,1, 1,0]) }.should raise_response_mismatch(
|
129
|
+
"Quantity is mismatch (expected 10, got 9)",
|
130
|
+
request, response)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "write multiple registers" do
|
135
|
+
it "should raise error if address of first register is mismatch" do
|
136
|
+
request = "\x10\x0\x1\x0\x2\x4\x0\xa\x1\x2"
|
137
|
+
response = "\x10\x0\x2\x0\x2"
|
138
|
+
mock_query!(request, response)
|
139
|
+
|
140
|
+
lambda{ @slave.write_holding_registers(0x1,[0xa,0x102]) }.should raise_response_mismatch(
|
141
|
+
"Address is mismatch (expected 1, got 2)",
|
142
|
+
request, response)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should raise error if quantity of registers is mismatch" do
|
146
|
+
request = "\x10\x0\x1\x0\x2\x4\x0\xa\x1\x2"
|
147
|
+
response = "\x10\x0\x2\x0\x1"
|
148
|
+
mock_query!(request, response)
|
149
|
+
|
150
|
+
lambda{ @slave.write_holding_registers(0x1,[0xa,0x102]) }.should raise_response_mismatch(
|
151
|
+
"Quantity is mismatch (expected 2, got 1)",
|
152
|
+
request, response)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
private
|
158
|
+
def mock_query!(request, response)
|
159
|
+
@slave.should_receive(:send_pdu).with(request)
|
160
|
+
@slave.should_receive(:read_pdu).and_return(response)
|
161
|
+
end
|
162
|
+
end
|
data/spec/rtu_client_spec.rb
CHANGED
@@ -1,16 +1,15 @@
|
|
1
1
|
require 'rmodbus'
|
2
|
-
include ModBus
|
3
2
|
|
4
|
-
describe RTUClient do
|
3
|
+
describe ModBus::RTUClient do
|
5
4
|
before do
|
6
5
|
@sp = mock('Serial port')
|
7
6
|
SerialPort.should_receive(:new).with("/dev/port1", 9600, 8, 1, 0).and_return(@sp)
|
8
7
|
@sp.stub!(:read_timeout=)
|
9
8
|
@sp.stub!(:read)
|
10
9
|
|
11
|
-
@cl = RTUClient.new("/dev/port1", 9600, :data_bits => 8, :stop_bits => 1, :parity => SerialPort::NONE)
|
10
|
+
@cl = ModBus::RTUClient.new("/dev/port1", 9600, :data_bits => 8, :stop_bits => 1, :parity => SerialPort::NONE)
|
12
11
|
@slave = @cl.with_slave(1)
|
13
|
-
@slave.read_retries =
|
12
|
+
@slave.read_retries = 1
|
14
13
|
end
|
15
14
|
|
16
15
|
it "should ignore frame with other UID" do
|
@@ -43,7 +42,7 @@ describe RTUClient do
|
|
43
42
|
SerialPort.should_receive(:new).with(port, baud, 8, 1, SerialPort::NONE).and_return(@sp)
|
44
43
|
@sp.should_receive(:closed?).and_return(false)
|
45
44
|
@sp.should_receive(:close)
|
46
|
-
RTUClient.connect(port, baud) do |cl|
|
45
|
+
ModBus::RTUClient.connect(port, baud) do |cl|
|
47
46
|
cl.port.should == port
|
48
47
|
cl.baud.should == baud
|
49
48
|
cl.data_bits.should == 8
|
data/spec/rtu_server_spec.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
require 'rmodbus'
|
2
|
-
include ModBus
|
3
2
|
|
4
|
-
describe RTUServer do
|
3
|
+
describe ModBus::RTUServer do
|
5
4
|
before do
|
6
5
|
@sp = mock "SerialPort"
|
7
6
|
SerialPort.should_receive(:new).with('/dev/ttyS0', 4800, 7, 2, SerialPort::NONE).and_return(@sp)
|
8
7
|
@sp.stub!(:read_timeout=)
|
9
8
|
|
10
|
-
@server = RTUServer.new('/dev/ttyS0', 4800, 1, :data_bits => 7, :stop_bits => 2)
|
9
|
+
@server = ModBus::RTUServer.new('/dev/ttyS0', 4800, 1, :data_bits => 7, :stop_bits => 2)
|
11
10
|
@server.coils = [1,0,1,1]
|
12
11
|
@server.discrete_inputs = [1,1,0,0]
|
13
12
|
@server.holding_registers = [1,2,3,4]
|
@@ -26,4 +25,4 @@ describe RTUServer do
|
|
26
25
|
@server.stop_bits.should == 2
|
27
26
|
@server.parity.should == SerialPort::NONE
|
28
27
|
end
|
29
|
-
end
|
28
|
+
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'rmodbus'
|
2
|
-
include ModBus
|
3
2
|
|
4
|
-
describe RTUViaTCPClient do
|
3
|
+
describe ModBus::RTUViaTCPClient do
|
5
4
|
describe "method 'query'" do
|
6
5
|
before do
|
7
6
|
@sock = mock('Socked')
|
@@ -9,9 +8,9 @@ describe RTUViaTCPClient do
|
|
9
8
|
@sock.stub!(:read_timeout=)
|
10
9
|
@sock.stub!(:read)
|
11
10
|
|
12
|
-
@cl = RTUViaTCPClient.new("127.0.0.1")
|
11
|
+
@cl = ModBus::RTUViaTCPClient.new("127.0.0.1")
|
13
12
|
@slave = @cl.with_slave(1)
|
14
|
-
@slave.read_retries =
|
13
|
+
@slave.read_retries = 1
|
15
14
|
end
|
16
15
|
|
17
16
|
it "should ignore frame with other UID" do
|
@@ -44,7 +43,7 @@ describe RTUViaTCPClient do
|
|
44
43
|
TCPSocket.should_receive(:new).with(ipaddr, port).and_return(@sock)
|
45
44
|
@sock.should_receive(:closed?).and_return(false)
|
46
45
|
@sock.should_receive(:close)
|
47
|
-
RTUViaTCPClient.connect(ipaddr, port) do |cl|
|
46
|
+
ModBus::RTUViaTCPClient.connect(ipaddr, port) do |cl|
|
48
47
|
cl.ipaddr.should == ipaddr
|
49
48
|
cl.port.should == port
|
50
49
|
end
|
@@ -71,8 +70,6 @@ describe RTUViaTCPClient do
|
|
71
70
|
end
|
72
71
|
|
73
72
|
it "should tune connection timeout" do
|
74
|
-
|
75
|
-
lambda { RTUViaTCPClient.new('81.123.231.11', 1999, :connect_timeout => 0.1) }.should raise_error(ModBusTimeout)
|
76
|
-
end
|
73
|
+
lambda { ModBus::RTUViaTCPClient.new('81.123.231.11', 1999, :connect_timeout => 0.001) }.should raise_error(ModBus::Errors::ModBusTimeout)
|
77
74
|
end
|
78
75
|
end
|
data/spec/slave_spec.rb
CHANGED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require "rmodbus"
|
2
|
+
|
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
|
data/spec/tcp_client_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'rmodbus'
|
2
2
|
|
3
|
-
describe TCPClient do
|
3
|
+
describe ModBus::TCPClient do
|
4
4
|
describe "method 'query'" do
|
5
5
|
before(:each) do
|
6
6
|
@uid = 1
|
@@ -27,7 +27,7 @@ describe TCPClient do
|
|
27
27
|
begin
|
28
28
|
@slave.query('').should == nil
|
29
29
|
rescue Exception => ex
|
30
|
-
ex.class.should == Errors::ModBusException
|
30
|
+
ex.class.should == ModBus::Errors::ModBusException
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -47,7 +47,7 @@ describe TCPClient do
|
|
47
47
|
TCPSocket.should_receive(:new).with(ipaddr, port).and_return(@sock)
|
48
48
|
@sock.should_receive(:closed?).and_return(false)
|
49
49
|
@sock.should_receive(:close)
|
50
|
-
TCPClient.connect(ipaddr, port) do |cl|
|
50
|
+
ModBus::TCPClient.connect(ipaddr, port) do |cl|
|
51
51
|
cl.ipaddr.should == ipaddr
|
52
52
|
cl.port.should == port
|
53
53
|
end
|
@@ -74,8 +74,6 @@ describe TCPClient do
|
|
74
74
|
end
|
75
75
|
|
76
76
|
it "should tune connection timeout" do
|
77
|
-
|
78
|
-
lambda { ModBus::TCPClient.new('81.123.231.11', 1999, :connect_timeout => 0.1) }.should raise_error(ModBus::Errors::ModBusTimeout)
|
79
|
-
end
|
77
|
+
lambda { ModBus::TCPClient.new('81.123.231.11', 1999, :connect_timeout => 0.001) }.should raise_error(ModBus::Errors::ModBusTimeout)
|
80
78
|
end
|
81
79
|
end
|
data/spec/tcp_server_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require "rmodbus"
|
2
2
|
|
3
|
-
describe TCPServer do
|
3
|
+
describe ModBus::TCPServer do
|
4
4
|
before do
|
5
5
|
@server = ModBus::TCPServer.new(8502,1)
|
6
6
|
@server.coils = [1,0,1,1]
|
@@ -10,17 +10,15 @@ describe TCPServer do
|
|
10
10
|
@server.start
|
11
11
|
@cl = ModBus::TCPClient.new('127.0.0.1', 8502)
|
12
12
|
@slave = @cl.with_slave(1)
|
13
|
-
@slave.read_retries =
|
13
|
+
@slave.read_retries = 1
|
14
14
|
end
|
15
15
|
|
16
16
|
it "should silent if UID has mismatched" do
|
17
|
-
@cl.
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
)
|
23
|
-
end
|
17
|
+
@cl.with_slave(2).read_coils(1,3)
|
18
|
+
#lambda { @cl.with_slave(2).read_coils(1,3) }.should raise_exception(
|
19
|
+
# ModBus::Errors::ModBusException,
|
20
|
+
# "Server did not respond"
|
21
|
+
#)
|
24
22
|
end
|
25
23
|
|
26
24
|
it "should send exception if function not supported" do
|
@@ -103,9 +101,11 @@ describe TCPServer do
|
|
103
101
|
end
|
104
102
|
|
105
103
|
after do
|
106
|
-
@cl.close
|
104
|
+
@cl.close unless @cl.closed?
|
107
105
|
@server.stop unless @server.stopped?
|
108
106
|
while GServer.in_service?(8502)
|
107
|
+
sleep(0.01)
|
109
108
|
end
|
109
|
+
@server.stop
|
110
110
|
end
|
111
111
|
end
|