mirror of
https://github.com/wjwwood/serial.git
synced 2026-01-22 11:44:53 +08:00
Merge branch 'boostless' of https://github.com/wjwwood/serial into boostless
Conflicts: include/serial/serial_listener.h
This commit is contained in:
commit
214b763664
5
Makefile
5
Makefile
@ -1,10 +1,9 @@
|
||||
# ash_gti's dumb downed makefile so I can more easily test stuff
|
||||
# # ash_gti's dumb downed makefile so I can more easily test stuff
|
||||
# CXX=clang++
|
||||
# CXXFLAGS=-g -I./include
|
||||
# CXXFLAGS=-g -I./include -ferror-limit=5 -O3 -Wall -Weffc++ -pedantic -pedantic-errors -Wextra -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment -Wconversion -Wdisabled-optimization -Wfloat-equal -Wformat -Wformat=2 -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wimplicit -Wimport -Winit-self -Winline -Winvalid-pch -Wlong-long -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wpacked -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wstack-protector -Wstrict-aliasing -Wstrict-aliasing=2 -Wswitch -Wswitch-default -Wswitch-enum -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvolatile-register-var -Wwrite-strings
|
||||
#
|
||||
# test: tests/serial_tests.o src/serial.o src/impl/unix.o
|
||||
# $(CXX) -o test tests/serial_tests.o src/serial.o src/impl/unix.o
|
||||
#
|
||||
ifdef ROS_ROOT
|
||||
include $(shell rospack find mk)/cmake.mk
|
||||
else
|
||||
|
||||
@ -49,13 +49,13 @@ Setup workspace (skip if you already have one):
|
||||
rosws init some_ros_workspace
|
||||
cd some_ros_workspace
|
||||
source setup.bash
|
||||
|
||||
|
||||
Add the rosinstall entry for this stack:
|
||||
|
||||
|
||||
echo "-git: {local-name: serial, uri: 'https://github.com/wjwwood/serial.git', version: 'master'}" >> .rosinstall
|
||||
|
||||
|
||||
Rerun rosinstall:
|
||||
|
||||
|
||||
rosinstall .
|
||||
source setup.bash
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 William Woodall
|
||||
* Copyright (c) 2011 William Woodall, John Harrison
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@ -30,7 +30,9 @@
|
||||
*
|
||||
* \section DESCRIPTION
|
||||
*
|
||||
* This provides a unix based pimpl for the Serial class.
|
||||
* This provides a unix based pimpl for the Serial class. This implementation is
|
||||
* based off termios.h and uses select for multiplexing the IO ports.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SERIAL_IMPL_UNIX_H
|
||||
@ -42,6 +44,7 @@ namespace serial {
|
||||
|
||||
using std::string;
|
||||
using std::invalid_argument;
|
||||
|
||||
using serial::SerialExecption;
|
||||
using serial::IOException;
|
||||
|
||||
@ -57,47 +60,98 @@ public:
|
||||
|
||||
virtual ~SerialImpl ();
|
||||
|
||||
void open ();
|
||||
void close () ;
|
||||
bool isOpen () const;
|
||||
void
|
||||
open ();
|
||||
|
||||
size_t available ();
|
||||
string read (size_t size = 1);
|
||||
size_t write (const string &data);
|
||||
void
|
||||
close ();
|
||||
|
||||
void flush ();
|
||||
void flushInput ();
|
||||
void flushOutput ();
|
||||
bool
|
||||
isOpen () const;
|
||||
|
||||
void sendBreak(int duration);
|
||||
void setBreak(bool level);
|
||||
void setRTS(bool level);
|
||||
void setDTR(bool level);
|
||||
bool getCTS();
|
||||
bool getDSR();
|
||||
bool getRI();
|
||||
bool getCD();
|
||||
size_t
|
||||
available ();
|
||||
|
||||
void setPort (const string &port);
|
||||
string getPort () const;
|
||||
size_t
|
||||
read (char* buf, size_t size = 1);
|
||||
|
||||
void setTimeout (long timeout);
|
||||
long getTimeout () const;
|
||||
size_t
|
||||
write (const string &data);
|
||||
|
||||
void setBaudrate (unsigned long baudrate);
|
||||
unsigned long getBaudrate () const;
|
||||
void
|
||||
flush ();
|
||||
|
||||
void setBytesize (bytesize_t bytesize);
|
||||
bytesize_t getBytesize () const;
|
||||
void
|
||||
flushInput ();
|
||||
|
||||
void setParity (parity_t parity);
|
||||
parity_t getParity () const;
|
||||
void
|
||||
flushOutput ();
|
||||
|
||||
void setStopbits (stopbits_t stopbits);
|
||||
stopbits_t getStopbits () const;
|
||||
void
|
||||
sendBreak(int duration);
|
||||
|
||||
void setFlowcontrol (flowcontrol_t flowcontrol);
|
||||
flowcontrol_t getFlowcontrol () const;
|
||||
void
|
||||
setBreak(bool level);
|
||||
|
||||
void
|
||||
setRTS(bool level);
|
||||
|
||||
void
|
||||
setDTR(bool level);
|
||||
|
||||
bool
|
||||
getCTS();
|
||||
|
||||
bool
|
||||
getDSR();
|
||||
|
||||
bool
|
||||
getRI();
|
||||
|
||||
bool
|
||||
getCD();
|
||||
|
||||
void
|
||||
setPort (const string &port);
|
||||
|
||||
string
|
||||
getPort () const;
|
||||
|
||||
void
|
||||
setTimeout (long timeout);
|
||||
|
||||
long
|
||||
getTimeout () const;
|
||||
|
||||
void
|
||||
setBaudrate (unsigned long baudrate);
|
||||
|
||||
unsigned long
|
||||
getBaudrate () const;
|
||||
|
||||
void
|
||||
setBytesize (bytesize_t bytesize);
|
||||
|
||||
bytesize_t
|
||||
getBytesize () const;
|
||||
|
||||
void
|
||||
setParity (parity_t parity);
|
||||
|
||||
parity_t
|
||||
getParity () const;
|
||||
|
||||
void
|
||||
setStopbits (stopbits_t stopbits);
|
||||
|
||||
stopbits_t
|
||||
getStopbits () const;
|
||||
|
||||
void
|
||||
setFlowcontrol (flowcontrol_t flowcontrol);
|
||||
|
||||
flowcontrol_t
|
||||
getFlowcontrol () const;
|
||||
|
||||
protected:
|
||||
void reconfigurePort ();
|
||||
@ -106,17 +160,13 @@ private:
|
||||
string port_; // Path to the file descriptor
|
||||
int fd_; // The current file descriptor
|
||||
|
||||
int interCharTimeout_;
|
||||
int writeTimeout_;
|
||||
bool isOpen_;
|
||||
bool xonxoff_;
|
||||
bool rtscts_;
|
||||
|
||||
char ___; // lol padding
|
||||
|
||||
long timeout_; // Timeout for read operations
|
||||
unsigned long baudrate_; // Baudrate
|
||||
|
||||
|
||||
parity_t parity_; // Parity
|
||||
bytesize_t bytesize_; // Size of the bytes
|
||||
stopbits_t stopbits_; // Stop Bits
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
*
|
||||
* Copyright (c) 2011 William Woodall
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
@ -24,8 +24,8 @@
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* \section DESCRIPTION
|
||||
@ -124,35 +124,38 @@ class Serial {
|
||||
public:
|
||||
/*!
|
||||
* Constructor, creates a SerialPortBoost object and opens the port.
|
||||
*
|
||||
*
|
||||
* \param port A std::string containing the address of the serial port,
|
||||
* which would be something like 'COM1' on Windows and '/dev/ttyS0'
|
||||
* on Linux.
|
||||
*
|
||||
*
|
||||
* \param baudrate An integer that represents the buadrate
|
||||
*
|
||||
* \param timeout A long that represents the time (in milliseconds) until a
|
||||
*
|
||||
* \param timeout A long that represents the time (in milliseconds) until a
|
||||
* timeout on reads occur. Setting this to zero (0) will cause reading to
|
||||
* be non-blocking, i.e. the available data will be returned immediately,
|
||||
* but it will not block to wait for more. Setting this to a number less
|
||||
* than zero (-1) will result in infinite blocking behaviour, i.e. the
|
||||
* serial port will block until either size bytes have been read or an
|
||||
* exception has occured.
|
||||
*
|
||||
* \param bytesize Size of each byte in the serial transmission of data,
|
||||
* default is EIGHTBITS, possible values are: FIVEBITS, SIXBITS, SEVENBITS,
|
||||
*
|
||||
* \param bytesize Size of each byte in the serial transmission of data,
|
||||
* default is EIGHTBITS, possible values are: FIVEBITS, SIXBITS, SEVENBITS,
|
||||
* EIGHTBITS
|
||||
*
|
||||
*
|
||||
* \param parity Method of parity, default is PARITY_NONE, possible values
|
||||
* are: PARITY_NONE, PARITY_ODD, PARITY_EVEN
|
||||
*
|
||||
* \param stopbits Number of stop bits used, default is STOPBITS_ONE,
|
||||
*
|
||||
* \param stopbits Number of stop bits used, default is STOPBITS_ONE,
|
||||
* possible values are: STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO
|
||||
*
|
||||
* \param flowcontrol Type of flowcontrol used, default is
|
||||
* FLOWCONTROL_NONE, possible values are: FLOWCONTROL_NONE,
|
||||
*
|
||||
* \param flowcontrol Type of flowcontrol used, default is
|
||||
* FLOWCONTROL_NONE, possible values are: FLOWCONTROL_NONE,
|
||||
* FLOWCONTROL_SOFTWARE, FLOWCONTROL_HARDWARE
|
||||
*
|
||||
*
|
||||
* \param buffer_size The maximum size of the internal buffer, defaults
|
||||
* to 256 bytes (2^8).
|
||||
*
|
||||
* \throw PortNotOpenedException
|
||||
*/
|
||||
Serial (const std::string &port = "",
|
||||
@ -161,7 +164,8 @@ public:
|
||||
bytesize_t bytesize = EIGHTBITS,
|
||||
parity_t parity = PARITY_NONE,
|
||||
stopbits_t stopbits = STOPBITS_ONE,
|
||||
flowcontrol_t flowcontrol = FLOWCONTROL_NONE);
|
||||
flowcontrol_t flowcontrol = FLOWCONTROL_NONE,
|
||||
const size_t buffer_size = 256);
|
||||
|
||||
/*! Destructor */
|
||||
virtual ~Serial ();
|
||||
@ -169,12 +173,12 @@ public:
|
||||
/*!
|
||||
* Opens the serial port as long as the portname is set and the port isn't
|
||||
* alreay open.
|
||||
*
|
||||
* If the port is provided to the constructor then an explicit call to open
|
||||
*
|
||||
* If the port is provided to the constructor then an explicit call to open
|
||||
* is not needed.
|
||||
*
|
||||
*
|
||||
* \see Serial::Serial
|
||||
*
|
||||
*
|
||||
* \throw std::invalid_argument
|
||||
* \throw serial::SerialExecption
|
||||
* \throw serial::IOException
|
||||
@ -183,7 +187,7 @@ public:
|
||||
open ();
|
||||
|
||||
/*! Gets the open status of the serial port.
|
||||
*
|
||||
*
|
||||
* \return Returns true if the port is open, false otherwise.
|
||||
*/
|
||||
bool
|
||||
@ -198,70 +202,48 @@ public:
|
||||
available();
|
||||
|
||||
/*! Read a given amount of bytes from the serial port.
|
||||
*
|
||||
*
|
||||
* If a timeout is set it may return less characters than requested. With
|
||||
* no timeout it will block until the requested number of bytes have been
|
||||
* read or until an exception occurs.
|
||||
*
|
||||
* \param buffer An unsigned char array large enough to hold incoming data
|
||||
* up to the requested size.
|
||||
*
|
||||
*
|
||||
* \param size A size_t defining how many bytes to be read.
|
||||
*
|
||||
* \return A size_t representing the number of bytes actually read.
|
||||
*/
|
||||
//size_t
|
||||
//read (unsigned char* buffer, size_t size = 1);
|
||||
|
||||
/*! Read a given amount of bytes from the serial port.
|
||||
*
|
||||
* If a timeout is set it may return less characters than requested. With
|
||||
* no timeout it will block until the requested number of bytes have been
|
||||
* read or until an exception occurs.
|
||||
*
|
||||
* \param size A size_t defining how many bytes to be read.
|
||||
*
|
||||
*
|
||||
* \return A std::string containing the data read.
|
||||
*/
|
||||
std::string
|
||||
read (size_t size = 1);
|
||||
|
||||
std::string readline(size_t size = std::numeric_limits<std::size_t>::max(),
|
||||
std::string eol = "\n");
|
||||
|
||||
std::vector<std::string> readlines(std::string eol = "\n");
|
||||
|
||||
/*! Read a given amount of bytes from the serial port.
|
||||
*
|
||||
* Reads into a std::string by reference rather than returning it.
|
||||
*
|
||||
* \param buffer A std::string reference for reading to.
|
||||
* \param size A size_t defining how many bytes to be read.
|
||||
*
|
||||
* \return A size_t that represents how many bytes were read.
|
||||
*
|
||||
* \see Serial::read(size_t)
|
||||
/*! Reads in a line or until a given delimiter has been processed
|
||||
*
|
||||
* Reads from the serial port until a single line has been read.
|
||||
*
|
||||
* \param size A maximum length of a line defaults to size_t::max()
|
||||
* \param eol A string to match against for the EOL.
|
||||
*
|
||||
* \return A std::string containing the line.
|
||||
*/
|
||||
//size_t
|
||||
//read (std::string &buffer, size_t size = 1);
|
||||
std::string
|
||||
readline(size_t size = std::numeric_limits<std::size_t>::max(),
|
||||
std::string eol = "\n");
|
||||
|
||||
/*! Write bytes from the data to the serial port by given length.
|
||||
*
|
||||
* \param data An unsigned char array containing data to be written to the
|
||||
* serial port.
|
||||
*
|
||||
* \param length A size_t representing the number of bytes to be written.
|
||||
*
|
||||
* \return A size_t representing the number of bytes actually written.
|
||||
/*! Reads in multiple lines until the serail port times out.
|
||||
*
|
||||
* This requires a timeout > 0 before it can be run. It will read until a
|
||||
* timeout occurs and return a list of strings.
|
||||
*
|
||||
* \param eol A string to match against for the EOL.
|
||||
*
|
||||
* \return A vector<string> containing the lines.
|
||||
*/
|
||||
//size_t
|
||||
//write (unsigned char* data, size_t length);
|
||||
std::vector<std::string>
|
||||
readlines(std::string eol = "\n");
|
||||
|
||||
/*! Write a string to the serial port.
|
||||
*
|
||||
* \param data A const std::string reference containg the data to be written
|
||||
*
|
||||
* \param data A const std::string reference containg the data to be written
|
||||
* to the serial port.
|
||||
*
|
||||
*
|
||||
* \return A size_t representing the number of bytes actually written to
|
||||
* the serial port.
|
||||
*/
|
||||
@ -269,27 +251,27 @@ public:
|
||||
write (const std::string &data);
|
||||
|
||||
/*! Sets the serial port identifier.
|
||||
*
|
||||
* \param port A const std::string reference containing the address of the
|
||||
* serial port, which would be something like 'COM1' on Windows and
|
||||
*
|
||||
* \param port A const std::string reference containing the address of the
|
||||
* serial port, which would be something like 'COM1' on Windows and
|
||||
* '/dev/ttyS0' on Linux.
|
||||
*
|
||||
*
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
void
|
||||
setPort (const std::string &port);
|
||||
|
||||
/*! Gets the serial port identifier.
|
||||
*
|
||||
*
|
||||
* \see Serial::setPort
|
||||
*
|
||||
*
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
std::string
|
||||
getPort () const;
|
||||
|
||||
/*! Sets the timeout for reads in milliseconds.
|
||||
*
|
||||
*
|
||||
* \param timeout A long that represents the time (in milliseconds) until a
|
||||
* timeout on reads occur. Setting this to zero (0) will cause reading to be
|
||||
* non-blocking, i.e. the available data will be returned immediately, but it
|
||||
@ -302,127 +284,151 @@ public:
|
||||
setTimeout (long timeout);
|
||||
|
||||
/*! Gets the timeout for reads in seconds.
|
||||
*
|
||||
*
|
||||
* \see Serial::setTimeout
|
||||
*/
|
||||
long
|
||||
getTimeout () const;
|
||||
|
||||
/*! Sets the baudrate for the serial port.
|
||||
*
|
||||
*
|
||||
* Possible baudrates depends on the system but some safe baudrates include:
|
||||
* 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000,
|
||||
* 57600, 115200
|
||||
* Some other baudrates that are supported by some comports:
|
||||
* 128000, 153600, 230400, 256000, 460800, 921600
|
||||
*
|
||||
*
|
||||
* \param baudrate An integer that sets the baud rate for the serial port.
|
||||
*
|
||||
*
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
void
|
||||
setBaudrate (unsigned long baudrate);
|
||||
|
||||
/*! Gets the baudrate for the serial port.
|
||||
*
|
||||
*
|
||||
* \return An integer that sets the baud rate for the serial port.
|
||||
*
|
||||
*
|
||||
* \see Serial::setBaudrate
|
||||
*
|
||||
*
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
unsigned long
|
||||
getBaudrate () const;
|
||||
|
||||
/*! Sets the bytesize for the serial port.
|
||||
*
|
||||
*
|
||||
* \param bytesize Size of each byte in the serial transmission of data,
|
||||
* default is EIGHTBITS, possible values are: FIVEBITS, SIXBITS, SEVENBITS,
|
||||
* EIGHTBITS
|
||||
*
|
||||
*
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
void
|
||||
setBytesize (bytesize_t bytesize);
|
||||
|
||||
/*! Gets the bytesize for the serial port.
|
||||
*
|
||||
*
|
||||
* \see Serial::setBytesize
|
||||
*
|
||||
*
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
bytesize_t
|
||||
getBytesize () const;
|
||||
|
||||
/*! Sets the parity for the serial port.
|
||||
*
|
||||
*
|
||||
* \param parity Method of parity, default is PARITY_NONE, possible values
|
||||
* are: PARITY_NONE, PARITY_ODD, PARITY_EVEN
|
||||
*
|
||||
*
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
void
|
||||
setParity (parity_t parity);
|
||||
|
||||
/*! Gets the parity for the serial port.
|
||||
*
|
||||
*
|
||||
* \see Serial::setParity
|
||||
*
|
||||
*
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
parity_t
|
||||
getParity () const;
|
||||
|
||||
/*! Sets the stopbits for the serial port.
|
||||
*
|
||||
*
|
||||
* \param stopbits Number of stop bits used, default is STOPBITS_ONE,
|
||||
* possible values are: STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO
|
||||
*
|
||||
*
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
void
|
||||
setStopbits (stopbits_t stopbits);
|
||||
|
||||
/*! Gets the stopbits for the serial port.
|
||||
*
|
||||
*
|
||||
* \see Serial::setStopbits
|
||||
*
|
||||
*
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
stopbits_t
|
||||
getStopbits () const;
|
||||
|
||||
/*! Sets the flow control for the serial port.
|
||||
*
|
||||
*
|
||||
* \param flowcontrol Type of flowcontrol used, default is FLOWCONTROL_NONE,
|
||||
* possible values are: FLOWCONTROL_NONE, FLOWCONTROL_SOFTWARE,
|
||||
* FLOWCONTROL_HARDWARE
|
||||
*
|
||||
*
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
void
|
||||
setFlowcontrol (flowcontrol_t flowcontrol);
|
||||
|
||||
/*! Gets the flow control for the serial port.
|
||||
*
|
||||
*
|
||||
* \see Serial::setFlowcontrol
|
||||
*
|
||||
*
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
flowcontrol_t
|
||||
getFlowcontrol () const;
|
||||
|
||||
void flush();
|
||||
void flushInput();
|
||||
void flushOutput();
|
||||
void sendBreak(int duration);
|
||||
void setBreak(bool level = true);
|
||||
void setRTS(bool level = true);
|
||||
void setDTR(bool level = true);
|
||||
bool getCTS();
|
||||
bool getDSR();
|
||||
bool getRI();
|
||||
bool getCD();
|
||||
/*! Flush the input and output buffers */
|
||||
void
|
||||
flush ();
|
||||
|
||||
/*! Flush only the input buffer */
|
||||
void
|
||||
flushInput ();
|
||||
|
||||
/*! Flush only the output buffer */
|
||||
void
|
||||
flushOutput ();
|
||||
|
||||
void
|
||||
sendBreak (int duration);
|
||||
|
||||
void
|
||||
setBreak (bool level = true);
|
||||
|
||||
void
|
||||
setRTS (bool level = true);
|
||||
|
||||
void
|
||||
setDTR (bool level = true);
|
||||
|
||||
bool
|
||||
getCTS ();
|
||||
|
||||
bool
|
||||
getDSR ();
|
||||
|
||||
bool
|
||||
getRI ();
|
||||
|
||||
bool
|
||||
getCD ();
|
||||
|
||||
private:
|
||||
// Disable copy constructors
|
||||
@ -430,9 +436,12 @@ private:
|
||||
void operator=(const Serial&);
|
||||
const Serial& operator=(Serial);
|
||||
|
||||
const size_t buffer_size_;
|
||||
char *read_cache_; //!< Cache for doing reads in chunks.
|
||||
|
||||
// Pimpl idiom, d_pointer
|
||||
class SerialImpl;
|
||||
SerialImpl *pimpl;
|
||||
SerialImpl *pimpl_;
|
||||
};
|
||||
|
||||
} // namespace serial
|
||||
|
||||
@ -9,11 +9,11 @@
|
||||
*
|
||||
* Copyright (c) 2011 William Woodall
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
@ -23,14 +23,14 @@
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* \section DESCRIPTION
|
||||
*
|
||||
* This provides a class that allows for asynchronous serial port reading.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SERIAL_LISTENER_H
|
||||
@ -53,14 +53,14 @@ namespace serial {
|
||||
|
||||
/*!
|
||||
* This is an alias to boost::shared_ptr<const std::string> used for tokens.
|
||||
*
|
||||
*
|
||||
* This is the type used internally and is the type returned in a vector by
|
||||
* the tokenizer. The shared_ptr allows for the token to be stored and kept
|
||||
* around long enough to be used by the comparators and callbacks, but no
|
||||
* longer. This internal storage is passed as a const std::string reference
|
||||
* to callbacks, like the DataCallback function type, to prevent implicit
|
||||
* copying.
|
||||
*
|
||||
*
|
||||
* \see serial::TokenizerType, serial::SerialListener::setTokenizer
|
||||
*/
|
||||
typedef boost::shared_ptr<const std::string> TokenPtr;
|
||||
@ -69,11 +69,11 @@ typedef boost::shared_ptr<const std::string> TokenPtr;
|
||||
* This is a general function type that is used as the callback prototype
|
||||
* for asynchronous functions like the default handler callback and the
|
||||
* listenFor callbacks.
|
||||
*
|
||||
*
|
||||
* The function takes a std::string reference and returns nothing, it is
|
||||
* simply passing the resulting line detected by the comparator to the user's
|
||||
* callback for processing.
|
||||
*
|
||||
*
|
||||
* \see SerialListener::listenFor, SerialListener::setDefaultHandler
|
||||
*/
|
||||
typedef boost::function<void(const std::string&)> DataCallback;
|
||||
@ -81,11 +81,11 @@ typedef boost::function<void(const std::string&)> DataCallback;
|
||||
/*!
|
||||
* This is a general function type that is used as the comparator callback
|
||||
* prototpe for the listenFor* type functions.
|
||||
*
|
||||
*
|
||||
* The function takes a std::string reference and returns true if the string
|
||||
* matches what the comparator is looking for and false if it does not, unless
|
||||
* otherwise specified.
|
||||
*
|
||||
*
|
||||
* \see SerialListener::listenFor, SerialListener::listenForOnce
|
||||
*/
|
||||
typedef boost::function<bool(const std::string&)> ComparatorType;
|
||||
@ -115,30 +115,30 @@ TokenizerType;
|
||||
|
||||
/*!
|
||||
* This function type describes the prototype for the exception callback.
|
||||
*
|
||||
* The function takes a std::exception reference and returns nothing. It is
|
||||
*
|
||||
* The function takes a std::exception reference and returns nothing. It is
|
||||
* called from the library when an exception occurs in a library thread.
|
||||
* This exposes these exceptions to the user so they can to error handling.
|
||||
*
|
||||
*
|
||||
* \see SerialListener::setExceptionHandler
|
||||
*/
|
||||
typedef boost::function<void(const std::exception&)> ExceptionCallback;
|
||||
|
||||
/*!
|
||||
* Represents a filter which new data is passed through.
|
||||
*
|
||||
* The filter consists of a comparator and a callback. The comparator takes a
|
||||
* token and returns true if it matches, false if it doesn't. If a match
|
||||
* occurs the serial listener will dispatch a call of the callback with the
|
||||
* matched data in a another thread. The comparator should be as short as
|
||||
* possible, but the callback can be longer since it is executed in a thread
|
||||
*
|
||||
* The filter consists of a comparator and a callback. The comparator takes a
|
||||
* token and returns true if it matches, false if it doesn't. If a match
|
||||
* occurs the serial listener will dispatch a call of the callback with the
|
||||
* matched data in a another thread. The comparator should be as short as
|
||||
* possible, but the callback can be longer since it is executed in a thread
|
||||
* or thread pool.
|
||||
*
|
||||
* \param comparator A ComparatorType that matches incoming data, returns true
|
||||
*
|
||||
* \param comparator A ComparatorType that matches incoming data, returns true
|
||||
* for a match, false othewise.
|
||||
*
|
||||
*
|
||||
* \param callback A DataCallback that gets called when a match occurs.
|
||||
*
|
||||
*
|
||||
* \see serial::ComparatorType, serial::DataCallback, serial::FilterPtr
|
||||
*/
|
||||
class Filter
|
||||
@ -154,11 +154,11 @@ public:
|
||||
|
||||
/*!
|
||||
* This is an alias to boost::shared_ptr<Filter> used for tokens.
|
||||
*
|
||||
*
|
||||
* This is used internally and is returned from SerialListener::listenFor like
|
||||
* functions so that users can later remove those filters by passing the
|
||||
* FilterPtr.
|
||||
*
|
||||
*
|
||||
* \see serial::Filter, serial::SerialListener::listenFor,
|
||||
* serial::SerialListener::listenForOnce
|
||||
*/
|
||||
@ -169,7 +169,7 @@ class BlockingFilter;
|
||||
/*!
|
||||
* Shared Pointer of BlockingFilter, returned by
|
||||
* SerialListener::createBlockingFilter.
|
||||
*
|
||||
*
|
||||
* \see serial::BlockingFilter, SerialListener::createBlockingFilter
|
||||
*/
|
||||
typedef boost::shared_ptr<BlockingFilter> BlockingFilterPtr;
|
||||
@ -179,16 +179,16 @@ class BufferedFilter;
|
||||
/*!
|
||||
* Shared Pointer of BufferedFilter, returned by
|
||||
* SerialListener::createBufferedFilter.
|
||||
*
|
||||
*
|
||||
* \see serial::BufferedFilter, SerialListener::createBufferedFilter
|
||||
*/
|
||||
typedef boost::shared_ptr<BufferedFilter> BufferedFilterPtr;
|
||||
|
||||
/*!
|
||||
* This is a general exception generated by the SerialListener class.
|
||||
*
|
||||
*
|
||||
* Check the SerialListenerException::what function for the cause.
|
||||
*
|
||||
*
|
||||
* \param e_what is a std::string that describes the cause of the error.
|
||||
*/
|
||||
class SerialListenerException : public std::exception {
|
||||
@ -261,11 +261,11 @@ public:
|
||||
popped_value=the_queue.front();
|
||||
the_queue.pop();
|
||||
}
|
||||
|
||||
|
||||
size_t size() const {
|
||||
return the_queue.size();
|
||||
}
|
||||
|
||||
|
||||
void cancel() {
|
||||
the_condition_variable.notify_one();
|
||||
}
|
||||
@ -298,14 +298,14 @@ public:
|
||||
|
||||
/*!
|
||||
* Sets the tokenizer to be used when tokenizing the data into tokens.
|
||||
*
|
||||
* This function is given a std::string of data and is responsible for
|
||||
*
|
||||
* This function is given a std::string of data and is responsible for
|
||||
* tokenizing that data into a std::vector<TokenPtr> of data tokens.
|
||||
* The default tokenizer splits the data by the ascii return carriage.
|
||||
* The user can create their own tokenizer or use one of the default ones.
|
||||
*
|
||||
*
|
||||
* \param tokenizer Function for tokenizing the incoming data.
|
||||
*
|
||||
*
|
||||
* \see serial::TokenizerType, serial::delimeter_tokenizer
|
||||
*/
|
||||
void
|
||||
@ -315,7 +315,7 @@ public:
|
||||
|
||||
/*!
|
||||
* Sets the number of bytes to be read at a time by the listener.
|
||||
*
|
||||
*
|
||||
* \param chunk_size Number of bytes to be read at a time.
|
||||
*/
|
||||
void
|
||||
@ -327,8 +327,8 @@ public:
|
||||
|
||||
/*!
|
||||
* Starts a thread to listen for messages and process them through filters.
|
||||
*
|
||||
* \param serial_port Pointer to a serial::Serial object that is used to
|
||||
*
|
||||
* \param serial_port Pointer to a serial::Serial object that is used to
|
||||
* retrieve new data.
|
||||
*/
|
||||
void
|
||||
@ -336,8 +336,8 @@ public:
|
||||
|
||||
/*!
|
||||
* Stops the listening thread and blocks until it completely stops.
|
||||
*
|
||||
* This function also clears all of the active filters from listenFor and
|
||||
*
|
||||
* This function also clears all of the active filters from listenFor and
|
||||
* similar functions.
|
||||
*/
|
||||
void
|
||||
@ -347,21 +347,21 @@ public:
|
||||
|
||||
/*!
|
||||
* Creates a filter that calls a callback when the comparator returns true.
|
||||
*
|
||||
*
|
||||
* The user provides a comparator and a callback, and every time a line is
|
||||
* received the comparator is called and the comparator has to evaluate the
|
||||
* line and return true if it matches and false if it doesn't. If it does
|
||||
* match, the callback is called with the resulting line.
|
||||
*
|
||||
*
|
||||
* \param comparator This is a comparator for detecting if a line matches.
|
||||
* The comparartor receives a std::string reference and must return a true
|
||||
* if it matches and false if it doesn't.
|
||||
*
|
||||
*
|
||||
* \param callback This is the handler for when a match occurs. It is given
|
||||
* a std::string reference of the line that matched your comparator.
|
||||
*
|
||||
*
|
||||
* \return boost::shared_ptr<Filter> so you can remove it later.
|
||||
*
|
||||
*
|
||||
* \see SerialListener::removeFilter
|
||||
*/
|
||||
FilterPtr
|
||||
@ -369,21 +369,21 @@ public:
|
||||
|
||||
/*!
|
||||
* Creates a BlockingFilter which blocks until the comparator returns true.
|
||||
*
|
||||
*
|
||||
* The user provides a comparator, and every time a line is
|
||||
* received the comparator is called and the comparator has to evaluate the
|
||||
* line and return true if it matches and false if it doesn't. If it does
|
||||
* match, any threads that have called BlockingFilter::wait will be
|
||||
* notified. The BlockingFilter will remove itself when its destructor is
|
||||
* called, i.e. when it leaves the scope, so in those cases an explicit call
|
||||
* called, i.e. when it leaves the scope, so in those cases an explicit call
|
||||
* to SerialListener::removeFilter is not needed.
|
||||
*
|
||||
*
|
||||
* \param comparator This is a comparator for detecting if a line matches.
|
||||
* The comparartor receives a std::string reference and must return a true
|
||||
* if it matches and false if it doesn't.
|
||||
*
|
||||
*
|
||||
* \return BlockingFilterPtr So you can call BlockingFilter::wait on it.
|
||||
*
|
||||
*
|
||||
* \see SerialListener::removeFilter, serial::BlockingFilter,
|
||||
* serial::BlockingFilterPtr
|
||||
*/
|
||||
@ -392,24 +392,24 @@ public:
|
||||
|
||||
/*!
|
||||
* Creates a BlockingFilter blocks until the comparator returns true.
|
||||
*
|
||||
*
|
||||
* The user provides a comparator, and every time a line is
|
||||
* received the comparator is called and the comparator has to evaluate the
|
||||
* line and return true if it matches and false if it doesn't. If it does
|
||||
* match, any threads that have called BlockingFilter::wait will be
|
||||
* notified. The BlockingFilter will remove itself when its destructor is
|
||||
* called, i.e. when it leaves the scope, so in those cases an explicit call
|
||||
* called, i.e. when it leaves the scope, so in those cases an explicit call
|
||||
* to SerialListener::removeFilter is not needed.
|
||||
*
|
||||
*
|
||||
* \param comparator This is a comparator for detecting if a line matches.
|
||||
* The comparartor receives a std::string reference and must return a true
|
||||
* if it matches and false if it doesn't.
|
||||
*
|
||||
*
|
||||
* \param buffer_size This is the number of tokens to be buffered by the
|
||||
* BufferedFilter, defaults to 1024.
|
||||
*
|
||||
*
|
||||
* \return BlockingFilter So you can call BlockingFilter::wait on it.
|
||||
*
|
||||
*
|
||||
* \see SerialListener::removeFilter, serial::BufferedFilter,
|
||||
* serial::BufferedFilterPtr
|
||||
*/
|
||||
@ -418,9 +418,9 @@ public:
|
||||
|
||||
/*!
|
||||
* Removes a filter by a given FilterPtr.
|
||||
*
|
||||
*
|
||||
* \param filter_ptr A shared pointer to the filter to be removed.
|
||||
*
|
||||
*
|
||||
* \see SerialListener::createFilter
|
||||
*/
|
||||
void
|
||||
@ -428,11 +428,11 @@ public:
|
||||
|
||||
/*!
|
||||
* Removes a BlockingFilter.
|
||||
*
|
||||
*
|
||||
* The BlockingFilter will remove itself if the destructor is called.
|
||||
*
|
||||
*
|
||||
* \param blocking_filter A BlockingFilter to be removed.
|
||||
*
|
||||
*
|
||||
* \see SerialListener::createBlockingFilter
|
||||
*/
|
||||
void
|
||||
@ -440,11 +440,11 @@ public:
|
||||
|
||||
/*!
|
||||
* Removes a BufferedFilter.
|
||||
*
|
||||
*
|
||||
* The BufferedFilter will remove itself if the destructor is called.
|
||||
*
|
||||
*
|
||||
* \param buffered_filter A BufferedFilter to be removed.
|
||||
*
|
||||
*
|
||||
* \see SerialListener::createBufferedFilter
|
||||
*/
|
||||
void
|
||||
@ -478,7 +478,7 @@ setWarningHandler (ExceptionCallback exception_handler) {
|
||||
|
||||
/*!
|
||||
* Sleeps for a given number of milliseconds.
|
||||
*
|
||||
*
|
||||
* \param milliseconds number of milliseconds to sleep.
|
||||
*/
|
||||
static void
|
||||
@ -489,21 +489,21 @@ setWarningHandler (ExceptionCallback exception_handler) {
|
||||
|
||||
/*!
|
||||
* This returns a tokenizer that splits on a given delimeter.
|
||||
*
|
||||
* The delimeter is passed into the function and a TokenizerType is returned
|
||||
*
|
||||
* The delimeter is passed into the function and a TokenizerType is returned
|
||||
* that can be passed to SerialListener::setTokenizer.
|
||||
*
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
* my_listener.setTokenizer(SerialListener::delimeter_tokenizer("\r"));
|
||||
* <\pre>
|
||||
*
|
||||
* \param delimeter A std::string that is used as a delimeter when
|
||||
*
|
||||
* \param delimeter A std::string that is used as a delimeter when
|
||||
* tokenizing data.
|
||||
*
|
||||
* \return TokenizerType A tokenizer function type that can be passed to
|
||||
*
|
||||
* \return TokenizerType A tokenizer function type that can be passed to
|
||||
* SerialListener::setTokenizer.
|
||||
*
|
||||
*
|
||||
* \see SerialListener::setTokenizer, serial::TokenizerType
|
||||
*/
|
||||
static TokenizerType
|
||||
@ -514,22 +514,22 @@ setWarningHandler (ExceptionCallback exception_handler) {
|
||||
|
||||
/*!
|
||||
* This returns a comparator that matches only the exact string given.
|
||||
*
|
||||
*
|
||||
* This can be used with listenFor or listenForOnce:
|
||||
*
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
* my_listener.listenFor(SerialListener::exactly("my_string"),
|
||||
* my_callback);
|
||||
* <\pre>
|
||||
*
|
||||
* \param exact_str A std::string that is used as the exact string to match
|
||||
*
|
||||
* \param exact_str A std::string that is used as the exact string to match
|
||||
* when comparing tokens for matching.
|
||||
*
|
||||
* \return ComparatorType A comparator function type that can be passed to
|
||||
*
|
||||
* \return ComparatorType A comparator function type that can be passed to
|
||||
* SerialListener::listenFor or SerialListener::listenForOnce.
|
||||
*
|
||||
* \see SerialListener::listenFor, SerialListener::listenForOnce,
|
||||
* \see SerialListener::listenFor, SerialListener::listenForOnce,
|
||||
* serial::ComparatorType
|
||||
*/
|
||||
static ComparatorType
|
||||
@ -539,21 +539,21 @@ setWarningHandler (ExceptionCallback exception_handler) {
|
||||
|
||||
/*!
|
||||
* This returns a comparator that looks for a given prefix.
|
||||
*
|
||||
*
|
||||
* This can be used with listenFor or listenForOnce:
|
||||
*
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
* my_listener.listenFor(SerialListener::startsWith("V="), my_callback);
|
||||
* <\pre>
|
||||
*
|
||||
* \param prefix A std::string that is used as the prefix string to match
|
||||
*
|
||||
* \param prefix A std::string that is used as the prefix string to match
|
||||
* when comparing tokens for matching.
|
||||
*
|
||||
* \return ComparatorType A comparator function type that can be passed to
|
||||
*
|
||||
* \return ComparatorType A comparator function type that can be passed to
|
||||
* SerialListener::listenFor or SerialListener::listenForOnce.
|
||||
*
|
||||
* \see SerialListener::listenFor, SerialListener::listenForOnce,
|
||||
* \see SerialListener::listenFor, SerialListener::listenForOnce,
|
||||
* serial::ComparatorType
|
||||
*/
|
||||
static ComparatorType
|
||||
@ -563,21 +563,21 @@ setWarningHandler (ExceptionCallback exception_handler) {
|
||||
|
||||
/*!
|
||||
* This returns a comparator that looks for a given postfix.
|
||||
*
|
||||
*
|
||||
* This can be used with listenFor or listenForOnce:
|
||||
*
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
* my_listener.listenFor(SerialListener::endsWith(";"), my_callback);
|
||||
* <\pre>
|
||||
*
|
||||
* \param postfix A std::string that is used as the postfix string to match
|
||||
*
|
||||
* \param postfix A std::string that is used as the postfix string to match
|
||||
* when comparing tokens for matching.
|
||||
*
|
||||
* \return ComparatorType A comparator function type that can be passed to
|
||||
*
|
||||
* \return ComparatorType A comparator function type that can be passed to
|
||||
* SerialListener::listenFor or SerialListener::listenForOnce.
|
||||
*
|
||||
* \see SerialListener::listenFor, SerialListener::listenForOnce,
|
||||
* \see SerialListener::listenFor, SerialListener::listenForOnce,
|
||||
* serial::ComparatorType
|
||||
*/
|
||||
static ComparatorType
|
||||
@ -587,22 +587,22 @@ setWarningHandler (ExceptionCallback exception_handler) {
|
||||
|
||||
/*!
|
||||
* This returns a comparator that looks for a given substring in the token.
|
||||
*
|
||||
*
|
||||
* This can be used with listenFor or listenForOnce:
|
||||
*
|
||||
*
|
||||
* Example:
|
||||
* <pre>
|
||||
* my_listener.listenFor(SerialListener::contains("some string"),
|
||||
* my_callback);
|
||||
* <\pre>
|
||||
*
|
||||
* \param substr A std::string that is used as the search substring to match
|
||||
*
|
||||
* \param substr A std::string that is used as the search substring to match
|
||||
* when comparing tokens for matching.
|
||||
*
|
||||
* \return ComparatorType A comparator function type that can be passed to
|
||||
*
|
||||
* \return ComparatorType A comparator function type that can be passed to
|
||||
* SerialListener::listenFor or SerialListener::listenForOnce.
|
||||
*
|
||||
* \see SerialListener::listenFor, SerialListener::listenForOnce,
|
||||
* \see SerialListener::listenFor, SerialListener::listenForOnce,
|
||||
* serial::ComparatorType
|
||||
*/
|
||||
static ComparatorType
|
||||
@ -698,13 +698,13 @@ private:
|
||||
};
|
||||
|
||||
/*!
|
||||
* This is the a filter that provides a wait function for blocking until a
|
||||
* This is the a filter that provides a wait function for blocking until a
|
||||
* match is found.
|
||||
*
|
||||
* This should probably not be created manually, but instead should be
|
||||
*
|
||||
* This should probably not be created manually, but instead should be
|
||||
* constructed using SerialListener::createBlockingFilter(ComparatorType)
|
||||
* function which returns a BlockingFilter instance.
|
||||
*
|
||||
*
|
||||
* \see serial::SerialListener::ComparatorType,
|
||||
* serial::SerialListener::createBlockingFilter
|
||||
*/
|
||||
@ -726,9 +726,9 @@ public:
|
||||
/*!
|
||||
* Waits a given number of milliseconds or until a token is matched. If a
|
||||
* token is matched it is returned, otherwise an empty string is returned.
|
||||
*
|
||||
*
|
||||
* \param ms Time in milliseconds to wait on a new token.
|
||||
*
|
||||
*
|
||||
* \return std::string token that was matched or "" if none were matched.
|
||||
*/
|
||||
std::string wait(long ms) {
|
||||
@ -757,22 +757,22 @@ private:
|
||||
* This is the a filter that provides a wait function for blocking until a
|
||||
* match is found. It will also buffer up to a given buffer size of tokens so
|
||||
* that they can be counted or accessed after they are matched by the filter.
|
||||
*
|
||||
* This should probably not be created manually, but instead should be
|
||||
*
|
||||
* This should probably not be created manually, but instead should be
|
||||
* constructed using SerialListener::createBufferedFilter(ComparatorType)
|
||||
* function which returns a BufferedFilter instance.
|
||||
*
|
||||
*
|
||||
* The internal buffer is a circular queue buffer, so when the buffer is full,
|
||||
* the oldest token is dropped and the new one is added. Additionally, when
|
||||
* wait is a called the oldest available token is returned.
|
||||
*
|
||||
*
|
||||
* \see serial::SerialListener::ComparatorType,
|
||||
* serial::SerialListener::createBufferedFilter
|
||||
*/
|
||||
class BufferedFilter
|
||||
{
|
||||
public:
|
||||
BufferedFilter (ComparatorType comparator, size_t buffer_size,
|
||||
BufferedFilter (ComparatorType comparator, size_t buffer_size,
|
||||
SerialListener &listener)
|
||||
: buffer_size_(buffer_size)
|
||||
{
|
||||
@ -788,14 +788,14 @@ public:
|
||||
}
|
||||
|
||||
/*!
|
||||
* Waits a given number of milliseconds or until a matched token is
|
||||
* Waits a given number of milliseconds or until a matched token is
|
||||
* available in the buffer. If a token is matched it is returned, otherwise
|
||||
* an empty string is returned.
|
||||
*
|
||||
* \param ms Time in milliseconds to wait on a new token. If ms is set to 0
|
||||
* then it will try to get a new token if one is available but will not
|
||||
*
|
||||
* \param ms Time in milliseconds to wait on a new token. If ms is set to 0
|
||||
* then it will try to get a new token if one is available but will not
|
||||
* block.
|
||||
*
|
||||
*
|
||||
* \return std::string token that was matched or "" if none were matched.
|
||||
*/
|
||||
std::string wait(long ms) {
|
||||
|
||||
@ -15,7 +15,7 @@ IF(EXISTS /usr/bin/clang)
|
||||
set(CMAKE_CXX_COMPILER /usr/bin/clang++)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "")
|
||||
# set(CMAKE_CXX_FLAGS "-ferror-limit=5 -std=c++0x -stdlib=libc++")
|
||||
set(CMAKE_CXX_FLAGS "-ferror-limit=5 -m64 -Wall -Weffc++ -pedantic -pedantic-errors -Wextra -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment -Wconversion -Wdisabled-optimization -Wfloat-equal -Wformat -Wformat=2 -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wimplicit -Wimport -Winit-self -Winline -Winvalid-pch -Wlong-long -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wpacked -Wpadded -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wstack-protector -Wstrict-aliasing -Wstrict-aliasing=2 -Wswitch -Wswitch-default -Wswitch-enum -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvolatile-register-var -Wwrite-strings")
|
||||
set(CMAKE_CXX_FLAGS "-ferror-limit=5 -O3 -Wall -Weffc++ -pedantic -pedantic-errors -Wextra -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment -Wconversion -Wdisabled-optimization -Wfloat-equal -Wformat -Wformat=2 -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wimplicit -Wimport -Winit-self -Winline -Winvalid-pch -Wlong-long -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wpacked -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wstack-protector -Wstrict-aliasing -Wstrict-aliasing=2 -Wswitch -Wswitch-default -Wswitch-enum -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvolatile-register-var -Wwrite-strings")
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
ENDIF(EXISTS /usr/bin/clang)
|
||||
|
||||
|
||||
403
src/impl/unix.cc
403
src/impl/unix.cc
@ -1,3 +1,5 @@
|
||||
/* Copyright 2012 William Woodall and John Harrison */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@ -33,31 +35,36 @@ Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate,
|
||||
long timeout, bytesize_t bytesize,
|
||||
parity_t parity, stopbits_t stopbits,
|
||||
flowcontrol_t flowcontrol)
|
||||
: port_(port), fd_(-1), interCharTimeout_(-1), writeTimeout_(-1),
|
||||
isOpen_(false), xonxoff_(false), rtscts_(false), ___(0), timeout_(timeout),
|
||||
baudrate_(baudrate), parity_(parity), bytesize_(bytesize),
|
||||
stopbits_(stopbits), flowcontrol_(flowcontrol)
|
||||
: port_ (port), fd_ (-1), isOpen_ (false), xonxoff_ (true), rtscts_ (false),
|
||||
timeout_ (timeout), baudrate_ (baudrate), parity_ (parity), bytesize_ (bytesize),
|
||||
stopbits_ (stopbits), flowcontrol_ (flowcontrol)
|
||||
{
|
||||
if (port_.empty() == false) this->open();
|
||||
if (port_.empty () == false)
|
||||
open ();
|
||||
}
|
||||
|
||||
Serial::SerialImpl::~SerialImpl () {
|
||||
this->close();
|
||||
Serial::SerialImpl::~SerialImpl ()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::open () {
|
||||
if (port_.empty()) {
|
||||
throw invalid_argument("bad port specified");
|
||||
Serial::SerialImpl::open ()
|
||||
{
|
||||
if (port_.empty())
|
||||
{
|
||||
throw invalid_argument ("bad port specified");
|
||||
}
|
||||
if (isOpen_ == true) {
|
||||
throw SerialExecption("port already open");
|
||||
if (isOpen_ == true)
|
||||
{
|
||||
throw SerialExecption ("port already open");
|
||||
}
|
||||
|
||||
|
||||
fd_ = ::open (port_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
|
||||
if (fd_ == -1) {
|
||||
throw IOException("invalid file descriptor");
|
||||
if (fd_ == -1)
|
||||
{
|
||||
throw IOException ("invalid file descriptor");
|
||||
}
|
||||
|
||||
reconfigurePort();
|
||||
@ -65,31 +72,25 @@ Serial::SerialImpl::open () {
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::reconfigurePort () {
|
||||
if (fd_ == -1) {
|
||||
Serial::SerialImpl::reconfigurePort ()
|
||||
{
|
||||
if (fd_ == -1)
|
||||
{
|
||||
// Can only operate on a valid file descriptor
|
||||
throw IOException("invalid file descriptor");
|
||||
throw IOException ("invalid file descriptor");
|
||||
}
|
||||
|
||||
struct termios options; // The current options for the file descriptor
|
||||
struct termios originalTTYAttrs; // The orignal file descriptor options
|
||||
struct termios options; // The options for the file descriptor
|
||||
|
||||
uint8_t vmin = 0, vtime = 0; // timeout is done via select
|
||||
if (interCharTimeout_ == -1) {
|
||||
vmin = 1;
|
||||
vtime = uint8_t(interCharTimeout_ * 10);
|
||||
if (tcgetattr(fd_, &options) == -1)
|
||||
{
|
||||
throw IOException ("::tcgetattr");
|
||||
}
|
||||
|
||||
if (tcgetattr(fd_, &originalTTYAttrs) == -1) {
|
||||
throw IOException("::tcgetattr");
|
||||
}
|
||||
|
||||
options = originalTTYAttrs;
|
||||
|
||||
// set up raw mode / no echo / binary
|
||||
options.c_cflag |= (unsigned long)(CLOCAL|CREAD);
|
||||
options.c_lflag &= (unsigned long) ~(ICANON|ECHO|ECHOE|ECHOK
|
||||
|ECHONL|ISIG|IEXTEN); //|ECHOPRT
|
||||
options.c_cflag |= (unsigned long) (CLOCAL|CREAD);
|
||||
options.c_lflag &= (unsigned long) ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|
|
||||
ISIG|IEXTEN); //|ECHOPRT
|
||||
|
||||
options.c_oflag &= (unsigned long) ~(OPOST);
|
||||
options.c_iflag &= (unsigned long) ~(INLCR|IGNCR|ICRNL|IGNBRK);
|
||||
@ -115,7 +116,7 @@ Serial::SerialImpl::reconfigurePort () {
|
||||
else if (bytesize_ == FIVEBITS)
|
||||
options.c_cflag |= CS5;
|
||||
else
|
||||
throw invalid_argument("Invalid char len");
|
||||
throw invalid_argument ("Invalid char len");
|
||||
// setup stopbits
|
||||
if (stopbits_ == STOPBITS_ONE)
|
||||
options.c_cflag &= (unsigned long) ~(CSTOPB);
|
||||
@ -123,22 +124,26 @@ Serial::SerialImpl::reconfigurePort () {
|
||||
options.c_cflag |= (CSTOPB); // XXX same as TWO.. there is no POSIX support for 1.5
|
||||
else if (stopbits_ == STOPBITS_TWO)
|
||||
options.c_cflag |= (CSTOPB);
|
||||
else
|
||||
throw invalid_argument("invalid stop bit");
|
||||
else
|
||||
throw invalid_argument ("invalid stop bit");
|
||||
// setup parity
|
||||
options.c_iflag &= (unsigned long) ~(INPCK|ISTRIP);
|
||||
if (parity_ == PARITY_NONE) {
|
||||
if (parity_ == PARITY_NONE)
|
||||
{
|
||||
options.c_cflag &= (unsigned long) ~(PARENB|PARODD);
|
||||
}
|
||||
else if (parity_ == PARITY_EVEN) {
|
||||
else if (parity_ == PARITY_EVEN)
|
||||
{
|
||||
options.c_cflag &= (unsigned long) ~(PARODD);
|
||||
options.c_cflag |= (PARENB);
|
||||
}
|
||||
else if (parity_ == PARITY_ODD) {
|
||||
}
|
||||
else if (parity_ == PARITY_ODD)
|
||||
{
|
||||
options.c_cflag |= (PARENB|PARODD);
|
||||
}
|
||||
else {
|
||||
throw invalid_argument("invalid parity");
|
||||
else
|
||||
{
|
||||
throw invalid_argument ("invalid parity");
|
||||
}
|
||||
// setup flow control
|
||||
// xonxoff
|
||||
@ -168,21 +173,21 @@ Serial::SerialImpl::reconfigurePort () {
|
||||
#error "OS Support seems wrong."
|
||||
#endif
|
||||
|
||||
// buffer
|
||||
// vmin "minimal number of characters to be read. = for non blocking"
|
||||
options.c_cc[VMIN] = vmin;
|
||||
// vtime
|
||||
options.c_cc[VTIME] = vtime;
|
||||
options.c_cc[VMIN] = 1; // Minimum of 1 character in the buffer
|
||||
options.c_cc[VTIME] = 0; // timeout on waiting for new data
|
||||
|
||||
// activate settings
|
||||
::tcsetattr(fd_, TCSANOW, &options);
|
||||
::tcsetattr (fd_, TCSANOW, &options);
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::close () {
|
||||
if (isOpen_ == true) {
|
||||
if (fd_ != -1) {
|
||||
::close(fd_); // Ignoring the outcome
|
||||
Serial::SerialImpl::close ()
|
||||
{
|
||||
if (isOpen_ == true)
|
||||
{
|
||||
if (fd_ != -1)
|
||||
{
|
||||
::close (fd_); // Ignoring the outcome
|
||||
fd_ = -1;
|
||||
}
|
||||
isOpen_ = false;
|
||||
@ -190,266 +195,318 @@ Serial::SerialImpl::close () {
|
||||
}
|
||||
|
||||
bool
|
||||
Serial::SerialImpl::isOpen () const {
|
||||
Serial::SerialImpl::isOpen () const
|
||||
{
|
||||
return isOpen_;
|
||||
}
|
||||
|
||||
size_t
|
||||
Serial::SerialImpl::available () {
|
||||
if (!isOpen_) {
|
||||
Serial::SerialImpl::available ()
|
||||
{
|
||||
if (!isOpen_)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int count = 0;
|
||||
int result = ioctl(fd_, TIOCINQ, &count);
|
||||
if (result == 0) {
|
||||
return (size_t)count;
|
||||
int result = ioctl (fd_, TIOCINQ, &count);
|
||||
if (result == 0)
|
||||
{
|
||||
return static_cast<size_t> (count);
|
||||
}
|
||||
else {
|
||||
throw IOException("ioctl");
|
||||
else
|
||||
{
|
||||
throw IOException ("ioctl");
|
||||
}
|
||||
}
|
||||
|
||||
string
|
||||
Serial::SerialImpl::read (size_t size) {
|
||||
if (!isOpen_) {
|
||||
throw PortNotOpenedException("Serial::read");
|
||||
}
|
||||
string message = "";
|
||||
char *buf = NULL;
|
||||
// Using size+1 to leave room for a null character
|
||||
if (size > 1024) {
|
||||
buf = (char*)malloc((size + 1) * sizeof(*buf));
|
||||
}
|
||||
else {
|
||||
buf = (char*)alloca((size + 1) * sizeof(*buf));
|
||||
size_t
|
||||
Serial::SerialImpl::read (char* buf, size_t size)
|
||||
{
|
||||
if (!isOpen_)
|
||||
{
|
||||
throw PortNotOpenedException ("Serial::read");
|
||||
}
|
||||
fd_set readfds;
|
||||
memset(buf, 0, (size + 1) * sizeof(*buf));
|
||||
ssize_t bytes_read = 0;
|
||||
while (bytes_read < (ssize_t)size) {
|
||||
if (timeout_ != -1) {
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fd_, &readfds);
|
||||
while (true)
|
||||
{
|
||||
if (timeout_ != -1)
|
||||
{
|
||||
FD_ZERO (&readfds);
|
||||
FD_SET (fd_, &readfds);
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = timeout_ / 1000;
|
||||
timeout.tv_usec = (int) timeout_ % 1000;
|
||||
int r = select(fd_ + 1, &readfds, NULL, NULL, &timeout);
|
||||
timeout.tv_sec = timeout_ / 1000;
|
||||
timeout.tv_usec = static_cast<int> (timeout_ % 1000);
|
||||
int r = select (fd_ + 1, &readfds, NULL, NULL, &timeout);
|
||||
|
||||
if (r == -1 && errno == EINTR)
|
||||
continue;
|
||||
|
||||
if (r == -1) {
|
||||
if (r == -1)
|
||||
{
|
||||
perror("select()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (timeout_ == -1 || FD_ISSET(fd_, &readfds)) {
|
||||
ssize_t newest_read = ::read(fd_,
|
||||
buf + bytes_read,
|
||||
size - static_cast<size_t>(bytes_read));
|
||||
if (timeout_ == -1 || FD_ISSET (fd_, &readfds))
|
||||
{
|
||||
bytes_read = ::read (fd_, buf, size);
|
||||
// read should always return some data as select reported it was
|
||||
// ready to read when we get to this point.
|
||||
if (newest_read < 1) {
|
||||
// printf("bytes_read: %lu\n", bytes_read);
|
||||
if (bytes_read < 1)
|
||||
{
|
||||
// Disconnected devices, at least on Linux, show the
|
||||
// behavior that they are always ready to read immediately
|
||||
// but reading returns nothing.
|
||||
throw SerialExecption("device reports readiness to read but "
|
||||
"returned no data (device disconnected?)");
|
||||
throw SerialExecption ("device reports readiness to read but "
|
||||
"returned no data (device disconnected?)");
|
||||
}
|
||||
bytes_read += newest_read;
|
||||
}
|
||||
else {
|
||||
break; // Timeout
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bytes_read > 0)
|
||||
message.append(buf, (size_t)bytes_read);
|
||||
if (size > 1024)
|
||||
free(buf);
|
||||
return message;
|
||||
return static_cast<size_t> (bytes_read);
|
||||
}
|
||||
|
||||
size_t
|
||||
Serial::SerialImpl::write (const string &data) {
|
||||
Serial::SerialImpl::write (const string &data)
|
||||
{
|
||||
if (isOpen_ == false) {
|
||||
throw PortNotOpenedException("Serial::write");
|
||||
throw PortNotOpenedException ("Serial::write");
|
||||
}
|
||||
ssize_t n = ::write(fd_, data.c_str(), data.length());
|
||||
ssize_t n = ::write (fd_, data.c_str (), data.length ());
|
||||
if (n == -1) {
|
||||
throw IOException("Write");
|
||||
throw IOException ("Write");
|
||||
}
|
||||
return (size_t)n;
|
||||
return static_cast<size_t> (n);
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setPort (const string &port) {
|
||||
Serial::SerialImpl::setPort (const string &port)
|
||||
{
|
||||
port_ = port;
|
||||
}
|
||||
|
||||
string
|
||||
Serial::SerialImpl::getPort () const {
|
||||
Serial::SerialImpl::getPort () const
|
||||
{
|
||||
return port_;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setTimeout (long timeout) {
|
||||
Serial::SerialImpl::setTimeout (long timeout)
|
||||
{
|
||||
timeout_ = timeout;
|
||||
if (isOpen_) reconfigurePort();
|
||||
if (isOpen_)
|
||||
reconfigurePort ();
|
||||
}
|
||||
|
||||
long
|
||||
Serial::SerialImpl::getTimeout () const {
|
||||
Serial::SerialImpl::getTimeout () const
|
||||
{
|
||||
return timeout_;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setBaudrate (unsigned long baudrate) {
|
||||
Serial::SerialImpl::setBaudrate (unsigned long baudrate)
|
||||
{
|
||||
baudrate_ = baudrate;
|
||||
if (isOpen_) reconfigurePort();
|
||||
if (isOpen_)
|
||||
reconfigurePort ();
|
||||
}
|
||||
|
||||
unsigned long
|
||||
Serial::SerialImpl::getBaudrate () const {
|
||||
Serial::SerialImpl::getBaudrate () const
|
||||
{
|
||||
return baudrate_;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize) {
|
||||
Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize)
|
||||
{
|
||||
bytesize_ = bytesize;
|
||||
if (isOpen_) reconfigurePort();
|
||||
if (isOpen_)
|
||||
reconfigurePort ();
|
||||
}
|
||||
|
||||
serial::bytesize_t
|
||||
Serial::SerialImpl::getBytesize () const {
|
||||
Serial::SerialImpl::getBytesize () const
|
||||
{
|
||||
return bytesize_;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setParity (serial::parity_t parity) {
|
||||
Serial::SerialImpl::setParity (serial::parity_t parity)
|
||||
{
|
||||
parity_ = parity;
|
||||
if (isOpen_) reconfigurePort();
|
||||
if (isOpen_)
|
||||
reconfigurePort ();
|
||||
}
|
||||
|
||||
serial::parity_t
|
||||
Serial::SerialImpl::getParity () const {
|
||||
Serial::SerialImpl::getParity () const
|
||||
{
|
||||
return parity_;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits) {
|
||||
Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits)
|
||||
{
|
||||
stopbits_ = stopbits;
|
||||
if (isOpen_) reconfigurePort();
|
||||
if (isOpen_)
|
||||
reconfigurePort ();
|
||||
}
|
||||
|
||||
serial::stopbits_t
|
||||
Serial::SerialImpl::getStopbits () const {
|
||||
Serial::SerialImpl::getStopbits () const
|
||||
{
|
||||
return stopbits_;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol) {
|
||||
Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol)
|
||||
{
|
||||
flowcontrol_ = flowcontrol;
|
||||
if (isOpen_) reconfigurePort();
|
||||
if (isOpen_)
|
||||
reconfigurePort ();
|
||||
}
|
||||
|
||||
serial::flowcontrol_t
|
||||
Serial::SerialImpl::getFlowcontrol () const {
|
||||
Serial::SerialImpl::getFlowcontrol () const
|
||||
{
|
||||
return flowcontrol_;
|
||||
}
|
||||
|
||||
void Serial::SerialImpl::flush () {
|
||||
if (isOpen_ == false) {
|
||||
throw PortNotOpenedException("Serial::flush");
|
||||
void
|
||||
Serial::SerialImpl::flush ()
|
||||
{
|
||||
if (isOpen_ == false)
|
||||
{
|
||||
throw PortNotOpenedException ("Serial::flush");
|
||||
}
|
||||
tcdrain(fd_);
|
||||
tcdrain (fd_);
|
||||
}
|
||||
|
||||
void Serial::SerialImpl::flushInput () {
|
||||
if (isOpen_ == false) {
|
||||
throw PortNotOpenedException("Serial::flushInput");
|
||||
void
|
||||
Serial::SerialImpl::flushInput ()
|
||||
{
|
||||
if (isOpen_ == false)
|
||||
{
|
||||
throw PortNotOpenedException ("Serial::flushInput");
|
||||
}
|
||||
tcflush(fd_, TCIFLUSH);
|
||||
tcflush (fd_, TCIFLUSH);
|
||||
}
|
||||
|
||||
void Serial::SerialImpl::flushOutput () {
|
||||
if (isOpen_ == false) {
|
||||
throw PortNotOpenedException("Serial::flushOutput");
|
||||
void
|
||||
Serial::SerialImpl::flushOutput ()
|
||||
{
|
||||
if (isOpen_ == false)
|
||||
{
|
||||
throw PortNotOpenedException ("Serial::flushOutput");
|
||||
}
|
||||
tcflush(fd_, TCOFLUSH);
|
||||
tcflush (fd_, TCOFLUSH);
|
||||
}
|
||||
|
||||
void Serial::SerialImpl::sendBreak(int duration) {
|
||||
if (isOpen_ == false) {
|
||||
throw PortNotOpenedException("Serial::sendBreak");
|
||||
void
|
||||
Serial::SerialImpl::sendBreak (int duration)
|
||||
{
|
||||
if (isOpen_ == false)
|
||||
{
|
||||
throw PortNotOpenedException ("Serial::sendBreak");
|
||||
}
|
||||
tcsendbreak(fd_, int(duration/4));
|
||||
tcsendbreak (fd_, static_cast<int> (duration/4));
|
||||
}
|
||||
|
||||
void Serial::SerialImpl::setBreak(bool level) {
|
||||
if (isOpen_ == false) {
|
||||
throw PortNotOpenedException("Serial::setBreak");
|
||||
void
|
||||
Serial::SerialImpl::setBreak (bool level)
|
||||
{
|
||||
if (isOpen_ == false)
|
||||
{
|
||||
throw PortNotOpenedException ("Serial::setBreak");
|
||||
}
|
||||
if (level) {
|
||||
ioctl(fd_, TIOCSBRK);
|
||||
if (level)
|
||||
{
|
||||
ioctl (fd_, TIOCSBRK);
|
||||
}
|
||||
else {
|
||||
ioctl(fd_, TIOCCBRK);
|
||||
ioctl (fd_, TIOCCBRK);
|
||||
}
|
||||
}
|
||||
|
||||
void Serial::SerialImpl::setRTS(bool level) {
|
||||
if (isOpen_ == false) {
|
||||
throw PortNotOpenedException("Serial::setRTS");
|
||||
void
|
||||
Serial::SerialImpl::setRTS (bool level)
|
||||
{
|
||||
if (isOpen_ == false)
|
||||
{
|
||||
throw PortNotOpenedException ("Serial::setRTS");
|
||||
}
|
||||
if (level) {
|
||||
ioctl(fd_, TIOCMBIS, TIOCM_RTS);
|
||||
if (level)
|
||||
{
|
||||
ioctl (fd_, TIOCMBIS, TIOCM_RTS);
|
||||
}
|
||||
else {
|
||||
ioctl(fd_, TIOCMBIC, TIOCM_RTS);
|
||||
ioctl (fd_, TIOCMBIC, TIOCM_RTS);
|
||||
}
|
||||
}
|
||||
|
||||
void Serial::SerialImpl::setDTR(bool level) {
|
||||
if (isOpen_ == false) {
|
||||
throw PortNotOpenedException("Serial::setDTR");
|
||||
void
|
||||
Serial::SerialImpl::setDTR (bool level)
|
||||
{
|
||||
if (isOpen_ == false)
|
||||
{
|
||||
throw PortNotOpenedException ("Serial::setDTR");
|
||||
}
|
||||
if (level) {
|
||||
ioctl(fd_, TIOCMBIS, TIOCM_DTR);
|
||||
if (level)
|
||||
{
|
||||
ioctl (fd_, TIOCMBIS, TIOCM_DTR);
|
||||
}
|
||||
else {
|
||||
ioctl(fd_, TIOCMBIC, TIOCM_DTR);
|
||||
else
|
||||
{
|
||||
ioctl (fd_, TIOCMBIC, TIOCM_DTR);
|
||||
}
|
||||
}
|
||||
|
||||
bool Serial::SerialImpl::getCTS() {
|
||||
if (isOpen_ == false) {
|
||||
throw PortNotOpenedException("Serial::getCTS");
|
||||
bool
|
||||
Serial::SerialImpl::getCTS ()
|
||||
{
|
||||
if (isOpen_ == false)
|
||||
{
|
||||
throw PortNotOpenedException ("Serial::getCTS");
|
||||
}
|
||||
int s = ioctl(fd_, TIOCMGET, 0);
|
||||
int s = ioctl (fd_, TIOCMGET, 0);
|
||||
return (s & TIOCM_CTS) != 0;
|
||||
}
|
||||
|
||||
bool Serial::SerialImpl::getDSR() {
|
||||
if (isOpen_ == false) {
|
||||
throw PortNotOpenedException("Serial::getDSR");
|
||||
bool
|
||||
Serial::SerialImpl::getDSR()
|
||||
{
|
||||
if (isOpen_ == false)
|
||||
{
|
||||
throw PortNotOpenedException ("Serial::getDSR");
|
||||
}
|
||||
int s = ioctl(fd_, TIOCMGET, 0);
|
||||
return (s & TIOCM_DSR) != 0;
|
||||
}
|
||||
|
||||
bool Serial::SerialImpl::getRI() {
|
||||
if (isOpen_ == false) {
|
||||
throw PortNotOpenedException("Serial::getRI");
|
||||
bool
|
||||
Serial::SerialImpl::getRI()
|
||||
{
|
||||
if (isOpen_ == false)
|
||||
{
|
||||
throw PortNotOpenedException ("Serial::getRI");
|
||||
}
|
||||
int s = ioctl(fd_, TIOCMGET, 0);
|
||||
int s = ioctl (fd_, TIOCMGET, 0);
|
||||
return (s & TIOCM_RI) != 0;
|
||||
}
|
||||
|
||||
bool Serial::SerialImpl::getCD() {
|
||||
if (isOpen_ == false) {
|
||||
throw PortNotOpenedException("Serial::getCD");
|
||||
bool
|
||||
Serial::SerialImpl::getCD()
|
||||
{
|
||||
if (isOpen_ == false)
|
||||
{
|
||||
throw PortNotOpenedException ("Serial::getCD");
|
||||
}
|
||||
int s = ioctl(fd_, TIOCMGET, 0);
|
||||
int s = ioctl (fd_, TIOCMGET, 0);
|
||||
return (s & TIOCM_CD) != 0;
|
||||
}
|
||||
|
||||
293
src/serial.cc
293
src/serial.cc
@ -1,3 +1,10 @@
|
||||
/* Copyright 2012 William Woodall and John Harrison */
|
||||
|
||||
#include <alloca.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
#include "serial/serial.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -6,11 +13,14 @@
|
||||
#include "serial/impl/unix.h"
|
||||
#endif
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::numeric_limits;
|
||||
using std::size_t;
|
||||
using std::invalid_argument;
|
||||
using std::memset;
|
||||
using std::min;
|
||||
using std::numeric_limits;
|
||||
using std::vector;
|
||||
using std::size_t;
|
||||
using std::string;
|
||||
|
||||
using serial::Serial;
|
||||
using serial::SerialExecption;
|
||||
using serial::IOException;
|
||||
@ -21,204 +31,301 @@ using serial::flowcontrol_t;
|
||||
|
||||
Serial::Serial (const string &port, unsigned long baudrate, long timeout,
|
||||
bytesize_t bytesize, parity_t parity, stopbits_t stopbits,
|
||||
flowcontrol_t flowcontrol)
|
||||
flowcontrol_t flowcontrol, const size_t buffer_size)
|
||||
: buffer_size_(buffer_size)
|
||||
{
|
||||
pimpl = new SerialImpl(port, baudrate, timeout, bytesize, parity,
|
||||
pimpl_ = new SerialImpl (port, baudrate, timeout, bytesize, parity,
|
||||
stopbits, flowcontrol);
|
||||
read_cache_ = new char[buffer_size_];
|
||||
memset (read_cache_, 0, buffer_size_ * sizeof (char));
|
||||
}
|
||||
|
||||
Serial::~Serial () {
|
||||
delete pimpl;
|
||||
Serial::~Serial ()
|
||||
{
|
||||
delete pimpl_;
|
||||
delete[] read_cache_;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::open () {
|
||||
this->pimpl->open ();
|
||||
Serial::open ()
|
||||
{
|
||||
pimpl_->open ();
|
||||
}
|
||||
|
||||
void
|
||||
Serial::close () {
|
||||
this->pimpl->close ();
|
||||
Serial::close ()
|
||||
{
|
||||
pimpl_->close ();
|
||||
memset (read_cache_, 0, buffer_size_ * sizeof (char));
|
||||
}
|
||||
|
||||
bool
|
||||
Serial::isOpen () const {
|
||||
return this->pimpl->isOpen ();
|
||||
Serial::isOpen () const
|
||||
{
|
||||
return pimpl_->isOpen ();
|
||||
}
|
||||
|
||||
size_t
|
||||
Serial::available () {
|
||||
return this->pimpl->available();
|
||||
Serial::available ()
|
||||
{
|
||||
return pimpl_->available ();
|
||||
}
|
||||
|
||||
string
|
||||
Serial::read (size_t size) {
|
||||
return this->pimpl->read (size);
|
||||
Serial::read (size_t size)
|
||||
{
|
||||
size_t cache_size = strlen (read_cache_);
|
||||
if (cache_size >= size)
|
||||
{
|
||||
// Don't need to do a new read.
|
||||
string result (read_cache_, size);
|
||||
memmove (read_cache_, read_cache_ + size, cache_size - size);
|
||||
*(read_cache_ + cache_size - size) = '\0';
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Needs to read, loop until we have read enough... or timeout
|
||||
size_t chars_left = 0;
|
||||
string result = "";
|
||||
|
||||
if (cache_size > 0)
|
||||
{
|
||||
result.append (read_cache_, cache_size);
|
||||
memset (read_cache_, 0, buffer_size_);
|
||||
chars_left = size - cache_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
chars_left = size;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
size_t chars_read = pimpl_->read (read_cache_, buffer_size_ - 1);
|
||||
if (chars_read > 0)
|
||||
{
|
||||
*(read_cache_ + chars_read) = '\0';
|
||||
if (chars_left > chars_read)
|
||||
{
|
||||
memset (read_cache_, 0, buffer_size_);
|
||||
result.append (read_cache_);
|
||||
chars_left -= chars_read;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.append (read_cache_, static_cast<size_t> (chars_left));
|
||||
memmove (read_cache_, read_cache_ + chars_left, chars_read - chars_left);
|
||||
*(read_cache_ + chars_read - chars_left) = '\0';
|
||||
memset (read_cache_ + chars_read - chars_left, 0,
|
||||
buffer_size_ - chars_read - chars_left);
|
||||
// Finished reading all of the data
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break; // Timeout occured
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
string
|
||||
Serial::readline(size_t size, string eol) {
|
||||
size_t leneol = eol.length();
|
||||
Serial::readline (size_t size, string eol)
|
||||
{
|
||||
size_t leneol = eol.length ();
|
||||
string line = "";
|
||||
while (true) {
|
||||
string c = pimpl->read(1);
|
||||
if (!c.empty()) {
|
||||
line.append(c);
|
||||
if (line.length() > leneol
|
||||
&& line.substr(line.length() - leneol, leneol) == eol)
|
||||
while (true)
|
||||
{
|
||||
string c = read (1);
|
||||
if (!c.empty ())
|
||||
{
|
||||
line.append (c);
|
||||
if (line.length () > leneol &&
|
||||
line.substr (line.length () - leneol, leneol) == eol)
|
||||
break;
|
||||
if (line.length() >= size) {
|
||||
if (line.length () >= size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
// Timeout
|
||||
break;
|
||||
}
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
vector<string>
|
||||
Serial::readlines(string eol) {
|
||||
if (this->pimpl->getTimeout() < 0) {
|
||||
Serial::readlines(string eol)
|
||||
{
|
||||
if (pimpl_->getTimeout () < 0)
|
||||
{
|
||||
throw "Error, must be set for readlines";
|
||||
}
|
||||
size_t leneol = eol.length();
|
||||
size_t leneol = eol.length ();
|
||||
vector<string> lines;
|
||||
while (true) {
|
||||
string line = readline(numeric_limits<size_t>::max(), eol);
|
||||
if (!line.empty()) {
|
||||
lines.push_back(line);
|
||||
if (line.substr(line.length() - leneol, leneol) == eol)
|
||||
while (true)
|
||||
{
|
||||
string line = readline (numeric_limits<size_t>::max (), eol);
|
||||
if (!line.empty ())
|
||||
{
|
||||
lines.push_back (line);
|
||||
if (line.substr (line.length () - leneol, leneol) == eol)
|
||||
break;
|
||||
}
|
||||
else {
|
||||
else
|
||||
// Timeout
|
||||
break;
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
size_t
|
||||
Serial::write (const string &data) {
|
||||
return this->pimpl->write (data);
|
||||
Serial::write (const string &data)
|
||||
{
|
||||
return pimpl_->write (data);
|
||||
}
|
||||
|
||||
void
|
||||
Serial::setPort (const string &port) {
|
||||
bool was_open = pimpl->isOpen();
|
||||
if (was_open) this->close();
|
||||
this->pimpl->setPort (port);
|
||||
if (was_open) this->open();
|
||||
Serial::setPort (const string &port)
|
||||
{
|
||||
bool was_open = pimpl_->isOpen();
|
||||
if (was_open) close();
|
||||
pimpl_->setPort (port);
|
||||
if (was_open) open();
|
||||
}
|
||||
|
||||
string
|
||||
Serial::getPort () const {
|
||||
return this->pimpl->getPort ();
|
||||
Serial::getPort () const
|
||||
{
|
||||
return pimpl_->getPort ();
|
||||
}
|
||||
|
||||
void
|
||||
Serial::setTimeout (long timeout) {
|
||||
this->pimpl->setTimeout (timeout);
|
||||
Serial::setTimeout (long timeout)
|
||||
{
|
||||
pimpl_->setTimeout (timeout);
|
||||
}
|
||||
|
||||
long
|
||||
Serial::getTimeout () const {
|
||||
return this->pimpl->getTimeout ();
|
||||
return pimpl_->getTimeout ();
|
||||
}
|
||||
|
||||
void
|
||||
Serial::setBaudrate (unsigned long baudrate) {
|
||||
this->pimpl->setBaudrate (baudrate);
|
||||
Serial::setBaudrate (unsigned long baudrate)
|
||||
{
|
||||
pimpl_->setBaudrate (baudrate);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
Serial::getBaudrate () const {
|
||||
return this->pimpl->getBaudrate ();
|
||||
Serial::getBaudrate () const
|
||||
{
|
||||
return pimpl_->getBaudrate ();
|
||||
}
|
||||
|
||||
void
|
||||
Serial::setBytesize (bytesize_t bytesize) {
|
||||
this->pimpl->setBytesize (bytesize);
|
||||
Serial::setBytesize (bytesize_t bytesize)
|
||||
{
|
||||
pimpl_->setBytesize (bytesize);
|
||||
}
|
||||
|
||||
bytesize_t
|
||||
Serial::getBytesize () const {
|
||||
return this->pimpl->getBytesize ();
|
||||
Serial::getBytesize () const
|
||||
{
|
||||
return pimpl_->getBytesize ();
|
||||
}
|
||||
|
||||
void
|
||||
Serial::setParity (parity_t parity) {
|
||||
this->pimpl->setParity (parity);
|
||||
Serial::setParity (parity_t parity)
|
||||
{
|
||||
pimpl_->setParity (parity);
|
||||
}
|
||||
|
||||
parity_t
|
||||
Serial::getParity () const {
|
||||
return this->pimpl->getParity ();
|
||||
Serial::getParity () const
|
||||
{
|
||||
return pimpl_->getParity ();
|
||||
}
|
||||
|
||||
void
|
||||
Serial::setStopbits (stopbits_t stopbits) {
|
||||
this->pimpl->setStopbits (stopbits);
|
||||
Serial::setStopbits (stopbits_t stopbits)
|
||||
{
|
||||
pimpl_->setStopbits (stopbits);
|
||||
}
|
||||
|
||||
stopbits_t
|
||||
Serial::getStopbits () const {
|
||||
return this->pimpl->getStopbits ();
|
||||
Serial::getStopbits () const
|
||||
{
|
||||
return pimpl_->getStopbits ();
|
||||
}
|
||||
|
||||
void
|
||||
Serial::setFlowcontrol (flowcontrol_t flowcontrol) {
|
||||
this->pimpl->setFlowcontrol (flowcontrol);
|
||||
Serial::setFlowcontrol (flowcontrol_t flowcontrol)
|
||||
{
|
||||
pimpl_->setFlowcontrol (flowcontrol);
|
||||
}
|
||||
|
||||
flowcontrol_t
|
||||
Serial::getFlowcontrol () const {
|
||||
return this->pimpl->getFlowcontrol ();
|
||||
Serial::getFlowcontrol () const
|
||||
{
|
||||
return pimpl_->getFlowcontrol ();
|
||||
}
|
||||
|
||||
void Serial::flush() {
|
||||
this->pimpl->flush();
|
||||
void Serial::flush ()
|
||||
{
|
||||
pimpl_->flush ();
|
||||
memset (read_cache_, 0, buffer_size_);
|
||||
}
|
||||
|
||||
void Serial::flushInput() {
|
||||
this->pimpl->flushInput();
|
||||
void Serial::flushInput ()
|
||||
{
|
||||
pimpl_->flushInput ();
|
||||
}
|
||||
|
||||
void Serial::flushOutput() {
|
||||
this->pimpl->flushOutput();
|
||||
void Serial::flushOutput ()
|
||||
{
|
||||
pimpl_->flushOutput ();
|
||||
memset (read_cache_, 0, buffer_size_);
|
||||
}
|
||||
|
||||
void Serial::sendBreak(int duration) {
|
||||
this->pimpl->sendBreak(duration);
|
||||
void Serial::sendBreak (int duration)
|
||||
{
|
||||
pimpl_->sendBreak (duration);
|
||||
}
|
||||
|
||||
void Serial::setBreak(bool level) {
|
||||
this->pimpl->setBreak(level);
|
||||
void Serial::setBreak (bool level)
|
||||
{
|
||||
pimpl_->setBreak (level);
|
||||
}
|
||||
|
||||
void Serial::setRTS(bool level) {
|
||||
this->pimpl->setRTS(level);
|
||||
void Serial::setRTS (bool level)
|
||||
{
|
||||
pimpl_->setRTS (level);
|
||||
}
|
||||
|
||||
void Serial::setDTR(bool level) {
|
||||
this->pimpl->setDTR(level);
|
||||
void Serial::setDTR (bool level)
|
||||
{
|
||||
pimpl_->setDTR (level);
|
||||
}
|
||||
|
||||
bool Serial::getCTS() {
|
||||
return this->pimpl->getCTS();
|
||||
bool Serial::getCTS ()
|
||||
{
|
||||
return pimpl_->getCTS ();
|
||||
}
|
||||
|
||||
bool Serial::getDSR() {
|
||||
return this->pimpl->getDSR();
|
||||
bool Serial::getDSR ()
|
||||
{
|
||||
return pimpl_->getDSR ();
|
||||
}
|
||||
|
||||
bool Serial::getRI() {
|
||||
return this->pimpl->getRI();
|
||||
bool Serial::getRI ()
|
||||
{
|
||||
return pimpl_->getRI ();
|
||||
}
|
||||
|
||||
bool Serial::getCD() {
|
||||
return this->pimpl->getCD();
|
||||
bool Serial::getCD ()
|
||||
{
|
||||
return pimpl_->getCD ();
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
/* Copyright 2012 William Woodall and John Harrison */
|
||||
|
||||
#include "serial/serial_listener.h"
|
||||
|
||||
/***** Inline Functions *****/
|
||||
|
||||
@ -1,10 +1,3 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
// OMG this is so nasty...
|
||||
// #define private public
|
||||
// #define protected public
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
@ -14,17 +7,27 @@ using std::string;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using serial::Serial;
|
||||
using serial::SerialExecption;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Serial s("/dev/tty.usbserial-A900adHq", 115200, 2000);
|
||||
s.flush();
|
||||
int count = 0;
|
||||
while (1) {
|
||||
size_t available = s.available();
|
||||
cout << "avialable: " << available << endl;
|
||||
string line = s.readline();
|
||||
cout << count << ": " << line;
|
||||
count++;
|
||||
try {
|
||||
Serial s("/dev/tty.usbserial-A900adHq", 115200, 2000);
|
||||
s.flush();
|
||||
long long count = 0;
|
||||
while (1) {
|
||||
// size_t available = s.available();
|
||||
// cout << "avialable: " << available << endl;
|
||||
string line = s.readline();
|
||||
cout << count << ": " << line << line.length() << endl;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
catch (SerialExecption e)
|
||||
{
|
||||
cout << "Caught SerialException: " << e.what() << endl;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cout << "Caught an error." << endl;
|
||||
}
|
||||
cout << endl << endl;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user