diff --git a/include/RealSerialPort.h b/include/RealSerialPort.h index 299dddd..26bc5cc 100644 --- a/include/RealSerialPort.h +++ b/include/RealSerialPort.h @@ -3,6 +3,7 @@ #include "ISerialPort.h" #include +#include using boost::asio::serial_port_base; @@ -11,7 +12,15 @@ class RealSerialPort : public ISerialPort { explicit RealSerialPort(boost::asio::io_service& io) : port(io) {} void open(const std::string& device, serial_port_base::baud_rate baudRate) override { - port.open(device); + try { + port.open(device); + setSerialOptions(baudRate); + } catch (const boost::system::system_error& e) { + BOOST_LOG_TRIVIAL(error) << "Failed to open serial port: " << e.what(); + } + } + + void setSerialOptions(serial_port_base::baud_rate baudRate) { port.set_option(baudRate); port.set_option(serial_port_base::character_size(8)); port.set_option(serial_port_base::parity(serial_port_base::parity::none)); @@ -20,10 +29,18 @@ class RealSerialPort : public ISerialPort { } void async_read_some(const boost::asio::mutable_buffer& buffer, std::function handler) override { + if (!port.is_open()) { + BOOST_LOG_TRIVIAL(error) << "Attempt to read from a closed serial port."; + return; + } port.async_read_some(buffer, handler); } void async_write(const boost::asio::const_buffer& buffer, std::function handler) override { + if (!port.is_open()) { + BOOST_LOG_TRIVIAL(error) << "Attempt to write to a closed serial port."; + return; + } boost::asio::async_write(port, buffer, handler); } diff --git a/include/SerialServer.h b/include/SerialServer.h index 2a53059..e640f49 100644 --- a/include/SerialServer.h +++ b/include/SerialServer.h @@ -1,27 +1,27 @@ -#ifndef SERVER_H -#define SERVER_H +#ifndef SERIALSERVER_H +#define SERIALSERVER_H -#include "common.hpp" -#include "ISerialPort.h" #include "RealSerialPort.h" - -using namespace boost::asio; -using ip::tcp; -using std::string; +#include +#include class SerialServer { +public: + SerialServer(boost::asio::io_service& io_service, const std::string& device, unsigned int baud_rate); + + void run(); + private: + void start_accept(); + void handle_session(); + void async_read_socket(); + void async_read_serial(); + boost::asio::io_service& io_service_; - ISerialPort& serial_; - boost::asio::ip::tcp::acceptor& acceptor_; + boost::asio::ip::tcp::acceptor acceptor_; boost::asio::ip::tcp::socket socket_; - std::array buf; // Buffer for data - - void start_accept(); - void do_read_write(); -public: - SerialServer(boost::asio::io_service& io, ISerialPort& serial, boost::asio::ip::tcp::acceptor& acceptor); - void run(); + RealSerialPort serial_port_; + std::array buffer_; }; -#endif // SERVER_H +#endif // SERIALSERVER_H diff --git a/src/SerialServer.cpp b/src/SerialServer.cpp index ace35ea..91cdbd7 100644 --- a/src/SerialServer.cpp +++ b/src/SerialServer.cpp @@ -1,52 +1,63 @@ #include "SerialServer.h" +#include -using namespace boost::asio; -using namespace boost::program_options; -using ip::tcp; -using std::string; -using std::endl; - -SerialServer::SerialServer(io_service& io, ISerialPort& serial, tcp::acceptor& acceptor) - : io_service_(io), serial_(serial), acceptor_(acceptor), socket_(io) { - BOOST_LOG_TRIVIAL(info) << "Starting server and waiting for connection..."; - start_accept(); -} +SerialServer::SerialServer(boost::asio::io_service& io_service, const std::string& device, unsigned int baud_rate) + : io_service_(io_service), + acceptor_(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 3333)), + socket_(io_service), + serial_port_(io_service) { + serial_port_.open(device, boost::asio::serial_port_base::baud_rate(baud_rate)); + } void SerialServer::run() { - BOOST_LOG_TRIVIAL(info) << "Server is running."; + start_accept(); io_service_.run(); - BOOST_LOG_TRIVIAL(info) << "Server stopped."; } void SerialServer::start_accept() { acceptor_.async_accept(socket_, [this](boost::system::error_code ec) { if (!ec) { - BOOST_LOG_TRIVIAL(info) << "Client connected. Starting to handle read/write operations."; - do_read_write(); - } else { - BOOST_LOG_TRIVIAL(error) << "Error accepting connection: " << ec.message(); - start_accept(); + handle_session(); } + start_accept(); }); } -void SerialServer::do_read_write() { - // Asynchronous read from serial port - serial_.async_read_some(boost::asio::buffer(buf), [this](boost::system::error_code ec, std::size_t length) { - if (!ec && length > 0) { - // Data is available - async_write(socket_, boost::asio::buffer(buf, length), [this](boost::system::error_code ec, std::size_t) { +void SerialServer::handle_session() { + async_read_socket(); + async_read_serial(); +} + +void SerialServer::async_read_socket() { + socket_.async_read_some(boost::asio::buffer(buffer_), [this](boost::system::error_code ec, std::size_t length) { + if (!ec) { + serial_port_.async_write(boost::asio::buffer(buffer_, length), [this](boost::system::error_code ec, std::size_t) { if (!ec) { - BOOST_LOG_TRIVIAL(info) << "Data successfully written to client."; + async_read_socket(); } else { BOOST_LOG_TRIVIAL(error) << "Error writing to client: " << ec.message(); } }); - } else if (!ec) { - BOOST_LOG_TRIVIAL(info) << "No data received from serial. Waiting..."; } else { - BOOST_LOG_TRIVIAL(error) << "Error reading from serial port: " << ec.message(); + BOOST_LOG_TRIVIAL(error) << "Read error on socket: " << ec.message(); + socket_.close(); + } + }); +} + +void SerialServer::async_read_serial() { + serial_port_.async_read_some(boost::asio::buffer(buffer_), [this](boost::system::error_code ec, std::size_t length) { + if (!ec) { + boost::asio::async_write(socket_, boost::asio::buffer(buffer_, length), [this](boost::system::error_code ec, std::size_t) { + if (!ec) { + async_read_serial(); + } else { + BOOST_LOG_TRIVIAL(error) << "Error sending to socket: " << ec.message(); + } + }); + } else { + BOOST_LOG_TRIVIAL(error) << "Read error on serial port: " << ec.message(); + socket_.close(); } - do_read_write(); // Continue the loop }); } diff --git a/src/main.cpp b/src/main.cpp index 26599a8..89732e2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,11 +14,8 @@ using std::cerr; using std::endl; void setup_and_run_server(io_service& io, const variables_map& vm) { - tcp::acceptor acceptor(io, tcp::endpoint(tcp::v4(), vm["port"].as())); - RealSerialPort realSerial(io); - realSerial.open(vm["device"].as(), boost::asio::serial_port_base::baud_rate(vm["baud"].as())); - - SerialServer server(io, realSerial, acceptor); + unsigned int baud_rate = vm["baud"].as(); // Get baud rate as unsigned int + SerialServer server(io, vm["device"].as(), baud_rate); server.run(); }