简体   繁体   English

asio_read_some 继续阅读以获取所有数据

[英]asio_read_some countinue reading to get all data

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?我用的是boost asio async_read_some,我要读取的数据是STXdataETXlrc,如果不是lrc我就用async_read_until,怎么继续读到ETXlrc? appreciate all the help.感谢所有帮助。

/huvcbo /huvcbo

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).在这种情况下,最简单的入门方法可能是使用 Asio 的组合读取操作(如readread_until等)。

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,
};

Eg:例如:

#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 .更多涉及的read_until重载允许您改为编写MatchCondition ,以便您可以将它们全部组合在一个调用中: 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:这是一个使用boost::regex重载的示例,它显示消息以及校验和是否验证:

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 :使用socat在本地测试:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM