#include "Serial.h" #include "Core/Statistics/Frequency_Limit.h" #include "Serial_p.h" #include #include #include 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 buffer(static_cast(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(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(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