Files
softbus_daemon/plugins/protocols/modbus_rtu/framer/ModbusRtuFramerPlugin.cpp
flower_linux 7459cc0f36 context bind
2026-04-22 17:25:51 +08:00

177 lines
6.1 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);
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<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