#include "plugins/protocols/modbus_rtu/framer/ModbusRtuFramerPlugin.h" #include #include #include "plugins/protocols/modbus_rtu/framer/ModbusRtuFraming.h" #include "utils/logs/logging.h" namespace softbus::message_bus::pipeline::protocol::modbusrtu { namespace { class ModbusRtuFramerSession final : public softbus::core::plugin_system::IProtocolFramerSession { public: ModbusRtuFramerSession(std::shared_ptr pool, ModbusRtuFramerPluginConfig cfg, std::uint32_t endpointHash) : m_pool(std::move(pool)) , m_cfg(cfg) , m_endpointHash(endpointHash) { m_buf.resize(m_cfg.maxAdu); } void feedChunk(softbus::core::models::RawBusMessage& in, std::vector& out) override { if (!m_pool || !in.payload.valid()) { return; } const std::uint8_t* p = in.payload.bytes(); const std::size_t n = in.payload.length; if (!p || n == 0) { return; } m_lastRx = std::chrono::steady_clock::now(); if (m_cfg.interFrameTimeoutMs > 0 && m_len > 0) { const auto age = std::chrono::duration_cast(m_lastRx - m_lastActivity).count(); if (age >= m_cfg.interFrameTimeoutMs) { m_len = 0; } } m_lastActivity = m_lastRx; if (m_len + n > m_cfg.maxAdu) { LOG_WARNING() << "ModbusRtuFramerPlugin: overflow endpointHash=0x" << QString::number(m_endpointHash, 16); m_len = 0; return; } std::memcpy(m_buf.data() + m_len, p, n); m_len += n; while (m_len > 0) { auto pred = predictAduLength(m_buf.data(), m_len, m_cfg.maxAdu); if (!pred || m_len < *pred) { break; } if (!crcOk(m_buf.data(), *pred)) { if (m_len <= 1) { m_len = 0; break; } std::memmove(m_buf.data(), m_buf.data() + 1, m_len - 1); --m_len; continue; } auto blk = m_pool->allocate(*pred); if (!blk || !blk->data || blk->capacity < *pred) { return; } std::memcpy(blk->data, m_buf.data(), *pred); blk->size = *pred; softbus::core::models::RawBusMessage framed; framed.deviceId = in.deviceId; framed.endpointHash = in.endpointHash; framed.protocol = softbus::core::models::ProtocolType::MODBUS_RTU; framed.logicalAddress = in.logicalAddress; framed.routingKey = in.routingKey; framed.header = in.header; framed.timestampMs = in.timestampMs; framed.traceId = in.traceId; framed.direction = in.direction; framed.payload.block = std::move(blk); framed.payload.offset = 0; framed.payload.length = *pred; if (*pred >= 2 && framed.payload.block && framed.payload.block->data) { framed.header.modbus.slaveId = framed.payload.block->data[0]; framed.header.modbus.functionCode = framed.payload.block->data[1]; framed.logicalAddress = framed.header.modbus.slaveId; } out.push_back(std::move(framed)); const std::size_t rest = m_len - *pred; if (rest > 0) { std::memmove(m_buf.data(), m_buf.data() + *pred, rest); } m_len = rest; } in.payload = {}; } void reset() override { m_len = 0; } void shutdown() override { m_len = 0; } private: std::shared_ptr m_pool; ModbusRtuFramerPluginConfig m_cfg; std::uint32_t m_endpointHash{0}; std::vector m_buf; std::size_t m_len{0}; std::chrono::steady_clock::time_point m_lastRx{std::chrono::steady_clock::now()}; std::chrono::steady_clock::time_point m_lastActivity{std::chrono::steady_clock::now()}; }; } // namespace ModbusRtuFramerPlugin::ModbusRtuFramerPlugin(std::shared_ptr pool, ModbusRtuFramerPluginConfig cfg) : m_pool(std::move(pool)) , m_cfg(cfg) { } QString ModbusRtuFramerPlugin::pluginId() const { return QStringLiteral("modbus_rtu_framer"); } softbus::core::models::ProtocolType ModbusRtuFramerPlugin::protocolType() const { return softbus::core::models::ProtocolType::MODBUS_RTU; } void ModbusRtuFramerPlugin::bindMemoryPool(std::shared_ptr pool) { m_pool = std::move(pool); } std::unique_ptr ModbusRtuFramerPlugin::createFramerSession(std::uint32_t endpointHash, const QJsonObject& params) { if (!m_pool) { return {}; } ModbusRtuFramerPluginConfig cfg = m_cfg; if (params.contains(QStringLiteral("modbusRtuMaxFrameBytes"))) { cfg.maxAdu = static_cast( std::max(8, params.value(QStringLiteral("modbusRtuMaxFrameBytes")).toInt(static_cast(cfg.maxAdu)))); } if (params.contains(QStringLiteral("modbusRtuInterFrameTimeoutMs"))) { cfg.interFrameTimeoutMs = params.value(QStringLiteral("modbusRtuInterFrameTimeoutMs")).toInt(cfg.interFrameTimeoutMs); } return std::make_unique(m_pool, cfg, endpointHash); } std::shared_ptr makeModbusRtuFramerPlugin( std::shared_ptr pool, ModbusRtuFramerPluginConfig cfg) { return std::make_shared(std::move(pool), cfg); } softbus::core::plugin_system::IProtocolFramerPlugin* createModbusRtuFramerPluginRaw() { return new ModbusRtuFramerPlugin(nullptr, {}); } } // namespace softbus::message_bus::pipeline::protocol::modbusrtu