#include "LinkManager.h" #include "../protocol/Frame.h" #include "MOOS/libMOOS/Utils/MOOSUtilityFunctions.h" #include "loguru.hpp" namespace ccu { LinkManager::LinkManager(const std::string& linkName, long localPort) : m_linkName(linkName), m_localPort(localPort) {} LinkManager::~LinkManager() { stop(); } bool LinkManager::start() { if (m_running) return true; if (!m_endpoint.init(m_localPort)) { LOG_F(ERROR, "[%s] bind failed on port %ld", m_linkName.c_str(), m_localPort); return false; } m_running = true; m_rxThread = std::thread([this]() { rxThreadFunc(); }); LOG_F(INFO, "[%s] listening on local port %ld", m_linkName.c_str(), m_localPort); return true; } void LinkManager::stop() { if (!m_running) return; m_running = false; if (m_rxThread.joinable()) m_rxThread.join(); } bool LinkManager::sendMessage(uint16_t id, const void* value) { return sendMessageTo(id, value, defaultRemoteHost(), defaultRemotePort()); } bool LinkManager::sendMessageTo(uint16_t id, const void* value, const std::string& host, long port) { if (host.empty() || port <= 0) return false; Message* msg = m_registry.find(id); if (!msg) { LOG_F(ERROR, "[%s] unknown message id 0x%04X", m_linkName.c_str(), id); return false; } std::vector frame = msg->encode(value); if (!m_endpoint.sendTo(host, port, frame)) { LOG_F(ERROR, "[%s] send msg 0x%04X to %s:%ld failed", m_linkName.c_str(), id, host.c_str(), port); return false; } ++m_txCount; if (m_logSink) m_logSink->onRawFrame(1, id, m_linkName, frame, true); if (m_onRawFrame) m_onRawFrame(1, frame, true); return true; } bool LinkManager::handleIncoming(const std::vector& frame) { if (frame.size() < FRAME_HEADER_LEN) return false; uint16_t id = 0; if (!Frame::parseId(frame, id)) { LOG_F(WARNING, "[%s] bad frame header", m_linkName.c_str()); ++m_errorCount; return false; } Message* msg = m_registry.find(id); if (!msg) { LOG_F(WARNING, "[%s] unknown msg id 0x%04X, len=%zu", m_linkName.c_str(), id, frame.size()); ++m_errorCount; return false; } bool checksumOk = msg->checksum().verify(frame); ++m_rxCount; m_lastRxTime = MOOSTime(false); // 原始帧落库 + 回调 if (m_logSink) m_logSink->onRawFrame(0, id, m_linkName, frame, checksumOk); if (m_onRawFrame) m_onRawFrame(0, frame, checksumOk); if (!checksumOk) { LOG_F(WARNING, "[%s] checksum error msg 0x%04X", m_linkName.c_str(), id); ++m_errorCount; return false; } // 解码交给上层(CCU 层知道具体消息类型) if (m_onMessage) m_onMessage(msg, frame); return true; } void LinkManager::rxThreadFunc() { uint8_t buf[2048]; while (m_running) { int n = m_endpoint.receive(buf, sizeof(buf)); if (n > 0) { std::vector frame(buf, buf + n); handleIncoming(frame); } else { // 无数据,短暂休眠避免忙等 std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } } } // namespace ccu