Files
softbus_daemon/plugins/protocols/modbus_rtu/framer/ModbusRtuFramerPlugin.cpp
flower_linux fcafa81db1 edge
2026-05-19 16:42:01 +08:00

178 lines
6.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "plugins/protocols/modbus_rtu/framer/ModbusRtuFramerPlugin.h"
#include <algorithm>
#include <cstring>
#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<softbus::core::memory::MemoryPool> 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<softbus::core::models::RawBusMessage>& 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<std::chrono::milliseconds>(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) << "bufLen=" << m_len << "chunk=" << n;
m_len = 0;
in.payload = {};
return;
}
std::memcpy(m_buf.data() + m_len, p, n);
m_len += n;
in.payload = {};
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) {
LOG_WARNING() << "ModbusRtuFramerPlugin: pool allocate failed endpointHash=0x"
<< QString::number(m_endpointHash, 16) << "aduLen=" << *pred << "bufLen=" << m_len;
break;
}
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;
}
}
void reset() override { m_len = 0; }
void shutdown() override { m_len = 0; }
private:
std::shared_ptr<softbus::core::memory::MemoryPool> m_pool;
ModbusRtuFramerPluginConfig m_cfg;
std::uint32_t m_endpointHash{0};
std::vector<std::uint8_t> 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<softbus::core::memory::MemoryPool> 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<softbus::core::memory::MemoryPool> pool)
{
m_pool = std::move(pool);
}
std::unique_ptr<softbus::core::plugin_system::IProtocolFramerSession>
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::size_t>(
std::max(8, params.value(QStringLiteral("modbusRtuMaxFrameBytes")).toInt(static_cast<int>(cfg.maxAdu))));
}
if (params.contains(QStringLiteral("modbusRtuInterFrameTimeoutMs"))) {
cfg.interFrameTimeoutMs = params.value(QStringLiteral("modbusRtuInterFrameTimeoutMs")).toInt(cfg.interFrameTimeoutMs);
}
return std::make_unique<ModbusRtuFramerSession>(m_pool, cfg, endpointHash);
}
std::shared_ptr<softbus::core::plugin_system::IProtocolFramerPlugin> makeModbusRtuFramerPlugin(
std::shared_ptr<softbus::core::memory::MemoryPool> pool, ModbusRtuFramerPluginConfig cfg)
{
return std::make_shared<ModbusRtuFramerPlugin>(std::move(pool), cfg);
}
softbus::core::plugin_system::IProtocolFramerPlugin* createModbusRtuFramerPluginRaw()
{
return new ModbusRtuFramerPlugin(nullptr, {});
}
} // namespace softbus::message_bus::pipeline::protocol::modbusrtu