Files
CPP_Core/Core/Serial/Serial.cpp
T
2026-06-29 09:40:55 +08:00

282 lines
8.5 KiB
C++

#include "Serial.h"
#include "Core/Statistics/Frequency_Limit.h"
#include "Serial_p.h"
#include <thread>
#include <utility>
#include <string_view>
void serial_log(Log_Type &log_type, std::string_view MSG) {
Frequency_Limit_Multi lm;
bool ok = lm.test(std::to_string(Psc::get_error_code()));
if (!ok)
return;
std::ostringstream oss;
BaseLogger::Log_Info info{true, spdlog::level::debug, "", log_type, std::string(MSG)};
oss << Psc::get_error_message()
<< BaseLogger::to_log(info)
<< std::endl;
if (!Psc::serial::serial_logger) {
std::cout << oss.str() << std::endl;
} else {
Psc::serial::serial_logger->error(" ", {}, oss.str());
}
}
namespace Psc::serial {
BaseLogger *serial_logger = nullptr;
bool Serial::open() {
fd = Psc::serial::open(serial_name);
if (fd == INVALID_HANDLE_VALUE) {
LOG_ERROR("Serial::open() 打开串口失败!");
return false;
}
serial_info = get_serial_info(fd);
set_binary_mode(serial_info);
std::ostringstream oss;
oss << "\n属性来源:\n";
if (buffer_byte_size == -1) {
buffer_byte_size = serial::get_buffer_byte_size(fd);
oss << "\t获取 buffer_byte_size: " << buffer_byte_size << std::endl;
} else {
serial::set_buffer_byte_size(fd, buffer_byte_size);
oss << "\t设置 buffer_byte_size: " << buffer_byte_size << std::endl;
}
if (baud_rate == -1) {
baud_rate = serial::get_baud_rate(serial_info);
oss << "\t获取 baud_rate: " << baud_rate << std::endl;
} else {
serial::set_baud_rate(serial_info, fd, baud_rate);
oss << "\t设置 baud_rate: " << baud_rate << std::endl;
}
if (dataBits == DataBits::UnknownDataBits) {
dataBits = serial::get_data_bits(serial_info);
oss << "\t获取 dataBits: " << Psc::to_string(dataBits) << std::endl;
} else {
serial::set_data_bits(serial_info, dataBits);
oss << "\t设置 dataBits: " << Psc::to_string(dataBits) << std::endl;
}
if (stopBits == StopBits::UnknownStopBits) {
stopBits = serial::get_stop_bits(serial_info);
oss << "\t获取 stopBits: " << Psc::to_string(stopBits) << std::endl;
} else {
serial::set_stop_bits(serial_info, stopBits);
oss << "\t设置 stopBits: " << Psc::to_string(stopBits) << std::endl;
}
if (parity == Parity::UnknownParity) {
parity = serial::get_parity(serial_info);
oss << "\t获取 parity: " << Psc::to_string(parity) << std::endl;
} else {
serial::set_parity(serial_info, parity);
oss << "\t设置 parity: " << Psc::to_string(parity) << std::endl;
}
if (flow_control == FlowControl::UnknownFlowControl) {
flow_control = serial::get_flow_control(serial_info);
oss << "\t获取 flow_control: " << Psc::to_string(flow_control) << std::endl;
} else {
serial::set_flow_control(serial_info, flow_control);
oss << "\t设置 flow_control: " << Psc::to_string(flow_control) << std::endl;
}
// oss << "最终设置: " << to_string();
// std::string s = oss.str();
// std::cout << s << std::endl;
set_block(fd, false);
set_serial_info(fd, serial_info);
serial_logger->debug("", {}, oss.str());
return true;
}
void Serial::close() {
serial::close(fd);
fd = INVALID_HANDLE_VALUE;
}
int64_t Serial::write(std::string_view data) {
return serial::write(fd, data.data(), data.size());
}
std::string Serial::read(int64_t size) { return read_all(fd); }
int Serial::get_available_bytes() { return serial::get_available_bytes(fd); }
std::string Serial::to_string() {
std::stringstream oss;
oss << "{" << std::endl;
oss << "\tfd:" << fd << std::endl;
oss << "\tbuffer_byte_size: " << serial::get_buffer_byte_size(fd)
<< std::endl;
oss << "\tbaud_rate: " << serial::get_baud_rate(serial_info) << std::endl;
oss << "\tdataBits: " << Psc::to_string(serial::get_data_bits(serial_info))
<< std::endl;
oss << "\tstopBits: " << Psc::to_string(serial::get_stop_bits(serial_info))
<< std::endl;
oss << "\tparity: " << Psc::to_string(serial::get_parity(serial_info))
<< std::endl;
oss << "\tflow_control: "
<< Psc::to_string(serial::get_flow_control(serial_info)) << std::endl;
oss << "}" << std::endl;
return oss.str();
}
void Serial::set_serial_name(std::string_view serial_name) {
this->serial_name = serial_name;
}
std::string Serial::get_serial_name() { return this->serial_name; }
void Serial::set_baud_rate(Baud_Rate_Type baud_rate) {
this->baud_rate = baud_rate;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_baud_rate(serial_info, fd, baud_rate);
set_serial_info(fd, serial_info);
}
}
Baud_Rate_Type Serial::get_baud_rate() { return baud_rate; }
void Serial::set_data_bits(DataBits data_bits) {
this->dataBits = data_bits;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_data_bits(serial_info, data_bits);
set_serial_info(fd, serial_info);
}
}
DataBits Serial::get_data_bits() { return dataBits; }
void Serial::set_stop_bits(StopBits stop_bits) {
this->stopBits = stop_bits;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_stop_bits(serial_info, stop_bits);
set_serial_info(fd, serial_info);
}
}
StopBits Serial::get_stop_bits() { return stopBits; }
void Serial::set_parity(Parity parity) {
this->parity = parity;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_parity(serial_info, parity);
set_serial_info(fd, serial_info);
}
}
Parity Serial::get_parity() { return parity; }
void Serial::set_flow_control(FlowControl flow_control) {
this->flow_control = flow_control;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_flow_control(serial_info, flow_control);
set_serial_info(fd, serial_info);
}
}
FlowControl Serial::get_flow_control() { return flow_control; }
void Serial::set_buffer_byte_size(int byte_size) {
this->buffer_byte_size = byte_size;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_buffer_byte_size(fd, byte_size);
}
}
int Serial::get_buffer_byte_size() { return buffer_byte_size; }
std::string read_block_all(Serial_FD fd, int64_t chunkSize) {
std::string result;
// 使用 vector 分配一个缓冲区
std::vector<char> buffer(static_cast<size_t>(chunkSize));
while (true) {
int64_t bytesRead = read_data(fd, buffer.data(), chunkSize);
// std::cout << "bytesRead " << bytesRead;
if (bytesRead <= 0) {
// 出错或者没有读取到数据时退出循环
break;
}
// 累积读取的数据
result.append(buffer.data(), static_cast<size_t>(bytesRead));
// 如果本次读取的数据不足 chunkSize,通常认为已经没有更多数据
if (bytesRead <= chunkSize) {
break;
}
}
return result;
}
std::string read_all(Serial_FD fd) {
int size = get_available_bytes(fd);
if (size == 0)
return "";
auto ret = read_block_all(fd, 1024 * 4);
return ret;
}
bool noblock_error() {
#ifdef _WIN32
DWORD code = GetLastError();
return code == ERROR_IO_PENDING || code == ERROR_NO_SYSTEM_RESOURCES;
#elif defined(__linux__)
return errno == EAGAIN || errno == EWOULDBLOCK;
#else
return false;
#endif
}
int64_t write_all(Serial_FD fd, std::string_view data, int64_t chunkSize,
int64_t milliseconds, int64_t retry_count) {
int64_t total_written = 0;
int64_t data_size = static_cast<int64_t>(data.size());
while (total_written < data_size) {
int64_t this_chunk = std::min(chunkSize, data_size - total_written);
int64_t cur_written = 0;
int64_t retry_left = retry_count;
while (cur_written < this_chunk) {
int64_t to_write = this_chunk - cur_written;
int64_t written = serial::write(
fd, data.data() + total_written + cur_written, to_write);
if (written < 0) {
// 写入错误,返回 -1
LOG_ERROR(VAR_STR_2(fd, written))
return -1;
}
if (written > 0) {
cur_written += written;
retry_left = retry_count; // 成功写入一次后,重置 retry
} else if (written == -1) {
if (noblock_error()) {
// 非阻塞暂时无法写入
if (retry_count != -1) {
if (--retry_left <= 0) {
LOG_ERROR("Retry limit reached");
return total_written;
}
}
} else {
LOG_ERROR("write failed");
return -1;
}
} else if (written == 0) {
// 不应该发生,write 返回 0 通常表示未写任何数据
LOG_ERROR("write returned 0 unexpectedly");
return -1;
}
if (cur_written == this_chunk)
break;
if (milliseconds > 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
}
}
total_written += cur_written;
}
return total_written;
}
} // namespace Psc::serial