c++ – Using Full-Duplex Serial Port with ASIO (or other libraries) in a Synchronous Manner
Yes you can do it the complicated way by synchronizing multi thread access to the IO object:
(todo coming up with complicated example)
Simpler, Single-Threaded Async
#include <boost/asio.hpp>
#include <boost/asio/serial_port.hpp>
#include <deque>
#include <iomanip>
#include <iostream>
namespace asio = boost::asio;
using sp = asio::serial_port;
using boost::system::error_code;
using namespace std::literals;
struct Example {
Example(asio::any_io_executor ex, std::string dev) : sp_(ex, dev) {
readLoop();
}
void Send(std::string cmd) {
std::cerr << "Queue: " << quoted(cmd) << std::endl;
outbox_.push_back(std::move(cmd));
if (outbox_.size() == 1)
writeLoop();
}
void Stop() {
sp_.cancel();
}
private:
void readLoop() {
asio::async_read_until( //
sp_, asio::dynamic_buffer(incoming_), "\n", [this](error_code ec, size_t len) {
std::cerr << "Read: " << len << " (" << ec.message() << ")" << std::endl;
if (!ec.failed()) {
Send("echo: "s + incoming_.substr(0, len));
incoming_.erase(0, len);
readLoop();
}
});
}
void writeLoop() {
if (outbox_.empty())
return;
asio::async_write(sp_, asio::buffer(outbox_.front()), [this](error_code ec, size_t len) {
std::cerr << "Wrote: " << len << " (" << ec.message() << ")" << std::endl;
if (!ec.failed()) {
outbox_.pop_front();
writeLoop();
}
});
}
asio::serial_port sp_;
std::string incoming_;
std::deque<std::string> outbox_;
};
int main(int argc, char** argv) {
asio::io_context ioc;
Example drone(ioc.get_executor(), (argc > 1 ? argv[1] : "/dev/stty0"));
ioc.run_for(30s);
// not really needed, but to show graceful shutdown
drone.Stop();
ioc.run();
}
Live Demo:
Read more here: Source link

