rmodbus 0.5.0 → 1.0.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.
Files changed (46) hide show
  1. data/NEWS.md +52 -0
  2. data/README.md +87 -0
  3. data/Rakefile +22 -36
  4. data/examples/perfomance_rtu.rb +35 -37
  5. data/examples/perfomance_tcp.rb +36 -38
  6. data/examples/use_rtu_via_tcp_modbus.rb +8 -5
  7. data/examples/use_tcp_modbus.rb +10 -6
  8. data/lib/rmodbus/client.rb +52 -174
  9. data/lib/rmodbus/common.rb +45 -18
  10. data/lib/rmodbus/{exceptions.rb → errors.rb} +3 -0
  11. data/lib/rmodbus/ext.rb +25 -2
  12. data/lib/rmodbus/proxy.rb +54 -0
  13. data/lib/rmodbus/{crc16.rb → rtu.rb} +73 -2
  14. data/lib/rmodbus/rtu_client.rb +20 -116
  15. data/lib/rmodbus/rtu_server.rb +28 -57
  16. data/lib/rmodbus/rtu_slave.rb +59 -0
  17. data/lib/rmodbus/rtu_via_tcp_client.rb +22 -86
  18. data/lib/rmodbus/rtu_via_tcp_server.rb +31 -95
  19. data/lib/rmodbus/rtu_via_tcp_slave.rb +58 -0
  20. data/lib/rmodbus/{parsers.rb → server.rb} +24 -15
  21. data/lib/rmodbus/slave.rb +268 -0
  22. data/lib/rmodbus/sp.rb +45 -0
  23. data/lib/rmodbus/tcp.rb +49 -0
  24. data/lib/rmodbus/tcp_client.rb +19 -88
  25. data/lib/rmodbus/tcp_server.rb +16 -19
  26. data/lib/rmodbus/tcp_slave.rb +64 -0
  27. data/lib/rmodbus/version.rb +17 -0
  28. data/lib/rmodbus.rb +20 -4
  29. data/spec/client_spec.rb +19 -45
  30. data/spec/exception_spec.rb +26 -27
  31. data/spec/ext_spec.rb +24 -1
  32. data/spec/logging_spec.rb +31 -37
  33. data/spec/proxy_spec.rb +73 -0
  34. data/spec/read_rtu_response_spec.rb +2 -4
  35. data/spec/rtu_client_spec.rb +17 -19
  36. data/spec/rtu_server_spec.rb +1 -3
  37. data/spec/rtu_via_tcp_client_spec.rb +69 -63
  38. data/spec/slave_spec.rb +55 -0
  39. data/spec/tcp_client_spec.rb +77 -69
  40. data/spec/tcp_server_spec.rb +34 -49
  41. metadata +123 -37
  42. data/AUTHORS +0 -3
  43. data/ChangeLog +0 -82
  44. data/LICENSE +0 -675
  45. data/README +0 -53
  46. data/examples/add_new_function.rb +0 -19
@@ -1,72 +1,78 @@
1
- begin
2
- require 'rubygems'
3
- rescue
4
- end
5
1
  require 'rmodbus'
6
-
7
2
  include ModBus
8
3
 
9
4
  describe RTUViaTCPClient do
5
+ describe "method 'query'" do
6
+ before do
7
+ @sock = mock('Socked')
8
+ TCPSocket.should_receive(:new).with("127.0.0.1", 10002).and_return(@sock)
9
+ @sock.stub!(:read_timeout=)
10
+ @sock.stub!(:read)
11
+
12
+ @cl = RTUViaTCPClient.new("127.0.0.1")
13
+ @slave = @cl.with_slave(1)
14
+ @slave.read_retries = 0
15
+ end
10
16
 
11
- before do
12
- @sock = mock('Socked')
13
- TCPSocket.should_receive(:new).with("127.0.0.1", 10002).and_return(@sock)
14
- @sock.stub!(:read_timeout=)
15
- @sock.stub!(:read)
16
-
17
- @mb_client = RTUViaTCPClient.new("127.0.0.1")
18
- @mb_client.read_retries = 0
19
- end
20
-
21
- it "should ignore frame with other UID" do
22
- request = "\x10\x0\x1\x0\x1\x2\xff\xff"
23
- @sock.should_receive(:write).with("\1#{request}\xA6\x31")
24
- @sock.should_receive(:read).with(2).and_return("\x2\x10")
25
- @sock.should_receive(:read).with(6).and_return("\x0\x1\x0\x1\x1C\x08")
26
- lambda {@mb_client.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
- @sock.should_receive(:write).with("\1#{request}\xA6\x31")
32
- @sock.should_receive(:read).with(2).and_return("\x2\x10")
33
- @sock.should_receive(:read).with(6).and_return("\x0\x1\x0\x1\x1C\x08")
34
- lambda {@mb_client.query(request)}.should raise_error(ModBus::Errors::ModBusTimeout)
35
- end
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
+ 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
36
72
 
37
- it "should return value of registers"do
38
- request = "\x3\x0\x1\x0\x1"
39
- @sock.should_receive(:write).with("\1#{request}\xd5\xca")
40
- @sock.should_receive(:read).with(2).and_return("\x1\x3")
41
- @sock.should_receive(:read).with(1).and_return("\x2")
42
- @sock.should_receive(:read).with(4).and_return("\xff\xff\xb9\xf4")
43
- @mb_client.query(request).should == "\xff\xff"
44
- end
45
-
46
- it 'should sugar connect method' do
47
- ipaddr, port, slave = '127.0.0.1', 502, 3
48
- TCPSocket.should_receive(:new).with(ipaddr, port).and_return(@sock)
49
- @sock.should_receive(:closed?).and_return(false)
50
- @sock.should_receive(:close)
51
- RTUViaTCPClient.connect(ipaddr, port, slave) do |cl|
52
- cl.ipaddr.should == ipaddr
53
- cl.port.should == port
54
- cl.slave.should == slave
73
+ it "should tune connection timeout" do
74
+ timeout(0.5) do
75
+ lambda { RTUViaTCPClient.new('81.123.231.11', 1999, :connect_timeout => 0.1) }.should raise_error(ModBusTimeout)
55
76
  end
56
77
  end
57
-
58
- it 'should have closed? method' do
59
- @sock.should_receive(:closed?).and_return(false)
60
- @mb_client.closed?.should == false
61
-
62
- @sock.should_receive(:closed?).and_return(false)
63
- @sock.should_receive(:close)
64
-
65
- @mb_client.close
66
-
67
- @sock.should_receive(:closed?).and_return(true)
68
- @mb_client.closed?.should == true
69
- end
70
-
71
78
  end
72
-
@@ -0,0 +1,55 @@
1
+ require 'rmodbus'
2
+ include ModBus
3
+
4
+ describe Slave do
5
+ before do
6
+ @slave = 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
@@ -1,73 +1,81 @@
1
- require 'rmodbus/tcp_client'
2
-
3
- include ModBus
4
-
5
- describe TCPClient, "method 'query'" do
6
-
7
- UID = 1
8
-
9
- before(:each) do
10
- @sock = mock("Socket")
11
- @adu = "\000\001\000\000\000\001\001"
12
-
13
- TCPSocket.should_receive(:new).with('127.0.0.1', 1502).and_return(@sock)
14
- @sock.stub!(:read).with(0).and_return('')
15
-
16
- @mb_client = TCPClient.new('127.0.0.1', 1502)
17
- end
18
-
19
- it 'should send valid MBAP Header' do
20
- @adu[0,2] = @mb_client.transaction.next.to_word
21
- @sock.should_receive(:write).with(@adu)
22
- @sock.should_receive(:read).with(7).and_return(@adu)
23
- @mb_client.query('').should == nil
24
- end
25
-
26
- it 'should throw exception if get other transaction' do
27
- @adu[0,2] = @mb_client.transaction.next.to_word
28
- @sock.should_receive(:write).with(@adu)
29
- @sock.should_receive(:read).with(7).and_return("\000\002\000\000\000\001" + UID.chr)
30
- begin
31
- @mb_client.query('').should == nil
32
- rescue Exception => ex
33
- ex.class.should == Errors::ModBusException
1
+ require 'rmodbus'
2
+
3
+ describe TCPClient do
4
+ describe "method 'query'" do
5
+ before(:each) do
6
+ @uid = 1
7
+ @sock = mock("Socket")
8
+ @adu = "\000\001\000\000\000\001\001"
9
+
10
+ TCPSocket.should_receive(:new).with('127.0.0.1', 1502).and_return(@sock)
11
+ @sock.stub!(:read).with(0).and_return('')
12
+ @cl = ModBus::TCPClient.new('127.0.0.1', 1502)
13
+ @slave = @cl.with_slave(@uid)
34
14
  end
35
- end
36
-
37
- it 'should return only data from PDU' do
38
- request = "\x3\x0\x6b\x0\x3"
39
- response = "\x3\x6\x2\x2b\x0\x0\x0\x64"
40
- @adu = @mb_client.transaction.next.to_word + "\x0\x0\x0\x9" + UID.chr + request
41
- @sock.should_receive(:write).with(@adu[0,4] + "\0\6" + UID.chr + request)
42
- @sock.should_receive(:read).with(7).and_return(@adu[0,7])
43
- @sock.should_receive(:read).with(8).and_return(response)
44
-
45
- @mb_client.query(request).should == response[2..-1]
46
- end
47
-
48
- it 'should sugar connect method' do
49
- ipaddr, port, slave = '127.0.0.1', 502, 3
50
- TCPSocket.should_receive(:new).with(ipaddr, port).and_return(@sock)
51
- @sock.should_receive(:closed?).and_return(false)
52
- @sock.should_receive(:close)
53
- TCPClient.connect(ipaddr, port, slave) do |cl|
54
- cl.ipaddr.should == ipaddr
55
- cl.port.should == port
56
- cl.slave.should == slave
15
+
16
+ it 'should send valid MBAP Header' do
17
+ @adu[0,2] = @slave.transaction.next.to_word
18
+ @sock.should_receive(:write).with(@adu)
19
+ @sock.should_receive(:read).with(7).and_return(@adu)
20
+ @slave.query('').should == nil
21
+ end
22
+
23
+ it 'should throw exception if get other transaction' do
24
+ @adu[0,2] = @slave.transaction.next.to_word
25
+ @sock.should_receive(:write).with(@adu)
26
+ @sock.should_receive(:read).with(7).and_return("\000\002\000\000\000\001" + @uid.chr)
27
+ begin
28
+ @slave.query('').should == nil
29
+ rescue Exception => ex
30
+ ex.class.should == Errors::ModBusException
31
+ end
32
+ end
33
+
34
+ it 'should return only data from PDU' do
35
+ request = "\x3\x0\x6b\x0\x3"
36
+ response = "\x3\x6\x2\x2b\x0\x0\x0\x64"
37
+ @adu = @slave.transaction.next.to_word + "\x0\x0\x0\x9" + @uid.chr + request
38
+ @sock.should_receive(:write).with(@adu[0,4] + "\0\6" + @uid.chr + request)
39
+ @sock.should_receive(:read).with(7).and_return(@adu[0,7])
40
+ @sock.should_receive(:read).with(8).and_return(response)
41
+
42
+ @slave.query(request).should == response[2..-1]
43
+ end
44
+
45
+ it 'should sugar connect method' do
46
+ ipaddr, port = '127.0.0.1', 502
47
+ TCPSocket.should_receive(:new).with(ipaddr, port).and_return(@sock)
48
+ @sock.should_receive(:closed?).and_return(false)
49
+ @sock.should_receive(:close)
50
+ TCPClient.connect(ipaddr, port) do |cl|
51
+ cl.ipaddr.should == ipaddr
52
+ cl.port.should == port
53
+ end
54
+ end
55
+
56
+ it 'should have closed? method' do
57
+ @sock.should_receive(:closed?).and_return(false)
58
+ @cl.closed?.should == false
59
+
60
+ @sock.should_receive(:closed?).and_return(false)
61
+ @sock.should_receive(:close)
62
+
63
+ @cl.close
64
+
65
+ @sock.should_receive(:closed?).and_return(true)
66
+ @cl.closed?.should == true
67
+ end
68
+
69
+ it 'should give slave object in block' do
70
+ @cl.with_slave(1) do |slave|
71
+ slave.uid = 1
72
+ end
73
+ end
74
+ end
75
+
76
+ it "should tune connection timeout" do
77
+ timeout(0.5) do
78
+ lambda { ModBus::TCPClient.new('81.123.231.11', 1999, :connect_timeout => 0.1) }.should raise_error(ModBusTimeout)
57
79
  end
58
80
  end
59
-
60
- it 'should have closed? method' do
61
- @sock.should_receive(:closed?).and_return(false)
62
- @mb_client.closed?.should == false
63
-
64
- @sock.should_receive(:closed?).and_return(false)
65
- @sock.should_receive(:close)
66
-
67
- @mb_client.close
68
-
69
- @sock.should_receive(:closed?).and_return(true)
70
- @mb_client.closed?.should == true
71
- end
72
-
73
81
  end
@@ -1,7 +1,6 @@
1
- require 'lib/rmodbus'
1
+ require 'rmodbus'
2
2
 
3
3
  describe TCPServer do
4
-
5
4
  before do
6
5
  @server = ModBus::TCPServer.new(8502,1)
7
6
  @server.coils = [1,0,1,1]
@@ -9,104 +8,90 @@ describe TCPServer do
9
8
  @server.holding_registers = [1,2,3,4]
10
9
  @server.input_registers = [1,2,3,4]
11
10
  @server.start
12
- @client = ModBus::TCPClient.new('127.0.0.1', 8502, 1)
13
- @client.read_retries = 0
11
+ @cl = ModBus::TCPClient.new('127.0.0.1', 8502)
12
+ @slave = @cl.with_slave(1)
13
+ @slave.read_retries = 0
14
14
  end
15
15
 
16
16
  it "should silent if UID has mismatched" do
17
- @client.close
18
- client = ModBus::TCPClient.new('127.0.0.1', 8502, 2)
19
- begin
20
- client.read_coils(1,3)
21
- rescue ModBus::Errors::ModBusException => ex
22
- ex.message.should == "Server did not respond"
17
+ @cl.close
18
+ ModBus::TCPClient.connect('127.0.0.1', 8502) do |cl|
19
+ lambda { cl.with_slave(2).read_coils(1,3) }.should raise_exception(
20
+ ModBus::Errors::ModBusException,
21
+ "Server did not respond"
22
+ )
23
23
  end
24
- client.close
25
- end
26
-
27
- it "should silent if protocol identifer has mismatched" do
28
- @client.close
29
- client = TCPSocket.new('127.0.0.1', 8502)
30
- begin
31
- client.write "\0\0\1\0\0\6\1"
32
- rescue ModBus::Errors::ModBusException => ex
33
- ex.message.should == "Server did not respond"
34
- end
35
- client.close
36
24
  end
37
25
 
38
26
  it "should send exception if function not supported" do
39
- begin
40
- @client.query('0x43')
41
- rescue ModBus::Errors::IllegalFunction => ex
42
- ex.message.should == "The function code received in the query is not an allowable action for the server"
43
- end
27
+ lambda { @slave.query('0x43') }.should raise_exception(
28
+ ModBus::Errors::IllegalFunction,
29
+ "The function code received in the query is not an allowable action for the server"
30
+ )
44
31
  end
45
32
 
46
33
  it "should send exception if quanity of out more 0x7d" do
47
- begin
48
- @client.read_coils(0, 0x7e)
49
- rescue ModBus::Errors::IllegalDataValue => ex
50
- ex.message.should == "A value contained in the query data field is not an allowable value for server"
51
- end
34
+ lambda { @slave.read_coils(0, 0x7e) }.should raise_exception(
35
+ ModBus::Errors::IllegalDataValue,
36
+ "A value contained in the query data field is not an allowable value for server"
37
+ )
52
38
  end
53
39
 
54
40
  it "should send exception if addr not valid" do
55
- begin
56
- @client.read_coils(2, 8)
57
- rescue ModBus::Errors::IllegalDataAddress => ex
58
- ex.message.should == "The data address received in the query is not an allowable address for the server"
59
- end
41
+ lambda { @slave.read_coils(2, 8) }.should raise_exception(
42
+ ModBus::Errors::IllegalDataAddress,
43
+ "The data address received in the query is not an allowable address for the server"
44
+ )
60
45
  end
61
46
 
62
47
  it "should calc a many requests" do
63
- @client.read_coils(1,2)
64
- @client.write_multiple_registers(0,[9,9,9,])
65
- @client.read_holding_registers(0,3).should == [9,9,9]
48
+ @slave.read_coils(1,2)
49
+ @slave.write_multiple_registers(0,[9,9,9,])
50
+ @slave.read_holding_registers(0,3).should == [9,9,9]
66
51
  end
67
52
 
68
53
  it "should supported function 'read coils'" do
69
- @client.read_coils(0,3).should == @server.coils[0,3]
54
+ @slave.read_coils(0,3).should == @server.coils[0,3]
70
55
  end
71
56
 
72
57
  it "should supported function 'read discrete inputs'" do
73
- @client.read_discrete_inputs(1,3).should == @server.discrete_inputs[1,3]
58
+ @slave.read_discrete_inputs(1,3).should == @server.discrete_inputs[1,3]
74
59
  end
75
60
 
76
61
  it "should supported function 'read holding registers'" do
77
- @client.read_holding_registers(0,3).should == @server.holding_registers[0,3]
62
+ @slave.read_holding_registers(0,3).should == @server.holding_registers[0,3]
78
63
  end
79
64
 
80
65
  it "should supported function 'read input registers'" do
81
- @client.read_input_registers(2,2).should == @server.input_registers[2,2]
66
+ @slave.read_input_registers(2,2).should == @server.input_registers[2,2]
82
67
  end
83
68
 
84
69
  it "should supported function 'write single coil'" do
85
70
  @server.coils[3] = 0
86
- @client.write_single_coil(3,1)
71
+ @slave.write_single_coil(3,1)
87
72
  @server.coils[3].should == 1
88
73
  end
89
74
 
90
75
  it "should supported function 'write single register'" do
91
76
  @server.holding_registers[3] = 25
92
- @client.write_single_register(3,35)
77
+ @slave.write_single_register(3,35)
93
78
  @server.holding_registers[3].should == 35
94
79
  end
95
80
 
96
81
  it "should supported function 'write multiple coils'" do
97
82
  @server.coils = [1,1,1,0, 0,0,0,0, 0,0,0,0, 0,1,1,1]
98
- @client.write_multiple_coils(3, [1, 0,1,0,1, 0,1,0,1])
83
+ @slave.write_multiple_coils(3, [1, 0,1,0,1, 0,1,0,1])
99
84
  @server.coils.should == [1,1,1,1, 0,1,0,1, 0,1,0,1, 0,1,1,1]
100
85
  end
101
86
 
102
87
  it "should supported function 'write multiple registers'" do
103
88
  @server.holding_registers = [1,2,3,4,5,6,7,8,9]
104
- @client.write_multiple_registers(3,[1,2,3,4,5])
89
+ @slave.write_multiple_registers(3,[1,2,3,4,5])
105
90
  @server.holding_registers.should == [1,2,3,1,2,3,4,5,9]
106
91
  end
107
92
 
108
93
  after do
109
- @client.close
94
+ @cl.close
110
95
  @server.stop unless @server.stopped?
111
96
  while GServer.in_service?(8502)
112
97
  end