28#include "AsyncSerial.h"
33#include <boost/bind/bind.hpp>
46 boost::asio::io_service
io;
47 boost::asio::serial_port
port;
64 boost::function<void(
const char*,
size_t)>
callback;
72bool AsyncSerial::isPortAvailable(std::string portName)
76 boost::asio::io_service service;
77 boost::asio::serial_port sp(service, portName);
85 catch (std::exception&)
93AsyncSerial::AsyncSerial(
const std::string& devname,
unsigned int baud_rate,
94 boost::asio::serial_port_base::parity opt_parity,
95 boost::asio::serial_port_base::character_size opt_csize,
96 boost::asio::serial_port_base::flow_control opt_flow,
97 boost::asio::serial_port_base::stop_bits opt_stop)
101 mBaudrate = boost::asio::serial_port_base::baud_rate(baud_rate);
102 mParity = opt_parity;
107 pimpl->backgroundThread = boost::thread(boost::bind(&boost::asio::io_service::run, &pimpl->io));
112 boost::asio::serial_port_base::parity opt_parity,
113 boost::asio::serial_port_base::character_size opt_csize,
114 boost::asio::serial_port_base::flow_control opt_flow,
115 boost::asio::serial_port_base::stop_bits opt_stop)
121 pimpl->port.open(devname);
122 pimpl->port.set_option(mBaudrate);
123 pimpl->port.set_option(mParity);
124 pimpl->port.set_option(mCsize);
125 pimpl->port.set_option(mFlow);
126 pimpl->port.set_option(mStopbit);
129 pimpl->io.post(boost::bind(&AsyncSerial::doRead,
this));
143 if (mDevname.length() <= 3)
146 mDevname =
"COM" + mDevname;
148 std::string testport =
"/dev/ttyS" + mDevname;
149 if (isPortAvailable(testport))
155 testport =
"/dev/ttyUSB" + mDevname;
156 if (isPortAvailable(testport))
162 testport =
"/dev/ttyACM" + mDevname;
163 if (isPortAvailable(testport))
169 testport =
"/dev/rfcomm" + mDevname;
170 if (isPortAvailable(testport))
181 pimpl->port.open(mDevname);
182 pimpl->port.set_option(boost::asio::serial_port_base::baud_rate(mBaudrate));
183 pimpl->port.set_option(mParity);
184 pimpl->port.set_option(mCsize);
185 pimpl->port.set_option(mFlow);
186 pimpl->port.set_option(mStopbit);
187 pimpl->writeQueue.clear();
188 pimpl->writeBuffer.reset();
189 pimpl->writeBufferSize = 0;
192 pimpl->io.post(boost::bind(&AsyncSerial::doRead,
this));
197 catch (std::exception&)
211 boost::lock_guard<boost::mutex> l(pimpl->errorMutex);
215void AsyncSerial::setQuitStatus(
bool e)
217 boost::lock_guard<boost::mutex> l(pimpl->quitMutex);
221bool AsyncSerial::quitStatus()
const
223 boost::lock_guard<boost::mutex> l(pimpl->quitMutex);
231 pimpl->backgroundThread.join();
240 throw(boost::system::system_error(boost::system::error_code(),
241 "Error while closing the device"));
251 boost::lock_guard<boost::mutex> l(pimpl->writeQueueMutex);
252 pimpl->writeQueue.insert(pimpl->writeQueue.end(), data, data + size);
254 pimpl->io.post(boost::bind(&AsyncSerial::doWrite,
this));
263 boost::lock_guard<boost::mutex> l(pimpl->writeQueueMutex);
264 pimpl->writeQueue.insert(pimpl->writeQueue.end(), data.begin(),
267 pimpl->io.post(boost::bind(&AsyncSerial::doWrite,
this));
276 boost::lock_guard<boost::mutex> l(pimpl->writeQueueMutex);
277 pimpl->writeQueue.insert(pimpl->writeQueue.end(), s.begin(), s.end());
279 pimpl->io.post(boost::bind(&AsyncSerial::doWrite,
this));
283AsyncSerial::~AsyncSerial()
295void AsyncSerial::doRead()
297 pimpl->port.async_read_some(boost::asio::buffer(pimpl->readBuffer,
readBufferSize),
298 boost::bind(&AsyncSerial::readEnd,
300 boost::asio::placeholders::error,
301 boost::asio::placeholders::bytes_transferred));
304void AsyncSerial::readEnd(
const boost::system::error_code& error,
305 size_t bytes_transferred)
319 if (pimpl->callback) pimpl->callback(pimpl->readBuffer, bytes_transferred);
324void AsyncSerial::doWrite()
327 if (pimpl->writeBuffer == 0)
329 boost::lock_guard<boost::mutex> l(pimpl->writeQueueMutex);
330 pimpl->writeBufferSize = pimpl->writeQueue.size();
331 pimpl->writeBuffer.reset(
new char[pimpl->writeQueue.size()]);
332 copy(pimpl->writeQueue.begin(), pimpl->writeQueue.end(), pimpl->writeBuffer.get());
333 pimpl->writeQueue.clear();
334 async_write(pimpl->port, boost::asio::buffer(pimpl->writeBuffer.get(), pimpl->writeBufferSize), boost::bind(&AsyncSerial::writeEnd,
this, boost::asio::placeholders::error));
338void AsyncSerial::writeEnd(
const boost::system::error_code& error)
342 boost::lock_guard<boost::mutex> l(pimpl->writeQueueMutex);
343 if (pimpl->writeQueue.empty())
345 pimpl->writeBuffer.reset();
346 pimpl->writeBufferSize = 0;
350 pimpl->writeBufferSize = pimpl->writeQueue.size();
351 pimpl->writeBuffer.reset(
new char[pimpl->writeQueue.size()]);
352 copy(pimpl->writeQueue.begin(), pimpl->writeQueue.end(), pimpl->writeBuffer.get());
353 pimpl->writeQueue.clear();
354 async_write(pimpl->port, boost::asio::buffer(pimpl->writeBuffer.get(), pimpl->writeBufferSize), boost::bind(&AsyncSerial::writeEnd,
this, boost::asio::placeholders::error));
363void AsyncSerial::doClose()
365 boost::system::error_code ec;
366 pimpl->port.cancel(ec);
371 pimpl->port.close(ec);
373 pimpl->writeQueue.clear();
386 boost::lock_guard<boost::mutex> l(pimpl->errorMutex);
392 pimpl->callback = callback;
397 pimpl->callback.clear();
404CallbackAsyncSerial::CallbackAsyncSerial() :
AsyncSerial()
409CallbackAsyncSerial::CallbackAsyncSerial(
const std::string& devname,
410 unsigned int baud_rate,
411 boost::asio::serial_port_base::parity opt_parity,
412 boost::asio::serial_port_base::character_size opt_csize,
413 boost::asio::serial_port_base::flow_control opt_flow,
414 boost::asio::serial_port_base::stop_bits opt_stop)
415 :
AsyncSerial(devname, baud_rate, opt_parity, opt_csize, opt_flow, opt_stop)
421 boost::function<
void(
const char*,
size_t)>& callback)
431CallbackAsyncSerial::~CallbackAsyncSerial()
void write(const char *data, size_t size)
void setReadCallback(const boost::function< void(const char *, size_t)> &callback)
void writeString(const std::string &s)
void open(const std::string &devname, unsigned int baud_rate, boost::asio::serial_port_base::parity opt_parity=boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none), boost::asio::serial_port_base::character_size opt_csize=boost::asio::serial_port_base::character_size(8), boost::asio::serial_port_base::flow_control opt_flow=boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none), boost::asio::serial_port_base::stop_bits opt_stop=boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one))
static const int readBufferSize
void setErrorStatus(bool e)
boost::thread backgroundThread
Thread that runs read/write operations.
boost::shared_array< char > writeBuffer
Data being written.
char readBuffer[AsyncSerial::readBufferSize]
data being read
boost::mutex quitMutex
Mutex for access to error.
boost::asio::io_service io
Io service object.
boost::function< void(const char *, size_t)> callback
Read complete callback.
boost::mutex writeQueueMutex
Mutex for access to writeQueue.
bool open
True if port open.
boost::asio::serial_port port
Serial port object.
boost::mutex errorMutex
Mutex for access to error.
std::vector< char > writeQueue
Data are queued here before they go in writeBuffer.
size_t writeBufferSize
Size of writeBuffer.
void setCallback(const boost::function< void(const char *, size_t)> &callback)