Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef BOOST_SERIAL_H
- #define BOOST_SERIAL_H
- #include <array>
- #include <vector>
- #include <string>
- #include <mutex>
- #include <boost/asio.hpp>
- #include <boost/thread.hpp>
- #include "MMaster.h"
- class BoostSerial : AbstractSerial
- {
- private:
- //serial device stuff
- boost::asio::io_service serial_service;
- boost::asio::io_service::work serial_work;
- boost::asio::serial_port serial;
- //async stuff
- //boost::thread *asyncReadThread;
- std::unique_ptr<boost::thread> asyncReadThread;
- std::array<uint8_t, 256> buf;
- mutable std::mutex usableBufferMtx;
- std::vector<uint8_t> usableBuffer;
- void asyncReadHandler(const boost::system::error_code &error, std::size_t bytes_transferred);
- //serial config stuff
- int baud = 115200;
- public:
- BoostSerial();
- ~BoostSerial();
- //write one byte
- void write(uint8_t);
- //write vector of bytes
- void write(std::vector<uint8_t>);
- //write string
- void write(std::string);//todo
- //read one character/byte
- int16_t read();
- //read everything as a vector of bytes
- void read(std::vector<uint8_t> &);
- //read everything as a string
- void read(std::string &);
- //read to given character (doesn't includes it in the result but removes from buffer) or to end the of buffer if character couldn't be found
- void read(std::string &, char);
- //check next character in the buffer without removing it
- int16_t peek();
- //open serial port and stard async read thread
- void open(std::string);
- bool isOpen() const;
- void close();
- //returns whether there is data awaiting in the buffer
- bool available() const;
- //clear buffer
- void flush();
- void setBaud(int = 115200);
- };
- void BoostSerial::asyncReadHandler(const boost::system::error_code &error, std::size_t bytes_transferred)
- {
- //place the content of buffer array into usableBuffer vector
- //usableBuffer is necessary because using handler buffer directly in read() or available() functions
- //fuck ups entire world for some reason
- //probably due to manipulating buffer in async_read_some
- std::unique_lock<std::mutex> lk(usableBufferMtx);
- for(auto i = 0; i < bytes_transferred; i++)
- {
- usableBuffer.push_back(buf[i]);
- }
- lk.unlock();
- //read async again
- serial.async_read_some(
- boost::asio::buffer(buf, buf.size()),
- boost::bind(
- &BoostSerial::asyncReadHandler,
- this, boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
- }
- BoostSerial::BoostSerial() : serial_service(), serial(serial_service), serial_work(serial_service), asyncReadThread(nullptr) {}
- BoostSerial::~BoostSerial()
- {
- if (serial.is_open())
- close();
- }
- void BoostSerial::write(uint8_t c)
- {
- std::vector<uint8_t> v({c});
- write(v);
- }
- void BoostSerial::write(std::vector<uint8_t> v)
- {
- serial.write_some(boost::asio::buffer(v, v.size()));
- }
- void BoostSerial::write(std::string s)
- {
- serial.write_some(boost::asio::buffer(s, s.size()));
- }
- int16_t BoostSerial::read()
- {
- std::unique_lock<std::mutex> lk(usableBufferMtx);
- //return -1 if there is no data available
- if(!usableBuffer.size())
- return -1;
- //return first element and remove it from the buffer
- int res = usableBuffer[0];
- usableBuffer.erase(usableBuffer.begin());
- return res;
- }
- void BoostSerial::read(std::vector<uint8_t> &v)
- {
- //move content of buffer to user's variable
- std::unique_lock<std::mutex> lk(usableBufferMtx);
- v = std::move(usableBuffer);
- usableBuffer.clear();
- }
- void BoostSerial::read(std::string & s)
- {
- s = "";
- std::unique_lock<std::mutex> lk(usableBufferMtx);
- for(auto i: usableBuffer)
- s+=i;
- usableBuffer.clear();
- }
- void BoostSerial::read(std::string &s, char c)
- {
- s = "";
- char x;
- bool done = false;
- do
- {
- x = read();
- if(x != -1 || x != c)
- {
- s+=x;
- }
- else
- done = true;
- }while(!done);
- }
- int16_t BoostSerial::peek()
- {
- std::unique_lock<std::mutex> lk(usableBufferMtx);
- //return -1 if there is no data available
- if(!usableBuffer.size())
- return -1;
- return usableBuffer[0];;
- }
- void BoostSerial::open(std::string dname)
- {
- serial.open(dname);
- if (!serial.is_open())
- return;
- serial.set_option(boost::asio::serial_port_base::baud_rate(baud));
- //create thread that will read incoming data asynchronously
- asyncReadThread.reset(new boost::thread(boost::bind(&boost::asio::io_service::run, &serial_service)));
- //push the first read request
- serial.async_read_some(
- boost::asio::buffer(buf, buf.size()),
- boost::bind(
- &BoostSerial::asyncReadHandler,
- this, boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
- }
- bool BoostSerial::isOpen() const
- {
- return serial.is_open();
- }
- void BoostSerial::close()
- {
- if(!serial.is_open())
- return;
- //cancel pending async processes
- serial.cancel();
- //finish async read thread and delete it
- serial_service.stop();
- asyncReadThread->join();
- serial.close();
- }
- bool BoostSerial::available() const
- {
- //returns true if there are some bytes in the buffer
- std::unique_lock<std::mutex> lk(usableBufferMtx);
- return (bool)usableBuffer.size();
- }
- void BoostSerial::flush()
- {
- std::vector<uint8_t> dull;
- if (available())
- read(dull);
- }
- void BoostSerial::setBaud(int baud_)
- {
- baud = baud_;
- if(serial.is_open())
- serial.set_option(boost::asio::serial_port_base::baud_rate(baud));
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement