Ticket #5339: serial.h

File serial.h, 11.8 KB (added by wjwwood@…, 12 years ago)
Line 
1/**
2 * @file serial.h
3 * @author William Woodall <wjwwood@gmail.com>
4 * @version 0.1
5 *
6 * @section LICENSE
7 *
8 * The MIT License
9 *
10 * Copyright (c) 2011 William Woodall
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to deal
14 * in the Software without restriction, including without limitation the rights
15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 * copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 * THE SOFTWARE.
29 *
30 * @section DESCRIPTION
31 *
32 * This provides a cross platform interface for interacting with Serial Ports.
33 */
34
35
36#ifndef SERIAL_H
37#define SERIAL_H
38
39#include <iostream>
40#include <sstream>
41#include <string>
42
43#include <boost/asio.hpp>
44#include <boost/asio/serial_port.hpp>
45#include <boost/bind.hpp>
46#include <boost/thread.hpp>
47
48// DEFINES
49#define DEFAULT_BAUDRATE 9600
50#define DEFAULT_TIMEOUT 0.0
51#define DEFAULT_BYTESIZE EIGHTBITS
52#define DEFAULT_PARITY PARITY_NONE
53#define DEFAULT_STOPBITS STOPBITS_ONE
54#define DEFAULT_FLOWCONTROL FLOWCONTROL_NONE
55
56// Serial Port settings CONSTANTS
57enum { FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS };
58enum { PARITY_NONE, PARITY_ODD, PARITY_EVEN };
59enum { STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO };
60enum { FLOWCONTROL_NONE, FLOWCONTROL_SOFTWARE, FLOWCONTROL_HARDWARE };
61
62class Serial {
63public:
64 /** Constructor, Creates a Serial object but doesn't open the serial port. */
65 Serial();
66
67 /**
68 * Constructor, creates a SerialPortBoost object and opens the port.
69 *
70 * @param port A std::string containing the address of the serial port,
71 * which would be something like 'COM1' on Windows and '/dev/ttyS0'
72 * on Linux.
73 *
74 * @param baudrate An integer that represents the buadrate
75 *
76 * @param timeout A double that represents the time (in seconds) until a
77 * timeout on reads occur. Setting this to a number less than or
78 * equal to zero will silently disable the timeout on reads.
79 *
80 * @param bytesize Size of each byte in the serial transmission of data,
81 * default is EIGHTBITS, possible values are: FIVEBITS,
82 * SIXBITS, SEVENBITS, EIGHTBITS
83 *
84 * @param parity Method of parity, default is PARITY_NONE, possible values
85 * are: PARITY_NONE, PARITY_ODD, PARITY_EVEN
86 *
87 * @param stopbits Number of stop bits used, default is STOPBITS_ONE, possible
88 * values are: STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO
89 *
90 * @param flowcontrol Type of flowcontrol used, default is FLOWCONTROL_NONE, possible
91 * values are: FLOWCONTROL_NONE, FLOWCONTROL_SOFTWARE, FLOWCONTROL_HARDWARE
92 *
93 * @throw SerialPortAlreadyOpenException
94 * @throw SerialPortFailedToOpenException
95 */
96 Serial(std::string port,
97 int baudrate = DEFAULT_BAUDRATE,
98 double timeout = DEFAULT_TIMEOUT,
99 int bytesize = DEFAULT_BYTESIZE,
100 int parity = DEFAULT_PARITY,
101 int stopbits = DEFAULT_STOPBITS,
102 int flowcontrol = DEFAULT_FLOWCONTROL);
103
104 /** Destructor */
105 ~Serial();
106
107 /**
108 * Opens the serial port as long as the portname is set and the port isn't alreay open.
109 *
110 * @throw SerialPortAlreadyOpenException
111 * @throw SerialPortFailedToOpenException
112 */
113 void open();
114
115 /** Closes the serial port and terminates threads. */
116 void close();
117
118 /** Read size bytes from the serial port.
119 * If a timeout is set it may return less characters than requested. With no timeout
120 * it will block until the requested number of bytes have been read.
121 *
122 * @param buffer A char[] of length >= the size parameter to hold incoming data.
123 *
124 * @param size An integer defining how many bytes to be read.
125 *
126 * @return An integer representing the number of bytes read.
127 */
128 int read(char* buffer, int size = 1);
129
130 /** Read size bytes from the serial port.
131 * If a timeout is set it may return less characters than requested. With no timeout
132 * it will block until the requested number of bytes have been read.
133 *
134 * @param size An integer defining how many bytes to be read.
135 *
136 * @return A std::string containing the data read.
137 */
138 std::string read(int size = 1);
139
140 /** Write length bytes from buffer to the serial port.
141 *
142 * @param data A char[] with data to be written to the serial port.
143 *
144 * @param length An integer representing the number of bytes to be written.
145 *
146 * @return An integer representing the number of bytes written.
147 */
148 int write(char data[], int length);
149
150 /** Write a string to the serial port.
151 *
152 * @param data A std::string to be written to the serial port. (must be null terminated)
153 *
154 * @return An integer representing the number of bytes written to the serial port.
155 */
156 int write(std::string data);
157
158 /** Sets the logic level of the RTS line.
159 *
160 * @param level The logic level to set the RTS to. Defaults to true.
161 */
162 void setRTS(bool level = true);
163
164 /** Sets the logic level of the DTR line.
165 *
166 * @param level The logic level to set the DTR to. Defaults to true.
167 */
168 void setDTR(bool level = true);
169
170 /** Gets the status of the CTS line.
171 *
172 * @return A boolean value that represents the current logic level of the CTS line.
173 */
174 bool getCTS();
175
176 /** Gets the status of the DSR line.
177 *
178 * @return A boolean value that represents the current logic level of the DSR line.
179 */
180 bool getDSR();
181
182 /** Sets the timeout for reads in seconds.
183 *
184 * @param timeout A long that specifies how long the read timeout is in seconds.
185 */
186 void setTimeoutMilliseconds(long timeout);
187
188 /** Gets the timeout for reads in seconds.
189 *
190 * @return A long that specifies how long the read timeout is in seconds.
191 */
192 long getTimeoutMilliseconds();
193
194 /** Sets the baudrate for the serial port.
195 *
196 * @param baudrate An integer that sets the baud rate for the serial port.
197 */
198 void setBaudrate(int baudrate);
199
200 /** Gets the baudrate for the serial port.
201 *
202 * @return An integer that sets the baud rate for the serial port.
203 */
204 int getBaudrate();
205
206 /** Sets the bytesize for the serial port.
207 *
208 * @param bytesize Size of each byte in the serial transmission of data,
209 * default is EIGHTBITS, possible values are: FIVEBITS,
210 * SIXBITS, SEVENBITS, EIGHTBITS
211 */
212 void setBytesize(int bytesize);
213
214 /** Gets the bytesize for the serial port.
215 *
216 * @return Size of each byte in the serial transmission of data,
217 * default is EIGHTBITS, possible values are: FIVEBITS,
218 * SIXBITS, SEVENBITS, EIGHTBITS
219 */
220 int getBytesize();
221
222 /** Sets the parity for the serial port.
223 *
224 * @param parity Method of parity, default is PARITY_NONE, possible values
225 * are: PARITY_NONE, PARITY_ODD, PARITY_EVEN
226 */
227 void setParity(int parity);
228
229 /** Gets the parity for the serial port.
230 *
231 * @return Method of parity, default is PARITY_NONE, possible values
232 * are: PARITY_NONE, PARITY_ODD, PARITY_EVEN
233 */
234 int getParity();
235
236 /** Sets the stopbits for the serial port.
237 *
238 * @param stopbits Number of stop bits used, default is STOPBITS_ONE, possible
239 * values are: STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO
240 */
241 void setStopbits(int stopbits);
242
243 /** Gets the stopbits for the serial port.
244 *
245 * @return Number of stop bits used, default is STOPBITS_ONE, possible
246 * values are: STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO
247 */
248 int getStopbits();
249
250 /** Sets the flow control for the serial port.
251 *
252 * @param flowcontrol Type of flowcontrol used, default is FLOWCONTROL_NONE, possible
253 * values are: FLOWCONTROL_NONE, FLOWCONTROL_SOFTWARE, FLOWCONTROL_HARDWARE
254 */
255 void setFlowcontrol(int flowcontrol);
256
257 /** Gets the flow control for the serial port.
258 *
259 * @return Type of flowcontrol used, default is FLOWCONTROL_NONE, possible
260 * values are: FLOWCONTROL_NONE, FLOWCONTROL_SOFTWARE, FLOWCONTROL_HARDWARE
261 */
262 int getFlowcontrol();
263private:
264 void init();
265 void read_complete(const boost::system::error_code& error, std::size_t bytes_transferred);
266 void timeout_callback(const boost::system::error_code& error);
267
268 boost::asio::io_service io_service;
269
270 boost::asio::io_service::work * work;
271
272 boost::asio::serial_port * serial_port;
273
274 boost::asio::deadline_timer * timeout_timer;
275
276 std::string port;
277 boost::asio::serial_port_base::baud_rate * baudrate;
278 boost::posix_time::time_duration * timeout;
279 boost::asio::serial_port_base::character_size * bytesize;
280 boost::asio::serial_port_base::parity * parity;
281 boost::asio::serial_port_base::stop_bits * stopbits;
282 boost::asio::serial_port_base::flow_control * flowcontrol;
283
284 int bytes_read;
285 int bytes_to_read;
286 bool reading;
287};
288
289class SerialPortAlreadyOpenException : public std::exception {
290 const char * port;
291public:
292 SerialPortAlreadyOpenException(const char * port) {this->port = port;}
293
294 virtual const char* what() const throw() {
295 std::stringstream ss;
296 ss << "Serial Port already open: " << this->port;
297 return ss.str().c_str();
298 }
299};
300
301class SerialPortFailedToOpenException : public std::exception {
302 const char * e_what;
303public:
304 SerialPortFailedToOpenException(const char * e_what) {this->e_what = e_what;}
305
306 virtual const char* what() const throw() {
307 std::stringstream ss;
308 ss << "Serial Port failed to open: " << this->e_what;
309 return ss.str().c_str();
310 }
311};
312
313class InvalidBytesizeException : public std::exception {
314 int bytesize;
315public:
316 InvalidBytesizeException(int bytesize) {this->bytesize = bytesize;}
317
318 virtual const char* what() const throw() {
319 std::stringstream ss;
320 ss << "Invalid bytesize provided: " << this->bytesize;
321 return ss.str().c_str();
322 }
323};
324
325class InvalidParityException : public std::exception {
326 int parity;
327public:
328 InvalidParityException(int parity) {this->parity = parity;}
329
330 virtual const char* what() const throw() {
331 std::stringstream ss;
332 ss << "Invalid parity provided: " << this->parity;
333 return ss.str().c_str();
334 }
335};
336
337class InvalidStopbitsException : public std::exception {
338 int stopbits;
339public:
340 InvalidStopbitsException(int stopbits) {this->stopbits = stopbits;}
341
342 virtual const char* what() const throw() {
343 std::stringstream ss;
344 ss << "Invalid stopbits provided: " << this->stopbits;
345 return ss.str().c_str();
346 }
347};
348
349class InvalidFlowcontrolException : public std::exception {
350 int flowcontrol;
351public:
352 InvalidFlowcontrolException(int flowcontrol) {this->flowcontrol = flowcontrol;}
353
354 virtual const char* what() const throw() {
355 std::stringstream ss;
356 ss << "Invalid flowcontrol provided: " << this->flowcontrol;
357 return ss.str().c_str();
358 }
359};
360
361#endif