rb232 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|