rs232 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|