1

I use boost asio async_read_some, the data I want to read STXdataETXlrc, if it were not for lrc I would use async_read_until, how can I continue reading until I get ETXlrc? appreciate all the help.

/huvcbo

sehe
  • 374,641
  • 47
  • 450
  • 633
huvcbo
  • 19
  • 1

1 Answers1

0

From the very sparse information, I'm assuming you are talking in the context of serial comms.

In that case, the simplest way to get started might be to use Asio's composed read operations (like read, read_until etc).

comm::read_until(sp, buf, '\x03');

With a bit of syntactic sugar you can write more expressively:

enum ControlCodes : uint8_t {
    STX = 2,
    ETX = 3,
};

E.g.:

#include <boost/asio.hpp>
#include <boost/asio/serial_port.hpp>
#include <iostream>
namespace comm = boost::asio;
enum ControlCodes : uint8_t {
    STX = 2,
    ETX = 3,
};

int main(int argc, char** argv) {
    comm::io_context ioc;
    comm::serial_port sp(ioc, argc > 1 ? argv[1] : "/dev/ttyS6");
    sp.set_option(comm::serial_port::baud_rate(115'200));

    std::vector<uint8_t> data;
    comm::read_until(sp, comm::dynamic_buffer(data), ETX);
}

You could then proceed to to a fixed-length read to get the checksum. More involved overloads of read_until allow you to write MatchCondition instead so you can combine it all in a single call: https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/reference/read_until.html.

Here's an example that uses the boost::regex overload, that shows the message and whether the checksum verifies:

Live On Compiler Explorer

#include <boost/asio.hpp>
#include <boost/asio/serial_port.hpp>
#include <boost/regex.hpp>
#include <fmt/ranges.h>
#include <numeric>
namespace comm = boost::asio;
enum ControlCodes : uint8_t {
    STX = 2,
    ETX = 3,
};

int main(int argc, char** argv) {
    comm::io_context ioc;
    comm::serial_port sp(ioc, argc > 1 ? argv[1] : "/dev/ttyS6");
    sp.set_option(comm::serial_port::baud_rate(115'200));

    std::vector<uint8_t> buffer;
    auto n = comm::read_until(sp, comm::dynamic_buffer(buffer), boost::regex("\x03."));

    auto raw = buffer.data();
    bool ok  = n >= 3 && *raw == STX;
    if (ok) {
        auto b   = raw + 1;
        auto e   = b + n - 3; // payload excludes STX, ETX, LRC
        auto lrc = accumulate(b, e, uint8_t(0), std::bit_xor<>{});
        bool verified = raw[n - 1] == lrc;

        fmt::print("Checksum {} bytes verified {}, buffer {::#02x} (expected {:#02x})\n",
                   n, verified, buffer, lrc);
    } else {
        fmt::print("Message not wellformed {} bytes buffer {::#02x}\n", n, buffer);
    }
}

Tested locally using socat:

enter image description here

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Added a bonus take that should verify the checksum (untested) [Live On Compiler Explorer](https://godbolt.org/z/qsnorcqdo) – sehe Mar 07 '22 at 15:10
  • Now tested: https://godbolt.org/z/e3KGGshWW (of course I had an off-by-one error) and a demo run using socat: https://i.stack.imgur.com/jqmr5.gif – sehe Mar 07 '22 at 15:44