#include #include #include #include #include #include "MsgHandler.hpp" constexpr uint8_t STX = 0x02; constexpr uint8_t ETX = 0x03; constexpr uint8_t CR = 0x0D; constexpr uint8_t LF = 0x0A; MsgHandler::MsgHandler() : fd(-1) {} bool MsgHandler::OpenPort(const std::string& port, const std::string& baudrate) { return true; } void MsgHandler::ClosePort() { if (fd != -1) { close(fd); fd = -1; } } bool MsgHandler::SetDevice(const std::string& device) { this->device = device; return true; } bool MsgHandler::SetEmptyWeight(const int& empty_weight) { this->empty_weight = empty_weight; return true; } bool MsgHandler::SetJitterWeight(const int& jitter_weight) { this->jitter_weight = jitter_weight; return true; } int MsgHandler::SendDeviceMsg(const std::vector& data) { std::cout << "write to " << this->device << std::endl; for (int num : data) { std::cout << std::hex << std::setw(2) << std::setfill('0') << num << " "; } std::cout << std::endl; int bytesWritten = SendMsg(data); return bytesWritten; } int MsgHandler::RecvDeviceMsg(std::vector& data, int timeoutMs) { int bytesRead = RecvMsg(data, timeoutMs); if (bytesRead > 0) { // std::cout << "read from " << this->device << std::endl; // for (int num : data) // { // std::cout << std::hex << std::setw(2) << std::setfill('0') // << num << " "; // } // std::cout << std::endl; } return bytesRead; } int MsgHandler::SendMsg(const std::vector& data) { if (fd == -1) { perror("设备未打开"); return -1; } int bytesWritten = write(fd, data.data(), data.size()); if (bytesWritten < 0) { perror("发送数据失败"); } return bytesWritten; } int MsgHandler::RecvMsg(std::vector& data, int timeoutMs) { if (fd == -1) { perror("设备未打开\n"); return -1; } // 使用select实现超时 fd_set readfds; struct timeval tv; FD_ZERO(&readfds); FD_SET(fd, &readfds); tv.tv_sec = timeoutMs / 1000; tv.tv_usec = (timeoutMs % 1000) * 1000; int ret = select(fd + 1, &readfds, NULL, NULL, &tv); if (ret == -1) { perror("select错误"); return -1; } else if (ret == 0) { //无数据可读 return 0; } // 有数据可读 uint8_t bytes; if (ioctl(fd, FIONREAD, &bytes) < 0) { perror("ioctl FIONREAD失败"); return -1; } data.resize(bytes); int bytesRead = read(fd, data.data(), bytes); if (bytesRead < 0) { perror("读取数据失败"); return -1; } return bytesRead; } void MsgHandler::HandleDdsMsg(const std::map& msg) { return; } bool MsgHandler::get_frame(std::vector& frame, uint8_t frame_size, uint8_t start, uint8_t end) { bool frame_found = false; do { auto start_it = std::find(m_WeightData.begin(), m_WeightData.end(), start); if (start_it == m_WeightData.end()) { // 没有找到起始字节,清空缓冲区 m_WeightData.clear(); break; } // 移除起始字节前的无用数据 if (start_it != m_WeightData.begin()) { m_WeightData.erase(m_WeightData.begin(), start_it); } // 检查是否有足够的数据(至少一个完整帧) if (m_WeightData.size() >= 12) { // 检查结束字节 if (m_WeightData[frame_size - 1] == end) { // 提取完整帧 frame.clear(); frame.insert(frame.begin(), m_WeightData.begin(), m_WeightData.begin() + frame_size); // 从缓冲区移除已处理的数据 m_WeightData.erase(m_WeightData.begin(), m_WeightData.begin() + frame_size); frame_found = true; break; } else { // 结束字节不匹配,可能是数据错误或粘包 // 查找下一个起始字节 auto next_start = std::find(m_WeightData.begin() + 1, m_WeightData.end(), start); if (next_start != m_WeightData.end()) { // 移除到下一个起始字节之前的数据 m_WeightData.erase(m_WeightData.begin(), next_start); } else { // 没有找到下一个起始字节,清空缓冲区 m_WeightData.clear(); break; } } } else { // 数据不完整,等待更多数据 break; } } while (true); return frame_found; } bool MsgHandler::get_weight_1(std::string& weight, std::vector& frame) { // 1. 解析符号 char sign = '+'; if (frame[1] == 0x2D) { sign = '-'; } else if (frame[1] != 0x2B) { return false; } // 2. 解析称量数据(6位数字) std::string weightDigits; for (int i = 2; i <= 7; i++) { if (frame[i] < 0x30 || frame[i] > 0x39) { return false; } weightDigits += static_cast(frame[i]); } // 3. 解析小数点位置 if (frame[8] < 0x30 || frame[8] > 0x34) { return false; } int decimalPos = frame[8] - 0x30; // 4. 构建结果字符串 std::string weightStr; if (decimalPos == 0) { // 情况1:没有小数点,去除所有前导零,但保留至少一位数字 std::string integerPart = weightDigits; // 去除前导零 size_t firstNonZero = 0; while (firstNonZero < integerPart.length() && integerPart[firstNonZero] == '0') { firstNonZero++; } if (firstNonZero == integerPart.length()) { // 如果全部是零,保留一个零 weightStr = "0"; } else { weightStr = integerPart.substr(firstNonZero); } } else { // 情况2:有小数点 if (decimalPos > weightDigits.length()) { return false; } // 从右向左插入小数点 int insertPos = weightDigits.length() - decimalPos; // 分离整数部分和小数部分 std::string integerPart = weightDigits.substr(0, insertPos); std::string decimalPart = weightDigits.substr(insertPos, decimalPos); // 处理整数部分:去除前导零,但如果全为零则保留一个0 bool allZero = true; for (char c : integerPart) { if (c != '0') { allZero = false; break; } } if (allZero && !integerPart.empty()) { integerPart = "0"; } else { // 去除整数部分的前导零 size_t firstNonZero = 0; while (firstNonZero < integerPart.length() && integerPart[firstNonZero] == '0') { firstNonZero++; } if (firstNonZero > 0 && firstNonZero < integerPart.length()) { integerPart = integerPart.substr(firstNonZero); } } // 构建最终字符串,小数部分保留完整位数 weightStr = integerPart + "." + decimalPart; } // 5. 添加符号 weight.clear(); weight += sign; weight += weightStr; return true; } bool MsgHandler::get_weight_1(float& weight, std::vector& frame) { float raw_value; float divisors[] = {1.0f, 10.0f, 100.0f, 1000.0f, 10000.0f}; std::string weightDigits; for (int i = 2; i <= 7; i++) { if (frame[i] < 0x30 || frame[i] > 0x39) { return false; } weightDigits += static_cast(frame[i]); } int decimalPos = frame[8] - 0x30; if (decimalPos < 0) { decimalPos = 0; } raw_value = std::stof(weightDigits); weight = raw_value / divisors[decimalPos]; if (frame[1] == 0x2D) { weight = 0 - weight; } return true; } bool MsgHandler::get_weight_2(std::string& weight, std::vector& frame) { // 1. 解析符号 char sign = '+'; if (frame[2] & 0x02) { sign = '-'; } // 2. 解析称量数据(6位数字) std::string weightDigits; for (int i = 4; i <= 9; i++) { if ((frame[i] >= 0x30) && (frame[i] <= 0x39)) { weightDigits += static_cast(frame[i]); } else if (frame[i] == 0x20) { weightDigits += '0'; } } // 3. 解析小数点位置 int decimalPos = frame[1]&0x07 - 2; if (decimalPos < 0) { decimalPos = 0; } // 4. 构建结果字符串 std::string weightStr; if (decimalPos == 0) { // 情况1:没有小数点,去除所有前导零,但保留至少一位数字 std::string integerPart = weightDigits; // 去除前导零 size_t firstNonZero = 0; while (firstNonZero < integerPart.length() && integerPart[firstNonZero] == '0') { firstNonZero++; } if (firstNonZero == integerPart.length()) { // 如果全部是零,保留一个零 weightStr = "0"; } else { weightStr = integerPart.substr(firstNonZero); } } else { // 情况2:有小数点 if (decimalPos > weightDigits.length()) { return false; } // 从右向左插入小数点 int insertPos = weightDigits.length() - decimalPos; // 分离整数部分和小数部分 std::string integerPart = weightDigits.substr(0, insertPos); std::string decimalPart = weightDigits.substr(insertPos, decimalPos); // 处理整数部分:去除前导零,但如果全为零则保留一个0 bool allZero = true; for (char c : integerPart) { if (c != '0') { allZero = false; break; } } if (allZero && !integerPart.empty()) { integerPart = "0"; } else { // 去除整数部分的前导零 size_t firstNonZero = 0; while (firstNonZero < integerPart.length() && integerPart[firstNonZero] == '0') { firstNonZero++; } if (firstNonZero > 0 && firstNonZero < integerPart.length()) { integerPart = integerPart.substr(firstNonZero); } } // 构建最终字符串,小数部分保留完整位数 weightStr = integerPart + "." + decimalPart; } // 5. 添加符号 weight.clear(); weight += sign; weight += weightStr; std::cout << weight << std::endl; return true; } bool MsgHandler::get_weight_2(float& weight, std::vector& frame) { float raw_value; float divisors[] = {1.0f, 10.0f, 100.0f, 1000.0f, 10000.0f, 100000.0f}; std::string weightDigits; for (int i = 4; i <= 9; i++) { if ((frame[i] >= 0x30) && (frame[i] <= 0x39)) { weightDigits += static_cast(frame[i]); } else if (frame[i] == 0x20) { weightDigits += '0'; } } int decimalPos = frame[1]&0x07 - 2; if (decimalPos < 0) { decimalPos = 0; } raw_value = std::stof(weightDigits); weight = raw_value / divisors[decimalPos]; if (frame[2] & 0x02) { weight = 0 - weight; } return true; } template bool MsgHandler::HandleDeviceMsg(T& msg) { std::vector m_Data; std::vector frame; if (RecvDeviceMsg(m_Data, 100) > 0) { m_WeightData.insert(m_WeightData.end(), m_Data.begin(), m_Data.end()); } if (m_WeightData.empty() != true) { if (device == "Keli") { if (get_frame(frame, 12, STX, ETX) == true) { return get_weight_1(msg, frame); } } else if (device == "Toledo") { if (get_frame(frame, 17, STX, CR) == true) { return get_weight_2(msg, frame); } } } return false; } template bool MsgHandler::HandleDeviceMsg(std::string&); template bool MsgHandler::HandleDeviceMsg(float&);