提取出 Data_Source_Handler

This commit is contained in:
2026-06-23 14:01:23 +08:00
parent d621dad9a1
commit 8a1d13aeb5
+167
View File
@@ -0,0 +1,167 @@
#pragma once
#include "Serial.h"
#include <asio/error_code.hpp>
#include <asio/io_context.hpp>
#include <asio/serial_port.hpp>
#include <asio/write.hpp>
#include <ucoro/awaitable.hpp>
#include <cstddef>
#include <memory>
#include <string>
namespace Psc::serial {
class Serial_Coro : public Serial {
public:
bool open()
{
if (port_ && port_->is_open()) {
return true;
}
port_ = std::make_unique<asio::serial_port>(io_context_);
asio::error_code ec;
port_->open(normalize_port_name(serial_name), ec);
if (ec) {
return false;
}
apply_options(ec);
if (ec) {
close();
return false;
}
serial::set_block(port_->native_handle(), false);
return true;
}
void close()
{
if (!port_) {
return;
}
asio::error_code ec;
port_->cancel(ec);
port_->close(ec);
port_.reset();
io_context_.restart();
}
[[nodiscard]] ucoro::awaitable<void> tick_coro()
{
io_context_.poll();
co_return;
}
[[nodiscard]] ucoro::awaitable<std::string> read_coro(std::size_t max_size = 16 * 1024)
{
co_await tick_coro();
if (!port_ || !port_->is_open()) {
co_return "";
}
auto available = serial::get_available_bytes(port_->native_handle());
if (available <= 0) {
co_return "";
}
auto data = serial::read_all(port_->native_handle());
if (data.size() > max_size) {
data.resize(max_size);
}
co_return data;
}
[[nodiscard]] ucoro::awaitable<std::size_t> write_coro(std::string data)
{
co_await tick_coro();
if (!port_ || !port_->is_open() || data.empty()) {
co_return 0;
}
asio::error_code ec;
auto size = asio::write(*port_, asio::buffer(data), ec);
if (ec) {
co_return 0;
}
co_return size;
}
std::string read(int64_t size = -1)
{
auto max_size = size > 0 ? static_cast<std::size_t>(size) : static_cast<std::size_t>(16 * 1024);
return ucoro::sync_await(read_coro(max_size));
}
int64_t write(const std::string& data)
{
return static_cast<int64_t>(ucoro::sync_await(write_coro(data)));
}
int get_available_bytes()
{
if (!port_ || !port_->is_open()) {
return 0;
}
return serial::get_available_bytes(port_->native_handle());
}
private:
static std::string normalize_port_name(std::string port_name)
{
#ifdef _WIN32
if (port_name.rfind("\\\\.\\", 0) != 0) {
port_name = "\\\\.\\" + port_name;
}
#endif
return port_name;
}
void apply_options(asio::error_code& ec)
{
if (baud_rate != static_cast<Baud_Rate_Type>(-1)) {
port_->set_option(asio::serial_port_base::baud_rate(static_cast<unsigned int>(baud_rate)), ec);
if (ec) return;
}
if (dataBits != DataBits::UnknownDataBits) {
port_->set_option(asio::serial_port_base::character_size(static_cast<unsigned int>(dataBits)), ec);
if (ec) return;
}
if (parity != Parity::UnknownParity) {
asio::serial_port_base::parity::type value = asio::serial_port_base::parity::none;
if (parity == Parity::EvenParity) value = asio::serial_port_base::parity::even;
if (parity == Parity::OddParity) value = asio::serial_port_base::parity::odd;
port_->set_option(asio::serial_port_base::parity(value), ec);
if (ec) return;
}
if (stopBits != StopBits::UnknownStopBits) {
asio::serial_port_base::stop_bits::type value = asio::serial_port_base::stop_bits::one;
if (stopBits == StopBits::OneAndHalfStop) value = asio::serial_port_base::stop_bits::onepointfive;
if (stopBits == StopBits::TwoStop) value = asio::serial_port_base::stop_bits::two;
port_->set_option(asio::serial_port_base::stop_bits(value), ec);
if (ec) return;
}
if (flow_control != FlowControl::UnknownFlowControl) {
asio::serial_port_base::flow_control::type value = asio::serial_port_base::flow_control::none;
if (flow_control == FlowControl::HardwareControl) value = asio::serial_port_base::flow_control::hardware;
if (flow_control == FlowControl::SoftwareControl) value = asio::serial_port_base::flow_control::software;
port_->set_option(asio::serial_port_base::flow_control(value), ec);
}
}
asio::io_context io_context_;
std::unique_ptr<asio::serial_port> port_;
};
} // namespace Psc::serial