rb232 0.2.5
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/COPYING +19 -0
- data/README +59 -0
- data/examples/listen.rb +46 -0
- data/extconf.rb +5 -0
- data/lib/rb232/text_protocol.rb +67 -0
- data/src/port.c +308 -0
- data/src/port.h +70 -0
- data/src/rb232.c +21 -0
- data/src/utility.c +30 -0
- data/src/utility.h +19 -0
- metadata +64 -0
data/COPYING
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2008 James Smith (james@floppy.org.uk)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
== RB232
|
2
|
+
|
3
|
+
A simple serial port library for Ruby.
|
4
|
+
|
5
|
+
Licensed under the MIT license (See COPYING file for details)
|
6
|
+
|
7
|
+
Author: James Smith (james@floppy.org.uk / http://www.floppy.org.uk)
|
8
|
+
|
9
|
+
Homepage: http://github.com/Floppy/rb232
|
10
|
+
|
11
|
+
Documentation: http://docs.github.com/Floppy/rb232
|
12
|
+
|
13
|
+
== ABOUT
|
14
|
+
|
15
|
+
This library is a simple serial port library for Ruby.
|
16
|
+
|
17
|
+
You may ask, why not just use ruby-serialport? Mainly because the GPL license
|
18
|
+
it is under is too restrictive for my purposes. This code is under the MIT
|
19
|
+
license, so you can do anything you like with it.
|
20
|
+
|
21
|
+
== INSTALLATION
|
22
|
+
|
23
|
+
1) Enable gems from gemcutter, if you haven't already done so:
|
24
|
+
> sudo gem install gemcutter
|
25
|
+
> sudo gem tumble
|
26
|
+
|
27
|
+
2) Install gem
|
28
|
+
> sudo gem install rb232
|
29
|
+
|
30
|
+
== STATUS
|
31
|
+
|
32
|
+
Currently you can read from a serial port, but not write back. The code is only
|
33
|
+
tested on Linux - other unixes *may* work, Mac OSX *might* be ok, but Windows
|
34
|
+
is right out for now. Watch this space for further developments!
|
35
|
+
|
36
|
+
== USAGE
|
37
|
+
|
38
|
+
The following code will read a 10-character string from the specified port,
|
39
|
+
using the default port settings (9600/8/n/1/no flow control)
|
40
|
+
|
41
|
+
@port = RB232::Port.new('/dev/ttyUSB0')
|
42
|
+
message = @port.read_string(10)
|
43
|
+
|
44
|
+
You can provide alternative settings when you create a new port:
|
45
|
+
|
46
|
+
RB232::Port.new('/dev/ttyS0', :baud_rate => 19200,
|
47
|
+
:data_bits => 7,
|
48
|
+
:parity => true,
|
49
|
+
:stop_bits => 2,
|
50
|
+
:hardware_flow_control => true)
|
51
|
+
|
52
|
+
See http://github.com/Floppy/rb232/tree/master/spec/port_spec.rb or RB232::Port
|
53
|
+
documentation for more details.
|
54
|
+
|
55
|
+
If you are using a simple text protocol over RS232, you can use the
|
56
|
+
RB232::TextProtocol class to help you out. It automatically monitors the port
|
57
|
+
and splits messages up by detecting separator characters. See
|
58
|
+
http://github.com/Floppy/rb232/tree/master/examples/listen.rb for an example of
|
59
|
+
how to use this class.
|
data/examples/listen.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
dir = File.dirname(__FILE__) + '/../lib'
|
4
|
+
$LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'rb232'
|
8
|
+
require 'rb232/text_protocol'
|
9
|
+
|
10
|
+
class SimpleClient
|
11
|
+
def update(message)
|
12
|
+
puts("Message received:")
|
13
|
+
puts(message)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'optparse'
|
18
|
+
|
19
|
+
# Command-line options - just baud rate and separator for now
|
20
|
+
options = {:port => '/dev/ttyS0', :baud_rate => 9600, :separator => "\n"}
|
21
|
+
OptionParser.new do |opts|
|
22
|
+
opts.on("-p", "--serial_port SERIAL_PORT", "serial port") do |p|
|
23
|
+
options[:port] = p
|
24
|
+
end
|
25
|
+
opts.on("-b", "--baud_rate BAUD_RATE", "baud rate") do |b|
|
26
|
+
options[:baud_rate] = b.to_i
|
27
|
+
end
|
28
|
+
opts.on("-s", "--separator SEPARATOR", "message separator character") do |s|
|
29
|
+
options[:separator] = s
|
30
|
+
end
|
31
|
+
end.parse!
|
32
|
+
|
33
|
+
port = RB232::Port.new(options[:port], :baud_rate => options[:baud_rate].to_i)
|
34
|
+
|
35
|
+
protocol = RB232::TextProtocol.new(port, options[:separator])
|
36
|
+
client = SimpleClient.new
|
37
|
+
protocol.add_observer(client)
|
38
|
+
|
39
|
+
# Start receiving messags
|
40
|
+
protocol.start
|
41
|
+
|
42
|
+
# Wait a while
|
43
|
+
sleep(30)
|
44
|
+
|
45
|
+
# OK, finish now
|
46
|
+
protocol.stop
|
data/extconf.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rb232'
|
2
|
+
require 'observer'
|
3
|
+
|
4
|
+
module RB232
|
5
|
+
|
6
|
+
# A helper class for RB232::Port which implements a simple text-based
|
7
|
+
# protocol on top of a serial port. Data is read from the serial port and split
|
8
|
+
# into individual messages based on a separator character.
|
9
|
+
#
|
10
|
+
# This class is Observable. Client code should implement an update(string) function
|
11
|
+
# add call TextProtocol#add_observer(self). When a complete message is received,
|
12
|
+
# the update() function will be called with the message string.
|
13
|
+
class TextProtocol
|
14
|
+
|
15
|
+
include Observable
|
16
|
+
|
17
|
+
# Create a protocol object. _port_ should be a RB232::Port object.
|
18
|
+
# _separator_ is the character which separates messages in the text protocol,
|
19
|
+
# "\n" by default.
|
20
|
+
def initialize(port, separator = "\n")
|
21
|
+
@port = port
|
22
|
+
@separator = separator
|
23
|
+
end
|
24
|
+
|
25
|
+
# Separator character, as specified in TextProtocol#new
|
26
|
+
attr_reader :separator
|
27
|
+
|
28
|
+
# Port object, as specified in TextProtocol#new
|
29
|
+
attr_reader :port
|
30
|
+
|
31
|
+
# Begin processing incoming data from the serial port.
|
32
|
+
# A thread is started which monitors the port for data and detects
|
33
|
+
# complete messages.
|
34
|
+
# Call TextProtocol#stop to halt this process.
|
35
|
+
def start
|
36
|
+
@stop = false
|
37
|
+
@reader_thread = Thread.new {
|
38
|
+
buffer = ""
|
39
|
+
while (@stop == false)
|
40
|
+
new_string = ""
|
41
|
+
# Read in as much data as possible
|
42
|
+
begin
|
43
|
+
new_string = @port.read_string(255)
|
44
|
+
if (new_string.size > 0)
|
45
|
+
buffer += new_string
|
46
|
+
messages = buffer.split(@separator,2)
|
47
|
+
if messages.size > 1
|
48
|
+
changed
|
49
|
+
notify_observers(messages[0])
|
50
|
+
buffer = messages[1] || ""
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end while (new_string.size > 0 && @stop == false)
|
54
|
+
sleep(0.5)
|
55
|
+
end
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
# Stop processing incoming data from the serial port.
|
60
|
+
def stop
|
61
|
+
@stop = true
|
62
|
+
@reader_thread.join
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
data/src/port.c
ADDED
@@ -0,0 +1,308 @@
|
|
1
|
+
#include "port.h"
|
2
|
+
#include "utility.h"
|
3
|
+
|
4
|
+
#include <fcntl.h>
|
5
|
+
#include <termios.h>
|
6
|
+
#include <unistd.h>
|
7
|
+
|
8
|
+
/* Module and class handles */
|
9
|
+
VALUE RB232 = Qnil;
|
10
|
+
VALUE RB232_Port = Qnil;
|
11
|
+
|
12
|
+
/*
|
13
|
+
* Data structure for storing object data
|
14
|
+
*/
|
15
|
+
struct RB232_Port_Data {
|
16
|
+
/* Settings */
|
17
|
+
char* port_name;
|
18
|
+
int baud_rate;
|
19
|
+
int data_bits;
|
20
|
+
BOOL parity;
|
21
|
+
int stop_bits;
|
22
|
+
BOOL hardware_flow_control;
|
23
|
+
/* Internals */
|
24
|
+
int port_handle;
|
25
|
+
struct termios settings;
|
26
|
+
};
|
27
|
+
|
28
|
+
/* Helper for accessing port data */
|
29
|
+
struct RB232_Port_Data* get_port_data(VALUE self) {
|
30
|
+
struct RB232_Port_Data *port_data;
|
31
|
+
Data_Get_Struct(self, struct RB232_Port_Data, port_data);
|
32
|
+
return port_data;
|
33
|
+
};
|
34
|
+
|
35
|
+
/*
|
36
|
+
* Port data deallocation
|
37
|
+
*/
|
38
|
+
VALUE rb232_port_data_free(void* p) {
|
39
|
+
struct RB232_Port_Data* port_data = p;
|
40
|
+
/* Close port */
|
41
|
+
close(port_data->port_handle);
|
42
|
+
/* Free memory */
|
43
|
+
free(port_data->port_name);
|
44
|
+
free(port_data);
|
45
|
+
/* Done */
|
46
|
+
return Qnil;
|
47
|
+
}
|
48
|
+
|
49
|
+
/*
|
50
|
+
* Object allocation
|
51
|
+
*/
|
52
|
+
VALUE rb232_port_alloc(VALUE klass) {
|
53
|
+
struct RB232_Port_Data* port_data = malloc(sizeof(struct RB232_Port_Data));
|
54
|
+
memset(port_data, 0, sizeof(struct RB232_Port_Data));
|
55
|
+
return Data_Wrap_Struct(klass, 0, rb232_port_data_free, port_data);
|
56
|
+
}
|
57
|
+
|
58
|
+
/*
|
59
|
+
* Object initialization. Takes a port name and a hash of port options.
|
60
|
+
*/
|
61
|
+
VALUE rb232_port_initialize_with_options(VALUE self, VALUE port, VALUE options) {
|
62
|
+
/* Get port data */
|
63
|
+
struct RB232_Port_Data *port_data = get_port_data(self);
|
64
|
+
/* Store port name */
|
65
|
+
int port_name_len = RSTRING(port)->len;
|
66
|
+
port_data->port_name = malloc(port_name_len + 1);
|
67
|
+
strcpy(port_data->port_name, RSTRING(port)->ptr);
|
68
|
+
/* Store options */
|
69
|
+
port_data->baud_rate = rbx_int_from_hash_or_default(options, ID2SYM(rb_intern("baud_rate")), 9600);
|
70
|
+
port_data->data_bits = rbx_int_from_hash_or_default(options, ID2SYM(rb_intern("data_bits")), 8);
|
71
|
+
port_data->parity = rbx_bool_from_hash_or_default(options, ID2SYM(rb_intern("parity")), FALSE);
|
72
|
+
port_data->stop_bits = rbx_int_from_hash_or_default(options, ID2SYM(rb_intern("stop_bits")), 1);
|
73
|
+
port_data->hardware_flow_control = rbx_bool_from_hash_or_default(options, ID2SYM(rb_intern("hardware_flow_control")), FALSE);
|
74
|
+
/* Open the serial port */
|
75
|
+
port_data->port_handle = open(port_data->port_name, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
76
|
+
if (port_data->port_handle < 0) {
|
77
|
+
rb_raise(rb_eArgError, "couldn't open the specified port");
|
78
|
+
}
|
79
|
+
/* Set port settings */
|
80
|
+
port_data->settings.c_cflag = CRTSCTS | CLOCAL | CREAD;
|
81
|
+
/* Baud rate */
|
82
|
+
switch (port_data->baud_rate) {
|
83
|
+
case 0:
|
84
|
+
port_data->settings.c_cflag |= B0;
|
85
|
+
break;
|
86
|
+
case 50:
|
87
|
+
port_data->settings.c_cflag |= B50;
|
88
|
+
break;
|
89
|
+
case 75:
|
90
|
+
port_data->settings.c_cflag |= B75;
|
91
|
+
break;
|
92
|
+
case 110:
|
93
|
+
port_data->settings.c_cflag |= B110;
|
94
|
+
break;
|
95
|
+
case 134:
|
96
|
+
port_data->settings.c_cflag |= B134;
|
97
|
+
break;
|
98
|
+
case 150:
|
99
|
+
port_data->settings.c_cflag |= B150;
|
100
|
+
break;
|
101
|
+
case 200:
|
102
|
+
port_data->settings.c_cflag |= B200;
|
103
|
+
break;
|
104
|
+
case 300:
|
105
|
+
port_data->settings.c_cflag |= B300;
|
106
|
+
break;
|
107
|
+
case 600:
|
108
|
+
port_data->settings.c_cflag |= B600;
|
109
|
+
break;
|
110
|
+
case 1200:
|
111
|
+
port_data->settings.c_cflag |= B1200;
|
112
|
+
break;
|
113
|
+
case 1800:
|
114
|
+
port_data->settings.c_cflag |= B1800;
|
115
|
+
break;
|
116
|
+
case 2400:
|
117
|
+
port_data->settings.c_cflag |= B2400;
|
118
|
+
break;
|
119
|
+
case 4800:
|
120
|
+
port_data->settings.c_cflag |= B4800;
|
121
|
+
break;
|
122
|
+
case 9600:
|
123
|
+
port_data->settings.c_cflag |= B9600;
|
124
|
+
break;
|
125
|
+
case 19200:
|
126
|
+
port_data->settings.c_cflag |= B19200;
|
127
|
+
break;
|
128
|
+
case 38400:
|
129
|
+
port_data->settings.c_cflag |= B38400;
|
130
|
+
break;
|
131
|
+
case 57600:
|
132
|
+
port_data->settings.c_cflag |= B57600;
|
133
|
+
break;
|
134
|
+
default:
|
135
|
+
rb_raise(rb_eArgError, "baud_rate must be a valid value");
|
136
|
+
}
|
137
|
+
/* Data bits */
|
138
|
+
switch (port_data->data_bits) {
|
139
|
+
case 8:
|
140
|
+
port_data->settings.c_cflag |= CS8;
|
141
|
+
break;
|
142
|
+
case 7:
|
143
|
+
port_data->settings.c_cflag |= CS7;
|
144
|
+
break;
|
145
|
+
case 6:
|
146
|
+
port_data->settings.c_cflag |= CS6;
|
147
|
+
break;
|
148
|
+
case 5:
|
149
|
+
port_data->settings.c_cflag |= CS5;
|
150
|
+
break;
|
151
|
+
default:
|
152
|
+
rb_raise(rb_eArgError, "data_bits must be 5, 6, 7 or 8");
|
153
|
+
}
|
154
|
+
/* Parity */
|
155
|
+
if (port_data->parity) port_data->settings.c_cflag |= PARENB;
|
156
|
+
/* Stop bits */
|
157
|
+
switch (port_data->stop_bits) {
|
158
|
+
case 2:
|
159
|
+
port_data->settings.c_cflag |= CSTOPB;
|
160
|
+
break;
|
161
|
+
case 1:
|
162
|
+
break;
|
163
|
+
default:
|
164
|
+
rb_raise(rb_eArgError, "stop_bits must be 1 or 2");
|
165
|
+
}
|
166
|
+
/* Flow control */
|
167
|
+
if (port_data->hardware_flow_control) port_data->settings.c_cflag |= CNEW_RTSCTS;
|
168
|
+
/* Other settings */
|
169
|
+
port_data->settings.c_iflag = IGNPAR | ICRNL;
|
170
|
+
port_data->settings.c_oflag = 0;
|
171
|
+
port_data->settings.c_lflag = ICANON;
|
172
|
+
/* Flush input buffer */
|
173
|
+
tcflush(port_data->port_handle, TCIFLUSH);
|
174
|
+
/* Apply settings to port */
|
175
|
+
tcsetattr(port_data->port_handle, TCSANOW, &port_data->settings);
|
176
|
+
/* Done */
|
177
|
+
return Qnil;
|
178
|
+
}
|
179
|
+
|
180
|
+
/*
|
181
|
+
* Create a Port object, using the port filename specified in _port_ (e.g. '/dev/ttyS0' or 'COM1').
|
182
|
+
*
|
183
|
+
* Valid options are :baud_rate (integer), :data_bits (integer), :parity
|
184
|
+
* (boolean), and :stop_bits (integer). Default values are 9600, 8, false, and 1 respectively.
|
185
|
+
*
|
186
|
+
* call-seq:
|
187
|
+
* new(port, options = {})
|
188
|
+
*
|
189
|
+
*/
|
190
|
+
VALUE rb232_port_initialize(int argc, VALUE* argv, VALUE self) {
|
191
|
+
/* Only allow 1 or 2 arguments */
|
192
|
+
if (argc == 0 || argc >= 3) {
|
193
|
+
rb_raise(rb_eArgError, "wrong number of arguments (must be 1 or 2)");
|
194
|
+
return Qnil;
|
195
|
+
}
|
196
|
+
/* Get port name */
|
197
|
+
SafeStringValue(argv[0]);
|
198
|
+
VALUE port = argv[0];
|
199
|
+
/* Get options */
|
200
|
+
VALUE options = Qnil;
|
201
|
+
if (argc == 1)
|
202
|
+
options = rb_hash_new();
|
203
|
+
else
|
204
|
+
options = rb_convert_type(argv[1], T_HASH, "Hash", "to_hash");
|
205
|
+
/* Call real initialize function */
|
206
|
+
return rb232_port_initialize_with_options(self, port, options);
|
207
|
+
}
|
208
|
+
|
209
|
+
/*
|
210
|
+
* Get the port name (for instance, '/dev/ttyS0' or 'COM1'), as set in Port#new.
|
211
|
+
*/
|
212
|
+
VALUE rb232_port_get_port_name(VALUE self) {
|
213
|
+
/* Return baud rate */
|
214
|
+
return rb_str_new2(get_port_data(self)->port_name);
|
215
|
+
}
|
216
|
+
|
217
|
+
/*
|
218
|
+
* Get the baud rate, as set in the _options_ argument to Port#new.
|
219
|
+
*/
|
220
|
+
VALUE rb232_port_get_baud_rate(VALUE self) {
|
221
|
+
/* Return baud rate */
|
222
|
+
return rb_uint_new(get_port_data(self)->baud_rate);
|
223
|
+
}
|
224
|
+
|
225
|
+
/*
|
226
|
+
* Get the number of data bits, as set in the _options_ argument to Port#new.
|
227
|
+
*/
|
228
|
+
VALUE rb232_port_get_data_bits(VALUE self) {
|
229
|
+
/* Return baud rate */
|
230
|
+
return rb_uint_new(get_port_data(self)->data_bits);
|
231
|
+
}
|
232
|
+
|
233
|
+
/*
|
234
|
+
* Get the parity setting, as set in the _options_ argument to Port#new.
|
235
|
+
*/
|
236
|
+
VALUE rb232_port_get_parity(VALUE self) {
|
237
|
+
/* Return parity setting */
|
238
|
+
if (get_port_data(self)->parity == TRUE)
|
239
|
+
return Qtrue;
|
240
|
+
else
|
241
|
+
return Qfalse;
|
242
|
+
}
|
243
|
+
|
244
|
+
/*
|
245
|
+
* Get the number of stop bits, as set in the _options_ argument to Port#new.
|
246
|
+
*/
|
247
|
+
VALUE rb232_port_get_stop_bits(VALUE self) {
|
248
|
+
/* Return baud rate */
|
249
|
+
return rb_uint_new(get_port_data(self)->stop_bits);
|
250
|
+
}
|
251
|
+
|
252
|
+
/*
|
253
|
+
* Get the hardware flow control setting, as set in the _options_ argument to Port#new.
|
254
|
+
*/
|
255
|
+
VALUE rb232_port_get_hardware_flow_control(VALUE self) {
|
256
|
+
/* Return flow control setting */
|
257
|
+
if (get_port_data(self)->hardware_flow_control == TRUE)
|
258
|
+
return Qtrue;
|
259
|
+
else
|
260
|
+
return Qfalse;
|
261
|
+
}
|
262
|
+
|
263
|
+
/*
|
264
|
+
* Read raw data from port
|
265
|
+
*/
|
266
|
+
int rb232_port_read(VALUE self, char* buffer, VALUE count) {
|
267
|
+
int bytes_to_read = NUM2INT(count);
|
268
|
+
if (bytes_to_read > 255)
|
269
|
+
rb_raise(rb_eArgError, "can't read more than 255 bytes at once");
|
270
|
+
return read(get_port_data(self)->port_handle, buffer, bytes_to_read);
|
271
|
+
}
|
272
|
+
|
273
|
+
/*
|
274
|
+
* Read up to _count_ raw byte values from the port.
|
275
|
+
* Returns an array of values. If no data is currently available, a zero-length
|
276
|
+
* array will be returned.
|
277
|
+
* Useful for binary protocols.
|
278
|
+
* call-seq:
|
279
|
+
* read_bytes(count)
|
280
|
+
*
|
281
|
+
*/
|
282
|
+
VALUE rb232_port_read_bytes(VALUE self, VALUE count) {
|
283
|
+
char buffer[256];
|
284
|
+
int bytes_read = rb232_port_read(self, buffer, count);
|
285
|
+
VALUE data = rb_ary_new();
|
286
|
+
int i;
|
287
|
+
for (i=0; i<bytes_read; i++) {
|
288
|
+
rb_ary_push(data, INT2NUM(buffer[i]));
|
289
|
+
}
|
290
|
+
return data;
|
291
|
+
}
|
292
|
+
|
293
|
+
/*
|
294
|
+
* Read up to _count_ characters from the port.
|
295
|
+
* Returns a string. If no data is currently available, an empty string will be
|
296
|
+
* returned.
|
297
|
+
* Useful for text-based protocols.
|
298
|
+
* call-seq:
|
299
|
+
* read_string(count)
|
300
|
+
*
|
301
|
+
*/
|
302
|
+
VALUE rb232_port_read_string(VALUE self, VALUE count) {
|
303
|
+
char buffer[256];
|
304
|
+
int bytes_read = rb232_port_read(self, buffer, count);
|
305
|
+
if (bytes_read < 1) bytes_read = 0;
|
306
|
+
buffer[bytes_read] = 0;
|
307
|
+
return rb_str_new2(buffer);
|
308
|
+
}
|
data/src/port.h
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
/* module RB232 */
|
4
|
+
extern VALUE RB232;
|
5
|
+
|
6
|
+
/* class Port */
|
7
|
+
extern VALUE RB232_Port;
|
8
|
+
|
9
|
+
/* Allocator for Port class */
|
10
|
+
VALUE rb232_port_alloc(VALUE klass);
|
11
|
+
|
12
|
+
/*
|
13
|
+
* Create a Port object, using the port filename specified in _port_ (e.g. '/dev/ttyS0' or 'COM1').
|
14
|
+
*
|
15
|
+
* Valid options are :baud_rate (integer), :data_bits (integer), :parity
|
16
|
+
* (boolean), and :stop_bits (integer). Default values are 9600, 8, false, and 1 respectively.
|
17
|
+
*
|
18
|
+
* call-seq:
|
19
|
+
* new(port, options = {})
|
20
|
+
*
|
21
|
+
*/
|
22
|
+
VALUE rb232_port_initialize(int argc, VALUE* argv, VALUE self);
|
23
|
+
|
24
|
+
/*
|
25
|
+
* Get the port name (for instance, '/dev/ttyS0' or 'COM1'), as set in Port#new.
|
26
|
+
*/
|
27
|
+
VALUE rb232_port_get_port_name(VALUE self);
|
28
|
+
|
29
|
+
/*
|
30
|
+
* Get the baud rate, as set in the _options_ argument to Port#new.
|
31
|
+
*/
|
32
|
+
VALUE rb232_port_get_baud_rate(VALUE self);
|
33
|
+
|
34
|
+
/*
|
35
|
+
* Get the number of data bits, as set in the _options_ argument to Port#new.
|
36
|
+
*/
|
37
|
+
VALUE rb232_port_get_data_bits(VALUE self);
|
38
|
+
|
39
|
+
/*
|
40
|
+
* Get the parity setting, as set in the _options_ argument to Port#new.
|
41
|
+
*/
|
42
|
+
VALUE rb232_port_get_parity(VALUE self);
|
43
|
+
|
44
|
+
/*
|
45
|
+
* Get the number of stop bits, as set in the _options_ argument to Port#new.
|
46
|
+
*/
|
47
|
+
VALUE rb232_port_get_stop_bits(VALUE self);
|
48
|
+
|
49
|
+
/*
|
50
|
+
* Get the hardware flow control setting, as set in the _options_ argument to Port#new.
|
51
|
+
*/
|
52
|
+
VALUE rb232_port_get_hardware_flow_control(VALUE self);
|
53
|
+
|
54
|
+
/*
|
55
|
+
* Read _count_ raw byte values from the port.
|
56
|
+
* Returns an array of values. Useful for binary protocols.
|
57
|
+
* call-seq:
|
58
|
+
* read_bytes(count)
|
59
|
+
*
|
60
|
+
*/
|
61
|
+
VALUE rb232_port_read_bytes(VALUE self, VALUE count);
|
62
|
+
|
63
|
+
/*
|
64
|
+
* Read _count_ characters from the port.
|
65
|
+
* Returns a string. Useful for text-based protocols.
|
66
|
+
* call-seq:
|
67
|
+
* read_string(count)
|
68
|
+
*
|
69
|
+
*/
|
70
|
+
VALUE rb232_port_read_string(VALUE self, VALUE count);
|
data/src/rb232.c
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "port.h"
|
3
|
+
|
4
|
+
/*
|
5
|
+
* Serial port communications. The class RB232::Port provides access to a hardware
|
6
|
+
* port on the local machine. Currently only Linux systems are supported.
|
7
|
+
*/
|
8
|
+
void Init_rb232() {
|
9
|
+
RB232 = rb_define_module("RB232");
|
10
|
+
RB232_Port = rb_define_class_under(RB232, "Port", rb_cObject);
|
11
|
+
rb_define_alloc_func(RB232_Port, rb232_port_alloc);
|
12
|
+
rb_define_method(RB232_Port, "initialize", rb232_port_initialize, -1); /* in port.c */
|
13
|
+
rb_define_method(RB232_Port, "port_name", rb232_port_get_port_name, 0); /* in port.c */
|
14
|
+
rb_define_method(RB232_Port, "baud_rate", rb232_port_get_baud_rate, 0); /* in port.c */
|
15
|
+
rb_define_method(RB232_Port, "data_bits", rb232_port_get_data_bits, 0); /* in port.c */
|
16
|
+
rb_define_method(RB232_Port, "parity", rb232_port_get_parity, 0); /* in port.c */
|
17
|
+
rb_define_method(RB232_Port, "stop_bits", rb232_port_get_stop_bits, 0); /* in port.c */
|
18
|
+
rb_define_method(RB232_Port, "hardware_flow_control", rb232_port_get_hardware_flow_control, 0); /* in port.c */
|
19
|
+
rb_define_method(RB232_Port, "read_bytes", rb232_port_read_bytes, 1); /* in port.c */
|
20
|
+
rb_define_method(RB232_Port, "read_string", rb232_port_read_string, 1); /* in port.c */
|
21
|
+
}
|
data/src/utility.c
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#include "utility.h"
|
2
|
+
|
3
|
+
/*
|
4
|
+
* Get a key from a hash, or if it's not there, use the default.
|
5
|
+
* A bit like doing hash[key] || default_val in Ruby.
|
6
|
+
* Integer version.
|
7
|
+
*/
|
8
|
+
int rbx_int_from_hash_or_default(VALUE hash, VALUE key, int default_val) {
|
9
|
+
VALUE data = (rb_hash_aref(hash, key));
|
10
|
+
if (data == Qnil)
|
11
|
+
return default_val;
|
12
|
+
else
|
13
|
+
return NUM2INT(data);
|
14
|
+
}
|
15
|
+
|
16
|
+
/*
|
17
|
+
* Get a key from a hash, or if it's not there, use the default.
|
18
|
+
* A bit like doing hash[key] || default_val in Ruby.
|
19
|
+
* Boolean version.
|
20
|
+
*/
|
21
|
+
BOOL rbx_bool_from_hash_or_default(VALUE hash, VALUE key, BOOL default_val) {
|
22
|
+
VALUE data = (rb_hash_aref(hash, key));
|
23
|
+
if (data == Qnil)
|
24
|
+
return default_val;
|
25
|
+
else
|
26
|
+
if (data == Qtrue)
|
27
|
+
return TRUE;
|
28
|
+
else
|
29
|
+
return FALSE;
|
30
|
+
}
|
data/src/utility.h
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
#define BOOL char
|
4
|
+
#define TRUE 1
|
5
|
+
#define FALSE 0
|
6
|
+
|
7
|
+
/*
|
8
|
+
* Get a key from a hash, or if it's not there, use the default.
|
9
|
+
* A bit like doing hash[key] || default_val in Ruby.
|
10
|
+
* Integer version.
|
11
|
+
*/
|
12
|
+
int rbx_int_from_hash_or_default(VALUE hash, VALUE key, int default_val);
|
13
|
+
|
14
|
+
/*
|
15
|
+
* Get a key from a hash, or if it's not there, use the default.
|
16
|
+
* A bit like doing hash[key] || default_val in Ruby.
|
17
|
+
* Boolean version.
|
18
|
+
*/
|
19
|
+
BOOL rbx_bool_from_hash_or_default(VALUE hash, VALUE key, BOOL default_val);
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rb232
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Smith
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-15 00:00:00 +00:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: james@floppy.org.uk
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions:
|
21
|
+
- extconf.rb
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README
|
26
|
+
- COPYING
|
27
|
+
- extconf.rb
|
28
|
+
- src/port.c
|
29
|
+
- src/port.h
|
30
|
+
- src/rb232.c
|
31
|
+
- src/utility.c
|
32
|
+
- src/utility.h
|
33
|
+
- lib/rb232/text_protocol.rb
|
34
|
+
- examples/listen.rb
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://github.com/Floppy/rb232
|
37
|
+
licenses: []
|
38
|
+
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.3.5
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: A simple serial port library for Ruby
|
63
|
+
test_files: []
|
64
|
+
|