rmodbus 0.3.1 → 0.4.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/ChangeLog +36 -2
- data/README +14 -15
- data/Rakefile +45 -0
- data/examples/perfomance_rtu.rb +58 -0
- data/examples/perfomance_tcp.rb +57 -0
- data/examples/use_tcp_modbus.rb +1 -0
- data/lib/rmodbus/client.rb +20 -7
- data/lib/rmodbus/crc16.rb +69 -0
- data/lib/rmodbus/ext.rb +65 -61
- data/lib/rmodbus/parsers.rb +133 -0
- data/lib/rmodbus/rtu_client.rb +107 -62
- data/lib/rmodbus/rtu_server.rb +90 -0
- data/lib/rmodbus/tcp_client.rb +47 -3
- data/lib/rmodbus/tcp_server.rb +18 -118
- data/lib/rmodbus.rb +1 -0
- data/spec/exception_spec.rb +117 -0
- data/spec/ext_spec.rb +5 -1
- data/spec/logging_spec.rb +69 -0
- data/spec/rtu_client_spec.rb +40 -10
- data/spec/rtu_server_spec.rb +31 -0
- data/spec/tcp_client_spec.rb +25 -0
- data/spec/tcp_server_spec.rb +2 -2
- metadata +15 -6
data/ChangeLog
CHANGED
@@ -17,6 +17,40 @@
|
|
17
17
|
2010-01-7 Timin Aleksey <atimin@gmail.com>
|
18
18
|
* lib/rmodbus/tcp_client.rb: Fixed bug of overflow transaction counter (thanks
|
19
19
|
Tallak Tveide)
|
20
|
+
2010-01-8 Timin Aleksey <atimin@gmail.com>
|
21
|
+
* lib/rmodbus/tcp_client.rb: Added new method TCPClient::connect,
|
22
|
+
TCPClient#ipaddr, TCPClient#port, TCPClient#slave
|
23
|
+
* lib/rmodbus/rtu_client.rb: Added new methods RTUClient::connect,
|
24
|
+
RTUClient#close, RTUClient#port, RTUClient#baud, RTUClient#slave
|
25
|
+
2010-01-9 Timin Aleksey <atimin@gmail.com>
|
26
|
+
* rmodbus.gemspec: Added Rakefile into gem, dependencie on
|
27
|
+
serialport-0.8.0.gem
|
28
|
+
* spec/logging_spec.rb: Added specs for debug logging
|
29
|
+
* lib/rmodbus/client.rb, lib/rmodbus/tcp_client.rb,
|
30
|
+
lib/rmodbus/rtu_client.rb: Added debug logging functional
|
20
31
|
2010-01-12 Timin Aleksey <atimin@gmail.com>
|
21
|
-
* lib/rmodbus/rtu_client.rb: RTUClient is live
|
22
|
-
|
32
|
+
* lib/rmodbus/rtu_client.rb: RTUClient is live!
|
33
|
+
2010-01-14 Timin Aleksey <atimin@gmail.com>
|
34
|
+
* lib/rmodbus/crc16.rb: Added module for calculation CRC16
|
35
|
+
* lib/rmodbus/parsers.rb: Added module for parsing requiest from clients
|
36
|
+
* lib/rmodbus/rtu_server.rb: Added RTUServer class
|
37
|
+
* rmodbus.gemspec: Update verison => 0.4.0
|
38
|
+
* README: Update information about project
|
39
|
+
2010-01-16 Timin Aleksey <atimin@gmail.com>
|
40
|
+
* lib/rmodbus/ext.rb, lib/rmodbus/client.rb: Fixed for ruby-1.8.6 compatibility
|
41
|
+
* lib/rmodbus/parsers.rb: Fixed bug for response on write requests
|
42
|
+
* lib/rmodbus/rtu_client.rb: Fixed bug in verifing CRC
|
43
|
+
* lib/rmodbus/rtu_server.rb: Reanimation RTUServer
|
44
|
+
* examples/perfomance_rtu.rb: Added test perfomance for ModBus RTU
|
45
|
+
2010-01-17 Timin Aleksey <atimin@gmail.com>
|
46
|
+
* lib/rmodbus/rtu_server, lib/rmodbus/tcp_server.rb: Fixed typo
|
47
|
+
discret_inputs -> discrete_inputs
|
48
|
+
* examples/perfomance_tcp.rb: Added test perfomance for ModBus TCP
|
49
|
+
* lib/rmodbus/tcp_client.rb: Added method TCPClient#closed?
|
50
|
+
* lib/rmodbus/rtu_client.rb: Added method RTUClient#closed?
|
51
|
+
2010-01-18 Timin Aleksey <atimin@gmail.com>
|
52
|
+
* lib/rmodbus/rtu_client.rb, lib/rmodbus/rtu_server.rb: Added support
|
53
|
+
modem parameters - :data_bits => 5..8, :stop_bits => 1 or 2, :parity =>
|
54
|
+
SerialPort::NONE, SerialPort::EVEN, SerialPort::ODD
|
55
|
+
2010-01-20 Timin Aleksey <atimin@gmail.com>
|
56
|
+
* lib/rmodbus/ext.rb: Fixed bug for divisible 8 data in Array#pack_to_word
|
data/README
CHANGED
@@ -2,10 +2,11 @@
|
|
2
2
|
|
3
3
|
*RModBus* - free implementation of protocol ModBus.
|
4
4
|
|
5
|
-
==
|
5
|
+
== Features
|
6
6
|
|
7
|
-
*
|
8
|
-
*
|
7
|
+
* Support Ruby 1.8, Ruby 1.9
|
8
|
+
* Support ModBus-TCP, ModBus-RTU protocol
|
9
|
+
* Support client(master) and server(slave)
|
9
10
|
* Support functions:
|
10
11
|
* 01 (0x01) Read Coils
|
11
12
|
* 02 (0x02) Read Discrete Inputs
|
@@ -19,17 +20,19 @@
|
|
19
20
|
|
20
21
|
== Installation
|
21
22
|
|
22
|
-
|
23
|
+
Download and install RModBus with the following
|
23
24
|
|
24
|
-
$
|
25
|
+
$ gem install --remote rmodbus
|
25
26
|
|
26
|
-
|
27
|
+
== Example
|
27
28
|
|
28
|
-
|
29
|
+
require 'rmodbus'
|
29
30
|
|
30
|
-
|
31
|
+
cl = ModBus::TCPClient.new('127.0.0.1', 8502, 1)
|
31
32
|
|
32
|
-
|
33
|
+
puts cl.read_holding_registers(0,4)
|
34
|
+
|
35
|
+
cl.write_multiple_registers(0, [4,4,4])
|
33
36
|
|
34
37
|
== GitHub
|
35
38
|
|
@@ -39,14 +42,10 @@ $ git clone git://github.com/flipback/RModBus.git
|
|
39
42
|
|
40
43
|
== Reference
|
41
44
|
|
45
|
+
Home page: http://rmodbus.heroku.com
|
46
|
+
|
42
47
|
RModBus project: http://rubyforge.org/projects/rmodbus
|
43
48
|
|
44
49
|
RModBud on GitHub: http://github.com/flipback/RModBus
|
45
50
|
|
46
51
|
ModBus community: http://www.modbus-ida.org
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
if RUBY_VERSION.to_f >= 1.9
|
3
|
+
require 'fileutils'
|
4
|
+
else
|
5
|
+
require 'ftools'
|
6
|
+
end
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'rubygems'
|
10
|
+
rescue Exception
|
11
|
+
end
|
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
|
21
|
+
end
|
22
|
+
rescue Exception
|
23
|
+
puts 'RSpec not available. Install it with: sudo gem install rspec'
|
24
|
+
end
|
25
|
+
|
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)
|
35
|
+
|
36
|
+
files = Dir.chdir('lib') { Dir['**/*.rb'] }
|
37
|
+
|
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
|
@@ -0,0 +1,58 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__),'../lib')
|
2
|
+
|
3
|
+
require 'rmodbus'
|
4
|
+
require 'benchmark'
|
5
|
+
|
6
|
+
include ModBus
|
7
|
+
|
8
|
+
BAUD = 9600
|
9
|
+
TIMES = 100
|
10
|
+
|
11
|
+
srv = RTUServer.new 'com3', BAUD
|
12
|
+
srv.coils = [0,1] * 50
|
13
|
+
srv.discret_inputs = [1,0] * 50
|
14
|
+
srv.holding_registers = [0,1,2,3,4,5,6,7,8,9] * 10
|
15
|
+
srv.input_registers = [0,1,2,3,4,5,6,7,8,9] * 10
|
16
|
+
srv.start
|
17
|
+
|
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 }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
srv.stop
|
58
|
+
cl.close
|
@@ -0,0 +1,57 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__),'../lib')
|
2
|
+
|
3
|
+
require 'rmodbus'
|
4
|
+
require 'benchmark'
|
5
|
+
|
6
|
+
include ModBus
|
7
|
+
|
8
|
+
TIMES = 1000
|
9
|
+
|
10
|
+
srv = ModBus::TCPServer.new 1502
|
11
|
+
srv.coils = [0,1] * 50
|
12
|
+
srv.discret_inputs = [1,0] * 50
|
13
|
+
srv.holding_registers = [0,1,2,3,4,5,6,7,8,9] * 10
|
14
|
+
srv.input_registers = [0,1,2,3,4,5,6,7,8,9] * 10
|
15
|
+
srv.start
|
16
|
+
|
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 }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
srv.stop
|
57
|
+
cl.close
|
data/examples/use_tcp_modbus.rb
CHANGED
data/lib/rmodbus/client.rb
CHANGED
@@ -29,6 +29,7 @@ module ModBus
|
|
29
29
|
@read_retries = 10
|
30
30
|
end
|
31
31
|
# Read value *ncoils* coils starting with *addr*
|
32
|
+
#
|
32
33
|
# Return array of their values
|
33
34
|
def read_coils(addr, ncoils)
|
34
35
|
query("\x1" + addr.to_word + ncoils.to_word).unpack_bits[0..ncoils-1]
|
@@ -134,19 +135,17 @@ module ModBus
|
|
134
135
|
|
135
136
|
tried = 0
|
136
137
|
begin
|
137
|
-
timeout(1, ModBusTimeout)
|
138
|
-
pdu = read_pdu
|
139
|
-
end
|
138
|
+
timeout(1, ModBusTimeout) { pdu = read_pdu }
|
140
139
|
rescue ModBusTimeout => err
|
141
140
|
tried += 1
|
142
141
|
retry unless tried >= @read_retries
|
143
142
|
raise ModBusTimeout.new, "Timed out during read attempt"
|
144
|
-
rescue
|
145
|
-
raise ModBusException.new, "Server did not respond"
|
146
143
|
end
|
147
144
|
|
148
|
-
if pdu
|
149
|
-
|
145
|
+
return nil if pdu.size == 0
|
146
|
+
|
147
|
+
if pdu.getbyte(0) >= 0x80
|
148
|
+
case pdu.getbyte(1)
|
150
149
|
when 1
|
151
150
|
raise IllegalFunction.new, "The function code received in the query is not an allowable action for the server"
|
152
151
|
when 2
|
@@ -178,6 +177,20 @@ module ModBus
|
|
178
177
|
def close
|
179
178
|
end
|
180
179
|
|
180
|
+
private
|
181
|
+
def logging_bytes(msg)
|
182
|
+
result = ""
|
183
|
+
msg.each_byte do |c|
|
184
|
+
byte = if c < 16
|
185
|
+
'0' + c.to_s(16)
|
186
|
+
else
|
187
|
+
c.to_s(16)
|
188
|
+
end
|
189
|
+
result << "[#{byte}]"
|
190
|
+
end
|
191
|
+
result
|
192
|
+
end
|
193
|
+
|
181
194
|
end
|
182
195
|
|
183
196
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# RModBus - free implementation of ModBus protocol in Ruby.
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 Timin Aleksey
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
|
15
|
+
module ModBus
|
16
|
+
module CRC16
|
17
|
+
def crc16(msg)
|
18
|
+
crc_lo = 0xff
|
19
|
+
crc_hi = 0xff
|
20
|
+
|
21
|
+
msg.unpack('c*').each do |byte|
|
22
|
+
i = crc_hi ^ byte
|
23
|
+
crc_hi = crc_lo ^ CrcHiTable[i]
|
24
|
+
crc_lo = CrcLoTable[i]
|
25
|
+
end
|
26
|
+
|
27
|
+
return ((crc_hi << 8) + crc_lo)
|
28
|
+
end
|
29
|
+
|
30
|
+
CrcHiTable = [
|
31
|
+
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
|
32
|
+
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
33
|
+
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
|
34
|
+
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
35
|
+
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
|
36
|
+
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
|
37
|
+
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
|
38
|
+
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
39
|
+
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
|
40
|
+
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
41
|
+
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
|
42
|
+
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
43
|
+
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
|
44
|
+
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
45
|
+
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
|
46
|
+
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
47
|
+
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
|
48
|
+
0x40]
|
49
|
+
CrcLoTable = [
|
50
|
+
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
|
51
|
+
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
|
52
|
+
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
|
53
|
+
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
|
54
|
+
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
|
55
|
+
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
|
56
|
+
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
|
57
|
+
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
|
58
|
+
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
|
59
|
+
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
|
60
|
+
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
|
61
|
+
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
|
62
|
+
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
|
63
|
+
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
|
64
|
+
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
|
65
|
+
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
|
66
|
+
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
|
67
|
+
0x40]
|
68
|
+
end
|
69
|
+
end
|
data/lib/rmodbus/ext.rb
CHANGED
@@ -1,61 +1,65 @@
|
|
1
|
-
# RModBus - free implementation of ModBus protocol on Ruby.
|
2
|
-
#
|
3
|
-
# Copyright (C) 2009 Timin Aleksey
|
4
|
-
#
|
5
|
-
# This program is free software: you can redistribute it and/or modify
|
6
|
-
# it under the terms of the GNU General Public License as published by
|
7
|
-
# the Free Software Foundation, either version 3 of the License, or
|
8
|
-
# (at your option) any later version.
|
9
|
-
#
|
10
|
-
# This program is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
-
# GNU General Public License for more details.
|
14
|
-
|
15
|
-
class String
|
16
|
-
|
17
|
-
unless RUBY_VERSION
|
18
|
-
def getbyte(index)
|
19
|
-
self[index].to_i
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def unpack_bits
|
24
|
-
array_bit = []
|
25
|
-
self.unpack('b*')[0].
|
26
|
-
array_bit << b.to_i
|
27
|
-
end
|
28
|
-
array_bit
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
class Integer
|
34
|
-
|
35
|
-
def to_word
|
36
|
-
(self >> 8).chr + (self & 0xff).chr
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
class Array
|
42
|
-
|
43
|
-
def pack_to_word
|
44
|
-
word = 0
|
45
|
-
s = ""
|
46
|
-
mask = 0x01
|
47
|
-
|
48
|
-
self.each do |bit|
|
49
|
-
word |= mask if bit > 0
|
50
|
-
mask <<= 1
|
51
|
-
if mask == 0x100
|
52
|
-
mask = 0x01
|
53
|
-
s << word.chr
|
54
|
-
word = 0
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
1
|
+
# RModBus - free implementation of ModBus protocol on Ruby.
|
2
|
+
#
|
3
|
+
# Copyright (C) 2009 Timin Aleksey
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
|
15
|
+
class String
|
16
|
+
|
17
|
+
unless RUBY_VERSION =~ /^1\.9/
|
18
|
+
def getbyte(index)
|
19
|
+
self[index].to_i
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def unpack_bits
|
24
|
+
array_bit = []
|
25
|
+
self.unpack('b*')[0].each_byte do |b|
|
26
|
+
array_bit << b.chr.to_i
|
27
|
+
end
|
28
|
+
array_bit
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
class Integer
|
34
|
+
|
35
|
+
def to_word
|
36
|
+
(self >> 8).chr + (self & 0xff).chr
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
class Array
|
42
|
+
|
43
|
+
def pack_to_word
|
44
|
+
word = 0
|
45
|
+
s = ""
|
46
|
+
mask = 0x01
|
47
|
+
|
48
|
+
self.each do |bit|
|
49
|
+
word |= mask if bit > 0
|
50
|
+
mask <<= 1
|
51
|
+
if mask == 0x100
|
52
|
+
mask = 0x01
|
53
|
+
s << word.chr
|
54
|
+
word = 0
|
55
|
+
end
|
56
|
+
end
|
57
|
+
unless mask == 0x01
|
58
|
+
s << word.chr
|
59
|
+
else
|
60
|
+
s
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|