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
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