NMEA: benchmark for to_string(sentence) added.
[marnav.git] / examples / serial_to_tcp.cpp
blobc584ad70515a6e4a322f3c4c93dfe090d50ddb8d
1 // This example shows how to receive NMEA sentences on a port, check them
2 // and forward it to a TCP server, which listens for sentences.
3 //
4 // Boost.ASIO is used for both, serial and TCP connections.
6 #include <boost/asio.hpp>
7 #include <marnav/nmea/nmea.hpp>
8 #include <marnav/io/default_nmea_reader.hpp>
9 #include <marnav/utils/unique.hpp>
11 namespace marnav_example
13 /// Synchronous reading of the serial port using Boost.ASIO
14 ///
15 /// @note Inline implemented for easier reading within this example.
16 class boost_asio_serial : public marnav::io::device
18 public:
19 boost_asio_serial(const std::string & port, int baud_rate = 4800)
20 : io()
21 , serial(io, port)
23 serial.set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
26 virtual void open() override{};
28 virtual void close() override { serial.close(); }
30 virtual int read(char * buffer, uint32_t size) override
32 if ((buffer == nullptr) || (size == 0))
33 throw std::invalid_argument{"invalid buffer or size"};
34 if (!serial.is_open())
35 throw std::runtime_error{"device not open"};
36 return boost::asio::read(serial, boost::asio::buffer(buffer, size));
39 virtual int write(const char * buffer, uint32_t size) override
41 if (buffer == nullptr)
42 throw std::invalid_argument{"invalid buffer"};
43 if (!serial.is_open())
44 throw std::runtime_error{"device not open"};
45 return boost::asio::write(serial, boost::asio::buffer(buffer, size));
48 private:
49 boost::asio::io_service io;
50 boost::asio::serial_port serial;
53 /// Blocking TCP client
54 ///
55 /// @note Inline implemented for easier reading within this example.
56 class boost_asio_tcp_client
58 public:
59 boost_asio_tcp_client(const std::string & host, const std::string & port)
60 : io()
61 , socket(io)
63 boost::asio::ip::tcp::resolver resolver{io};
64 boost::asio::connect(socket, resolver.resolve({host, port}));
67 ~boost_asio_tcp_client() {}
69 int write(const char * buffer, uint32_t size)
71 if (buffer == nullptr)
72 throw std::invalid_argument{"invalid buffer or size"};
73 if (!socket.is_open())
74 throw std::runtime_error{"device not open"};
75 return boost::asio::write(socket, boost::asio::buffer(buffer, size));
78 private:
79 boost::asio::io_service io;
80 boost::asio::ip::tcp::socket socket;
84 int main(int, char **)
86 using namespace marnav;
87 using namespace marnav_example;
89 // open input port and reader
90 io::default_nmea_reader input{utils::make_unique<boost_asio_serial>("/dev/ttyUSB0", 38400)};
92 // open output port (TCP client), default port of certain navigational software
93 boost_asio_tcp_client output{"127.0.0.1", "2947"};
95 std::string data;
97 // read and process NMEA sentences, bus synchronization is done automatically.
98 while (input.read_sentence(data)) {
99 try {
100 // data was successfully read from the NMEA bus, inclusive synchronization
101 // of NMEA sentences. This means it is possible to begin to listen on the
102 // bus at any time.
103 auto sentence = nmea::make_sentence(data);
105 // valid sentence was received, forward it
106 output.write(data.c_str(), data.size());
107 } catch (std::exception e) {
108 // ignore unknown sentences and other stuff
112 return 0;