Files
softbus_daemon/plugins/protocols/modbus_rtu/framer/ModbusRtuFramerPlugin.cpp

170 lines
5.5 KiB
C++
Raw Normal View History

2026-04-10 10:52:10 +08:00
#include "plugins/protocols/modbus_rtu/framer/ModbusRtuFramerPlugin.h"
2026-04-07 14:20:04 +08:00
#include <algorithm>
#include <cstring>
2026-04-10 10:52:10 +08:00
#include "plugins/protocols/modbus_rtu/framer/ModbusRtuFraming.h"
2026-04-07 14:20:04 +08:00
#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,
QString endpoint)
: m_pool(std::move(pool))
, m_cfg(cfg)
, m_endpoint(std::move(endpoint))
{
m_buf.resize(m_cfg.maxAdu);
}
2026-04-15 11:16:27 +08:00
void feedChunk(softbus::core::models::RawBusMessage& in,
std::vector<softbus::core::models::RawBusMessage>& out) override
2026-04-07 14:20:04 +08:00
{
if (!m_pool || !in.payload.valid()) {
return;
}
const std::uint8_t* p = in.payload.bytes();
const std::size_t n = in.payloadSize ? in.payloadSize : 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 endpoint=" << m_endpoint;
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;
2026-04-15 11:16:27 +08:00
softbus::core::models::RawBusMessage framed;
2026-04-07 14:20:04 +08:00
framed.deviceId = in.deviceId;
framed.stableKey = in.stableKey;
framed.endpoint = in.endpoint;
framed.timestamp = in.timestamp;
framed.protocolHint = in.protocolHint;
framed.traceId = in.traceId;
framed.direction = in.direction;
framed.payload.block = std::move(blk);
framed.payload.offset = 0;
framed.payload.length = *pred;
framed.payloadSize = *pred;
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 = {};
in.payloadSize = 0;
}
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;
QString m_endpoint;
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");
}
bool ModbusRtuFramerPlugin::supports(const QString& protocolHint) const
{
return isModbusRtuHint(protocolHint);
}
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(const QString& endpoint, 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, endpoint);
}
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