rmodbus 0.5.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
data/NEWS.md ADDED
@@ -0,0 +1,52 @@
1
+ Release 1.0.0
2
+ =====================================
3
+ New API for client part of library
4
+ ---------------------------------------
5
+
6
+ Example:
7
+
8
+ require 'rmodbus'
9
+
10
+ ModBus::TCPClient.new('127.0.0.1', 8502) do |cl|
11
+ cl.with_slave(1) do |slave|
12
+ # Read a single holding register at address 16
13
+ slave.holding_registers[16]
14
+
15
+ # Write a single holding register at address 16
16
+ slave.holding_registers[16] = 123
17
+
18
+ # Read holding registers 16 through 20
19
+ slave.holding_registers[16..20]
20
+
21
+ # Write holding registers 16 through 20 with some values
22
+ slave.holding_registers[16..20] = [1, 2, 3, 4, 5]
23
+ end
24
+ end
25
+
26
+ for more information [see](http://rdoc.info/gems/rmodbus/1.0.0/frames)
27
+
28
+ Conversion to/from 32bit registers
29
+ -----------------------------------
30
+
31
+ Some modbus devices use two registers to store 32bit values.
32
+ RModbus provides some helper functions to go back and forth between these two things when reading/writing.
33
+ The built-in examples assume registers in a particular order but it's trivial to change.
34
+
35
+ # Reading values in multiple registers (you can read more than 2 and convert them all so long as they are in multiples of 2)
36
+ res = slave.holding_registers[0..1]
37
+ res.inspect => [20342, 17344]
38
+ res.to_32i => [1136676726]
39
+ res.to_32f => [384.620788574219]
40
+
41
+ # Writing 32b values to multiple registers
42
+ cl.holding_registers[0..1] = [1136676726].from_32i
43
+ cl.holding_registers[0..1] => [20342, 17344]
44
+ cl.holding_registers[2..3] = [384.620788574219].from_32f
45
+ cl.holding_registers[2..3] => [20342, 17344]
46
+
47
+ Support JRuby
48
+ --------------------------------------
49
+ Now you could use RModBus on JRuby without RTU implementation.
50
+
51
+ RTU classes requires gem [serialport](https://github.com/hparra/ruby-serialport) which
52
+ currently not compatible with JRuby
data/README.md ADDED
@@ -0,0 +1,87 @@
1
+ RModBus
2
+ ==========================
3
+
4
+ **RModBus** - free implementation of protocol ModBus.
5
+
6
+ Features
7
+ ---------------------------
8
+ - Ruby 1.8, Ruby 1.9, JRuby (without serial ModBus RTU)
9
+ - TCP, RTU, RTU over TCP protocols
10
+ - Client(master) and server(slave)
11
+ - 16, 32 -bit and float registers
12
+
13
+ Support functions
14
+ ---------------------------
15
+ * Read Coils (0x01)
16
+ * Read Discrete Inputs (0x02)
17
+ * Read Holding Registers (0x03)
18
+ * Read Input Registers (0x04)
19
+ * Write Single Coil (0x05)
20
+ * Write Single Register (0x06)
21
+ * Write Multiple Coils (0x0F)
22
+ * Write Multiple registers (0x10)
23
+ * Mask Write register (0x16)
24
+
25
+ Installation
26
+ ------------------------------------
27
+
28
+ Download and install RModBus with the following
29
+
30
+ **$ gem install rmodbus**
31
+
32
+ Example
33
+ ------------------------------------
34
+
35
+ require 'rmodbus'
36
+
37
+ ModBus::TCPClient.new('127.0.0.1', 8502) do |cl|
38
+ cl.with_slave(1) do |slave|
39
+ # Read a single holding register at address 16
40
+ slave.holding_registers[16]
41
+
42
+ # Write a single holding register at address 16
43
+ slave.holding_registers[16] = 123
44
+
45
+ # Read holding registers 16 through 20
46
+ slave.holding_registers[16..20]
47
+
48
+ # Write holding registers 16 through 20 with some values
49
+ slave.holding_registers[16..20] = [1, 2, 3, 4, 5]
50
+ end
51
+ end
52
+
53
+
54
+ Conversion to/from 32bit registers
55
+ -----------------------------------
56
+
57
+ Some modbus devices use two registers to store 32bit values.
58
+ RModbus provides some helper functions to go back and forth between these two things when reading/writing.
59
+ The built-in examples assume registers in a particular order but it's trivial to change.
60
+
61
+ # Reading values in multiple registers (you can read more than 2 and convert them all so long as they are in multiples of 2)
62
+ res = slave.holding_registers[0..1]
63
+ res.inspect => [20342, 17344]
64
+ res.to_32i => [1136676726]
65
+ res.to_32f => [384.620788574219]
66
+
67
+ # Writing 32b values to multiple registers
68
+ cl.holding_registers[0..1] = [1136676726].from_32i
69
+ cl.holding_registers[0..1] => [20342, 17344]
70
+ cl.holding_registers[2..3] = [384.620788574219].from_32f
71
+ cl.holding_registers[2..3] => [20342, 17344]
72
+
73
+ GitHub
74
+ ----------------------------------
75
+
76
+ You can checkout source code from GitHub repositry
77
+
78
+ **$ git clone git://github.com/flipback/RModBus.git**
79
+
80
+ Reference
81
+ ----------------------------------
82
+
83
+ Home page: http://rmodbus.heroku.com
84
+
85
+ RModBud on GitHub: http://github.com/flipback/RModBus
86
+
87
+ ModBus community: http://www.modbus-ida.org
data/Rakefile CHANGED
@@ -1,45 +1,31 @@
1
- require 'rbconfig'
2
- if RUBY_VERSION.to_f >= 1.9
3
- require 'fileutils'
4
- else
5
- require 'ftools'
6
- end
1
+ # encoding: utf-8
7
2
 
3
+ require 'rubygems'
4
+ require 'bundler'
8
5
  begin
9
- require 'rubygems'
10
- rescue Exception
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
11
  end
12
12
 
13
- begin
14
- require 'spec/rake/spectask'
15
-
16
- Spec::Rake::SpecTask.new do |t|
17
- t.spec_opts = ['-c']
18
- t.libs << 'lib'
19
- t.spec_files = FileList['spec/**/*_spec.rb']
20
- t.rcov = false
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
+ if RUBY_PLATFORM == "java"
19
+ spec.pattern.exclude("spec/rtu_client_spec.rb", "spec/rtu_server_spec.rb")
21
20
  end
22
- rescue Exception
23
- puts 'RSpec not available. Install it with: sudo gem install rspec'
24
21
  end
25
22
 
26
- include Config
27
-
28
- task :install do
29
-
30
- sitedir = CONFIG['sitelibdir']
31
- rmodbus_dest = File.join(sitedir, 'rmodbus')
32
-
33
- File::makedirs(rmodbus_dest, true)
34
- File::chmod(0755, rmodbus_dest)
23
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
24
+ spec.pattern = FileList['spec/**/*_spec.rb']
25
+ spec.rcov = true
26
+ end
35
27
 
36
- files = Dir.chdir('lib') { Dir['**/*.rb'] }
28
+ task :default => :spec
37
29
 
38
- files.each do |fn|
39
- fn_dir = File.dirname(fn)
40
- target_dir = File.join(sitedir, fn_dir)
41
- File::makedirs(target_dir) unless File.exist?(target_dir)
42
- File::install(File.join('lib', fn), File.join(sitedir, fn), 0644, true)
43
- end
44
-
45
- end
30
+ require 'yard'
31
+ YARD::Rake::YardocTask.new
@@ -10,49 +10,47 @@ TIMES = 100
10
10
 
11
11
  srv = RTUServer.new 'com3', BAUD
12
12
  srv.coils = [0,1] * 50
13
- srv.discret_inputs = [1,0] * 50
13
+ srv.discrete_inputs = [1,0] * 50
14
14
  srv.holding_registers = [0,1,2,3,4,5,6,7,8,9] * 10
15
15
  srv.input_registers = [0,1,2,3,4,5,6,7,8,9] * 10
16
16
  srv.start
17
17
 
18
18
 
19
- cl = RTUClient.new 'com4', BAUD
20
-
21
-
22
- Benchmark.bmbm do |x|
23
- x.report('Read coils') do
24
- TIMES.times { cl.read_coils 0, 100 }
25
- end
26
-
27
- x.report('Read discrete inputs') do
28
- TIMES.times { cl.read_discrete_inputs 0, 100 }
29
- end
30
-
31
- x.report('Read holding registers') do
32
- TIMES.times { cl.read_holding_registers 0, 100 }
33
- end
34
-
35
- x.report('Read input registers') do
36
- TIMES.times { cl.read_input_registers 0, 100 }
37
- end
38
-
39
- x.report('Write single coil') do
40
- TIMES.times { cl.write_single_coil 0, 1 }
41
- end
42
-
43
- x.report('Write single register') do
44
- TIMES.times { cl.write_single_register 100, 0xAAAA }
45
- end
46
-
47
- x.report('Write multiple coils') do
48
- TIMES.times { cl.write_multiple_coils 0, [1,0] * 50 }
49
- end
50
-
51
-
52
- x.report('Write multiple registers') do
53
- TIMES.times { cl.write_multiple_registers 0, [0,1,2,3,4,5,6,7,8,9] * 10 }
19
+ cl = RTUClient.new('com4', BAUD)
20
+ cl.with_slave(1) do |slave|
21
+ Benchmark.bmbm do |x|
22
+ x.report('Read coils') do
23
+ TIMES.times { slave.read_coils 0, 100 }
24
+ end
25
+
26
+ x.report('Read discrete inputs') do
27
+ TIMES.times { slave.read_discrete_inputs 0, 100 }
28
+ end
29
+
30
+ x.report('Read holding registers') do
31
+ TIMES.times { slave.read_holding_registers 0, 100 }
32
+ end
33
+
34
+ x.report('Read input registers') do
35
+ TIMES.times { slave.read_input_registers 0, 100 }
36
+ end
37
+
38
+ x.report('Write single coil') do
39
+ TIMES.times { slave.write_single_coil 0, 1 }
40
+ end
41
+
42
+ x.report('Write single register') do
43
+ TIMES.times { slave.write_single_register 100, 0xAAAA }
44
+ end
45
+
46
+ x.report('Write multiple coils') do
47
+ TIMES.times { slave.write_multiple_coils 0, [1,0] * 50 }
48
+ end
49
+
50
+ x.report('Write multiple registers') do
51
+ TIMES.times { slave.write_multiple_registers 0, [0,1,2,3,4,5,6,7,8,9] * 10 }
52
+ end
54
53
  end
55
54
  end
56
-
57
55
  srv.stop
58
56
  cl.close
@@ -9,49 +9,47 @@ TIMES = 1000
9
9
 
10
10
  srv = ModBus::TCPServer.new 1502
11
11
  srv.coils = [0,1] * 50
12
- srv.discret_inputs = [1,0] * 50
12
+ srv.discrete_inputs = [1,0] * 50
13
13
  srv.holding_registers = [0,1,2,3,4,5,6,7,8,9] * 10
14
14
  srv.input_registers = [0,1,2,3,4,5,6,7,8,9] * 10
15
15
  srv.start
16
16
 
17
17
 
18
- cl = TCPClient.new '127.0.0.1', 1502
19
-
20
-
21
- Benchmark.bmbm do |x|
22
- x.report('Read coils') do
23
- TIMES.times { cl.read_coils 0, 100 }
24
- end
25
-
26
- x.report('Read discrete inputs') do
27
- TIMES.times { cl.read_discrete_inputs 0, 100 }
28
- end
29
-
30
- x.report('Read holding registers') do
31
- TIMES.times { cl.read_holding_registers 0, 100 }
32
- end
33
-
34
- x.report('Read input registers') do
35
- TIMES.times { cl.read_input_registers 0, 100 }
36
- end
37
-
38
- x.report('Write single coil') do
39
- TIMES.times { cl.write_single_coil 0, 1 }
40
- end
41
-
42
- x.report('Write single register') do
43
- TIMES.times { cl.write_single_register 100, 0xAAAA }
44
- end
45
-
46
- x.report('Write multiple coils') do
47
- TIMES.times { cl.write_multiple_coils 0, [1,0] * 50 }
48
- end
49
-
50
-
51
- x.report('Write multiple registers') do
52
- TIMES.times { cl.write_multiple_registers 0, [0,1,2,3,4,5,6,7,8,9] * 10 }
18
+ cl = TCPClient.new('127.0.0.1', 1502)
19
+ cl.with_slave(1) do |slave|
20
+ Benchmark.bmbm do |x|
21
+ x.report('Read coils') do
22
+ TIMES.times { slave.read_coils 0, 100 }
23
+ end
24
+
25
+ x.report('Read discrete inputs') do
26
+ TIMES.times { slave.read_discrete_inputs 0, 100 }
27
+ end
28
+
29
+ x.report('Read holding registers') do
30
+ TIMES.times { slave.read_holding_registers 0, 100 }
31
+ end
32
+
33
+ x.report('Read input registers') do
34
+ TIMES.times { slave.read_input_registers 0, 100 }
35
+ end
36
+
37
+ x.report('Write single coil') do
38
+ TIMES.times { slave.write_single_coil 0, 1 }
39
+ end
40
+
41
+ x.report('Write single register') do
42
+ TIMES.times { slave.write_single_register 100, 0xAAAA }
43
+ end
44
+
45
+ x.report('Write multiple coils') do
46
+ TIMES.times { slave.write_multiple_coils 0, [1,0] * 50 }
47
+ end
48
+
49
+ x.report('Write multiple registers') do
50
+ TIMES.times { slave.write_multiple_registers 0, [0,1,2,3,4,5,6,7,8,9] * 10 }
51
+ end
53
52
  end
54
53
  end
55
-
56
- srv.stop
57
54
  cl.close
55
+ srv.stop
@@ -9,11 +9,14 @@ srv.input_registers = [1,2,3,4]
9
9
  srv.debug = true
10
10
  srv.start
11
11
 
12
- ModBus::RTUViaTCPClient.connect('127.0.0.1', 10002, 1) do |cl|
13
- cl.debug = true
14
- puts cl.read_holding_registers(0,4).inspect
15
- cl.write_multiple_registers(0, [4,4,4])
16
- puts cl.read_holding_registers(0,4).inspect
12
+ ModBus::RTUViaTCPClient.connect('127.0.0.1', 10002) do |cl|
13
+ cl.with_slave(1) do |slave|
14
+ slave.debug = true
15
+ regs = slave.holding_registers
16
+ puts regs[0..3]
17
+ regs[0..3] = [2,0,1,1]
18
+ puts regs[0..3]
19
+ end
17
20
  end
18
21
 
19
22
  srv.shutdown
@@ -3,17 +3,21 @@ require 'rmodbus'
3
3
 
4
4
  srv = ModBus::TCPServer.new(8502,1)
5
5
  srv.coils = [1,0,1,1]
6
- srv.discret_inputs = [1,1,0,0]
6
+ srv.discrete_inputs = [1,1,0,0]
7
7
  srv.holding_registers = [1,2,3,4]
8
8
  srv.input_registers = [1,2,3,4]
9
9
  srv.debug = true
10
10
  srv.audit = true
11
11
  srv.start
12
12
 
13
- ModBus::TCPClient.connect('127.0.0.1', 8502, 1) do |cl|
14
- cl.debug = true
15
- puts cl.read_holding_registers(0,4)
16
- cl.write_multiple_registers(0, [4,4,4])
17
- puts cl.read_holding_registers(0,4)
13
+ ModBus::TCPClient.connect('127.0.0.1', 8502) do |cl|
14
+ cl.with_slave(1) do |slave|
15
+ slave.debug = true
16
+ regs = slave.holding_registers
17
+ puts regs[0..3]
18
+ regs[0..3] = [2,0,1,1]
19
+ puts regs[0..3]
20
+ end
18
21
  end
22
+
19
23
  srv.stop