提取出 Data_Source_Handler
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user