rs232 0.1.3 → 0.1.4
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/README +26 -28
- data/lib/rs232.rb +57 -39
- data/rakefile.rb +15 -6
- metadata +11 -6
data/README
CHANGED
@@ -1,34 +1,32 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
usage:
|
23
|
-
|
1
|
+
|
2
|
+
|
3
|
+
RS232
|
4
|
+
|
5
|
+
Ruby interface to Windows Serial Port API
|
6
|
+
|
7
|
+
author hugo benichi
|
8
|
+
email hugo[dot]benichi[at]m4x[dot]org
|
9
|
+
copyright 2012 hugo benichi
|
10
|
+
version 0.1.4
|
11
|
+
|
12
|
+
|
13
|
+
Installation:
|
14
|
+
|
15
|
+
To compile the gem, produce a .gem package and install it automatically, run
|
16
|
+
from the root directory:
|
17
|
+
|
18
|
+
$ rake gem_install
|
19
|
+
|
20
|
+
Usage:
|
21
|
+
|
24
22
|
cf test/test_rs232.rb
|
25
|
-
|
23
|
+
|
26
24
|
first, require the gem with
|
27
25
|
require 'rs232'
|
28
|
-
|
29
|
-
then
|
26
|
+
|
27
|
+
then create an RS232 instance, passing an address and optional conf params
|
30
28
|
serial_port = RS232.new 'COM1'
|
31
|
-
|
29
|
+
|
32
30
|
the default parameters are
|
33
31
|
baud rate: 9600
|
34
32
|
8 bits
|
@@ -37,4 +35,4 @@
|
|
37
35
|
control flow hardware (RTS/CTS)
|
38
36
|
delimiters "\r\n"
|
39
37
|
|
40
|
-
you can
|
38
|
+
you can use RS232 instances with 'write', 'read' and 'query' commands
|
data/lib/rs232.rb
CHANGED
@@ -2,8 +2,10 @@ class RS232
|
|
2
2
|
|
3
3
|
require 'ffi'
|
4
4
|
|
5
|
-
attr_accessor :report,
|
6
|
-
|
5
|
+
attr_accessor :report, # flag set by client, if true reports read/write bits
|
6
|
+
:delimiter # line delimiter caracters, default: "\r\n"
|
7
|
+
attr_reader :count, # number of last read/write bits
|
8
|
+
:error # last error/status code
|
7
9
|
|
8
10
|
# serial port object constructor
|
9
11
|
# also sets the parameters and timeout properties through an hash argument
|
@@ -27,10 +29,14 @@ class RS232
|
|
27
29
|
share = params[:share] || 0 #Win32::FILE_SHARE_DELETE
|
28
30
|
type = params[:file] || Win32::OPEN_EXISTING
|
29
31
|
attr = params[:attr] || Win32::FILE_ATTRIBUTE_NORMAL
|
32
|
+
|
30
33
|
@serial = Win32::CreateFileA( address, mode, share, nil, type, attr, nil)
|
31
34
|
@error = Win32.error_check
|
35
|
+
|
32
36
|
puts "RS232 >> got file handle 0x%.8x for com port %s" % [@serial, address]
|
33
|
-
|
37
|
+
|
38
|
+
# com port connection configuration with C struct
|
39
|
+
DCB.new.tap do |p| # check below for DCB struct definition
|
34
40
|
p[:dcblength] = DCB::Sizeof
|
35
41
|
Win32::GetCommState @serial, p
|
36
42
|
p[:baudrate] = params[:baudrate] || 9600
|
@@ -40,6 +46,8 @@ class RS232
|
|
40
46
|
Win32::SetCommState @serial, p
|
41
47
|
@error = Win32.error_check
|
42
48
|
end
|
49
|
+
|
50
|
+
# com port connection timeouts configuration with C struct
|
43
51
|
CommTimeouts.new.tap do |timeouts|
|
44
52
|
timeouts[:read_interval_timeout] = params[:read_interval_timeout] || 50
|
45
53
|
timeouts[:read_total_timeout_multiplier] = params[:read_total_timeout_multiplier] || 50
|
@@ -49,13 +57,15 @@ class RS232
|
|
49
57
|
Win32::SetCommTimeouts @serial, timeouts
|
50
58
|
@error = Win32.error_check
|
51
59
|
end
|
60
|
+
|
52
61
|
grow_buffer 128
|
53
62
|
@count = FFI::MemoryPointer.new :uint, 1
|
54
63
|
@report = false
|
55
64
|
@delimiter = params[:delimiter] || "\r\n"
|
56
65
|
end
|
57
66
|
|
58
|
-
# writes a string to the Serial port
|
67
|
+
# writes a string to the Serial port
|
68
|
+
# automatically appends the delimiter characters stored in @delimiter
|
59
69
|
def write string
|
60
70
|
command = "%s%s" % [string.chomp, @delimiter]
|
61
71
|
grow_buffer command.length
|
@@ -66,7 +76,7 @@ class RS232
|
|
66
76
|
puts "write count %i" % @count.read_uint32 if @report
|
67
77
|
end
|
68
78
|
|
69
|
-
#
|
79
|
+
# reads a string from the Serial port
|
70
80
|
def read
|
71
81
|
Win32::ReadFile @serial, @buffer, @buflen, @count, nil
|
72
82
|
@error = Win32.error_check
|
@@ -74,27 +84,31 @@ class RS232
|
|
74
84
|
@buffer.read_string.chomp
|
75
85
|
end
|
76
86
|
|
77
|
-
# write
|
87
|
+
# write + read helper method for queries
|
78
88
|
def query string
|
79
89
|
write string
|
80
90
|
read
|
81
91
|
end
|
82
92
|
|
83
|
-
#
|
93
|
+
# closes the Com port TODO: sets this as object finilizer
|
84
94
|
def stop
|
85
95
|
Win32::CloseHandle @serial
|
86
96
|
@error = Win32.error_check
|
87
97
|
end
|
88
98
|
|
89
|
-
#
|
90
|
-
def grow_buffer size
|
91
|
-
|
99
|
+
# increases the buffer size for reading and writing
|
100
|
+
def grow_buffer size
|
101
|
+
if @buffer.nil? || @buflen < size
|
102
|
+
@buffer = FFI::MemoryPointer.new :char, @buflen = size
|
103
|
+
end
|
92
104
|
end
|
93
105
|
|
94
106
|
# wraps the native Windows API functions for file IO and COMM port found in kernel32.dll
|
95
107
|
module Win32
|
108
|
+
|
96
109
|
extend FFI::Library
|
97
110
|
ffi_lib 'kernel32.dll'
|
111
|
+
|
98
112
|
[
|
99
113
|
[ :GetLastError, [], :uint32],
|
100
114
|
[ :CreateFileA, [:pointer, :uint32, :uint32, :pointer, :uint32, :uint32, :pointer], :pointer],
|
@@ -110,55 +124,59 @@ class RS232
|
|
110
124
|
[ :GetCommTimeouts, [:pointer, :pointer], :int32],
|
111
125
|
[ :SetCommTimeouts, [:pointer, :pointer], :int32],
|
112
126
|
].each{ |sig| attach_function *sig }
|
127
|
+
|
113
128
|
def self.error_code
|
114
129
|
err = self::GetLastError()
|
115
130
|
"error code: %i | 0x%.8x" % [err,err]
|
116
131
|
end
|
132
|
+
|
117
133
|
def self.error_check
|
118
134
|
self::GetLastError().tap{ |err| puts "error: %i | 0x%.8x" % [err,err] if err != 0 }
|
119
135
|
end
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
136
|
+
|
137
|
+
# consts from Windows seven sdk. extract with
|
138
|
+
# grep -i "generic_read" *.h
|
139
|
+
# from the /Include directory
|
140
|
+
FILE_SHARE_DELETE = 0x00000004
|
141
|
+
FILE_SHARE_READ = 0x00000001
|
142
|
+
FILE_SHARE_WRITE = 0x00000002
|
143
|
+
FILE_SHARE_ALL = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE
|
127
144
|
GENERIC_READ = 0x80000000
|
128
145
|
GENERIC_WRITE = 0x40000000
|
129
|
-
|
130
|
-
|
146
|
+
CREATE_NEW = 1
|
147
|
+
CREATE_ALWAYS = 2
|
131
148
|
OPEN_EXISTING = 3
|
132
|
-
|
149
|
+
OPEN_ALWAYS = 4
|
133
150
|
FILE_ATTRIBUTE_NORMAL = 0x00000080
|
151
|
+
|
134
152
|
end
|
135
153
|
|
136
154
|
# this struct is used by windows to configure the COMM port
|
137
155
|
class DCB < FFI::Struct
|
138
156
|
layout :dcblength, :uint32,
|
139
157
|
:baudrate, :uint32,
|
140
|
-
:flags, :uint32,
|
141
|
-
:wreserved, :uint16,
|
142
|
-
:xonlim, :uint16,
|
143
|
-
:xofflim, :uint16,
|
144
|
-
:bytesize, :uint8,
|
145
|
-
:parity, :uint8,
|
146
|
-
:stopbits, :uint8,
|
147
|
-
:xonchar, :int8,
|
148
|
-
:xoffchar, :int8,
|
149
|
-
:errorchar, :int8,
|
150
|
-
:eofchar, :int8,
|
151
|
-
:evtchar, :int8,
|
152
|
-
:wreserved1, :uint16
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
Sizeof = 28 # this is used to tell windows the size of its own struct,
|
157
|
-
ONESTOPBIT = 0
|
158
|
+
:flags, :uint32, # :flag is actually a bit fields compound:
|
159
|
+
:wreserved, :uint16, # uint32 fBinary :1;
|
160
|
+
:xonlim, :uint16, # uint32 fParity :1;
|
161
|
+
:xofflim, :uint16, # uint32 fParity :1;
|
162
|
+
:bytesize, :uint8, # uint32 fOutxCtsFlow :1;
|
163
|
+
:parity, :uint8, # uint32 fOutxDsrFlow :1;
|
164
|
+
:stopbits, :uint8, # uint32 fDtrControl :2;
|
165
|
+
:xonchar, :int8, # uint32 fDsrSensitivity :1;
|
166
|
+
:xoffchar, :int8, # uint32 fTXContinueOnXoff :1;
|
167
|
+
:errorchar, :int8, # uint32 fOutX :1;
|
168
|
+
:eofchar, :int8, # uint32 fInX :1;
|
169
|
+
:evtchar, :int8, # uint32 fErrorChar :1;
|
170
|
+
:wreserved1, :uint16 # uint32 fNull :1;
|
171
|
+
# uint32 fRtsControl :2;
|
172
|
+
# uint32 fAbortOnError :1;
|
173
|
+
# uint32 fDummy2 :17;
|
174
|
+
Sizeof = 28 # this is used to tell windows the size of its own struct,
|
175
|
+
ONESTOPBIT = 0 # not sure why necessary (different Windows versions ?)
|
158
176
|
NOPARITY = 0
|
159
177
|
end
|
160
178
|
|
161
|
-
# this
|
179
|
+
# this struct is used to set timeout properties of the opened COM ports
|
162
180
|
class CommTimeouts < FFI::Struct
|
163
181
|
layout :read_interval_timeout, :uint32,
|
164
182
|
:read_total_timeout_multiplier, :uint32,
|
data/rakefile.rb
CHANGED
@@ -1,11 +1,20 @@
|
|
1
|
-
task :test_global do
|
2
|
-
|
1
|
+
task :test_global do # test if run after gem install
|
2
|
+
ruby "test/test_rs232.rb"
|
3
|
+
end
|
4
|
+
|
5
|
+
task :test_local do # test if run from gem root dir
|
6
|
+
ruby "-Ilib test/test_rs232.rb"
|
7
|
+
end
|
8
|
+
|
9
|
+
task :gem_build do
|
10
|
+
sh "gem build rs232.gemspec"
|
11
|
+
end
|
3
12
|
|
4
|
-
task :gem_build do sh "gem build rs232.gemspec" end
|
5
13
|
task :gem_install => :gem_build do
|
6
|
-
gemfile = Dir.new("./").entries.select{ |f|
|
7
|
-
|
14
|
+
gemfile = Dir.new("./").entries.select{ |f|
|
15
|
+
f =~ /rs232-[\d]+\.[\d]+\.[\d]+.gem/
|
16
|
+
}.sort[-1]
|
8
17
|
sh "gem install --local %s" % gemfile
|
9
18
|
end
|
10
19
|
|
11
|
-
task :default => :test_local
|
20
|
+
task :default => :test_local
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rs232
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-03-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
description: Allows to script access to the serial port on Windows. Simple read and
|
26
31
|
write commands
|
27
|
-
email: hugo
|
32
|
+
email: hugo[dot]benichi[at]m4x[dot]org
|
28
33
|
executables: []
|
29
34
|
extensions: []
|
30
35
|
extra_rdoc_files: []
|
@@ -53,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
53
58
|
version: '0'
|
54
59
|
requirements: []
|
55
60
|
rubyforge_project:
|
56
|
-
rubygems_version: 1.8.
|
61
|
+
rubygems_version: 1.8.23
|
57
62
|
signing_key:
|
58
63
|
specification_version: 3
|
59
64
|
summary: Ruby interface to Windows Serial Port API
|