modbus rtu 1.1 plugins
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
# Runtime-loadable Modbus RTU parser + framer plugin
|
||||
add_library(modbus_rtu SHARED
|
||||
plugin_stub.cpp
|
||||
../modbusrtu/parser/ModbusRtuProtocolPlugin.cpp
|
||||
../modbusrtu/codec/ModbusRtuCodec.cpp
|
||||
../modbusrtu/framer/ModbusRtuFramerPlugin.cpp
|
||||
../modbusrtu/framer/ModbusRtuFraming.cpp
|
||||
parser/ModbusRtuProtocolPlugin.cpp
|
||||
mapper/ModbusRtuProtocolMapperPlugin.cpp
|
||||
codec/ModbusRtuCodec.cpp
|
||||
framer/ModbusRtuFramerPlugin.cpp
|
||||
framer/ModbusRtuFraming.cpp
|
||||
)
|
||||
target_include_directories(modbus_rtu PRIVATE
|
||||
${CMAKE_SOURCE_DIR}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Modbus RTU 协议模块(`modbusrtu`)
|
||||
# Modbus RTU 协议模块(`modbus_rtu`)
|
||||
|
||||
本目录实现 **Modbus RTU** 的成帧、编解码与解析插件,供守护进程静态编译与 `plugins/protocols/modbus_rtu` 动态库(`.so`)共用同一套源码。
|
||||
|
||||
@@ -26,7 +26,7 @@ parser (依赖 codec、types;不反向依赖 framer 插件类)
|
||||
## 与动态库的关系
|
||||
|
||||
- 动态库入口:`plugins/protocols/modbus_rtu/plugin_stub.cpp`,导出 `softbus_create_protocol_plugin` / `softbus_create_framer_plugin` 等符号。
|
||||
- 主工程 `CMakeLists.txt` 同样列出本目录下源文件,用于无 `.so` 时的内置链接;路径与 include 均以 `plugins/protocols/modbusrtu/...` 为准。
|
||||
- 主工程 `CMakeLists.txt` 同样列出本目录下源文件,用于无 `.so` 时的内置链接;路径与 include 均以 `plugins/protocols/modbus_rtu/...` 为准。
|
||||
|
||||
## 配置提示
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "plugins/protocols/modbusrtu/codec/ModbusRtuCodec.h"
|
||||
#include "plugins/protocols/modbus_rtu/codec/ModbusRtuCodec.h"
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
#include "plugins/protocols/modbusrtu/framer/ModbusRtuFraming.h"
|
||||
#include "plugins/protocols/modbus_rtu/framer/ModbusRtuFraming.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline::protocol
|
||||
{
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
#include "plugins/protocols/modbusrtu/types/ModbusRtuPdu.h"
|
||||
#include "plugins/protocols/modbus_rtu/types/ModbusRtuPdu.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline
|
||||
{
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "plugins/protocols/modbusrtu/framer/ModbusRtuFramerPlugin.h"
|
||||
#include "plugins/protocols/modbus_rtu/framer/ModbusRtuFramerPlugin.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include "plugins/protocols/modbusrtu/framer/ModbusRtuFraming.h"
|
||||
#include "plugins/protocols/modbus_rtu/framer/ModbusRtuFraming.h"
|
||||
#include "utils/logs/logging.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline::protocol::modbusrtu
|
||||
@@ -72,7 +72,6 @@ public:
|
||||
|
||||
auto blk = m_pool->allocate(*pred);
|
||||
if (!blk || !blk->data || blk->capacity < *pred) {
|
||||
in.framerError = QStringLiteral("pool_exhausted");
|
||||
return;
|
||||
}
|
||||
std::memcpy(blk->data, m_buf.data(), *pred);
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "plugins/protocols/modbusrtu/framer/ModbusRtuFraming.h"
|
||||
#include "plugins/protocols/modbus_rtu/framer/ModbusRtuFraming.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline::protocol::modbusrtu
|
||||
{
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "plugins/protocols/modbus_rtu/mapper/ModbusRtuProtocolMapperPlugin.h"
|
||||
|
||||
#include "plugins/protocols/modbus_rtu/framer/ModbusRtuFraming.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline::protocol::modbusrtu
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class ModbusRtuMapperSession final : public softbus::core::plugin_system::IProtocolMapperSession
|
||||
{
|
||||
public:
|
||||
std::vector<softbus::core::models::DOMMessage> map(
|
||||
const softbus::message_bus::pipeline::PipelineContext& rawContext,
|
||||
const softbus::message_bus::pipeline::protocol::ProtocolEnvelope& envelope) override
|
||||
{
|
||||
std::vector<softbus::core::models::DOMMessage> out;
|
||||
if (envelope.family != softbus::message_bus::pipeline::protocol::ProtocolFamily::ModbusRtu) {
|
||||
return out;
|
||||
}
|
||||
const auto* pdu = std::get_if<softbus::message_bus::pipeline::protocol::ModbusRtuPdu>(&envelope.pdu);
|
||||
if (!pdu) {
|
||||
return out;
|
||||
}
|
||||
|
||||
if (const auto* resp =
|
||||
std::get_if<softbus::message_bus::pipeline::protocol::ReadHoldingRegistersResponse>(pdu)) {
|
||||
out.reserve(static_cast<std::size_t>(resp->registers.size()));
|
||||
for (int i = 0; i < resp->registers.size(); ++i) {
|
||||
softbus::core::models::DOMMessage msg;
|
||||
msg.messageId = QStringLiteral("%1.reg.%2")
|
||||
.arg(rawContext.stableKey.isEmpty() ? QString::number(rawContext.deviceId)
|
||||
: rawContext.stableKey)
|
||||
.arg(i);
|
||||
msg.timestamp = rawContext.timestamp.toMSecsSinceEpoch();
|
||||
msg.value = static_cast<std::uint32_t>(resp->registers[static_cast<qsizetype>(i)]);
|
||||
msg.quality = softbus::core::models::DataQuality::GOOD;
|
||||
msg.attributes.insert(QStringLiteral("sourceEndpoint"), rawContext.endpoint);
|
||||
out.push_back(std::move(msg));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
if (const auto* req =
|
||||
std::get_if<softbus::message_bus::pipeline::protocol::ReadHoldingRegistersRequest>(pdu)) {
|
||||
softbus::core::models::DOMMessage msg;
|
||||
msg.messageId = QStringLiteral("%1.req.read_holding")
|
||||
.arg(rawContext.stableKey.isEmpty() ? QString::number(rawContext.deviceId)
|
||||
: rawContext.stableKey);
|
||||
msg.timestamp = rawContext.timestamp.toMSecsSinceEpoch();
|
||||
msg.value = static_cast<std::uint32_t>(req->quantity);
|
||||
msg.quality = softbus::core::models::DataQuality::GOOD;
|
||||
msg.attributes.insert(QStringLiteral("sourceEndpoint"), rawContext.endpoint);
|
||||
msg.attributes.insert(QStringLiteral("frameType"), QStringLiteral("request"));
|
||||
msg.attributes.insert(QStringLiteral("startAddress"), static_cast<int>(req->startAddress));
|
||||
msg.attributes.insert(QStringLiteral("quantity"), static_cast<int>(req->quantity));
|
||||
out.push_back(std::move(msg));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void reset() override {}
|
||||
};
|
||||
|
||||
class ModbusRtuProtocolMapperPlugin final : public softbus::core::plugin_system::IProtocolMapperPlugin
|
||||
{
|
||||
public:
|
||||
QString pluginId() const override { return QStringLiteral("modbus_rtu_mapper"); }
|
||||
bool supports(const QString& protocolHint) const override
|
||||
{
|
||||
return isModbusRtuHint(protocolHint);
|
||||
}
|
||||
std::unique_ptr<softbus::core::plugin_system::IProtocolMapperSession> createMapperSession() override
|
||||
{
|
||||
return std::make_unique<ModbusRtuMapperSession>();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
std::shared_ptr<softbus::core::plugin_system::IProtocolMapperPlugin> makeModbusRtuProtocolMapperPlugin()
|
||||
{
|
||||
return std::make_shared<ModbusRtuProtocolMapperPlugin>();
|
||||
}
|
||||
|
||||
softbus::core::plugin_system::IProtocolMapperPlugin* createModbusRtuProtocolMapperPluginRaw()
|
||||
{
|
||||
return new ModbusRtuProtocolMapperPlugin();
|
||||
}
|
||||
|
||||
} // namespace softbus::message_bus::pipeline::protocol::modbusrtu
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/plugin_system/IProtocolMapperPlugin.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline::protocol::modbusrtu
|
||||
{
|
||||
|
||||
std::shared_ptr<softbus::core::plugin_system::IProtocolMapperPlugin> makeModbusRtuProtocolMapperPlugin();
|
||||
softbus::core::plugin_system::IProtocolMapperPlugin* createModbusRtuProtocolMapperPluginRaw();
|
||||
|
||||
} // namespace softbus::message_bus::pipeline::protocol::modbusrtu
|
||||
|
||||
107
plugins/protocols/modbus_rtu/parser/ModbusRtuProtocolPlugin.cpp
Normal file
107
plugins/protocols/modbus_rtu/parser/ModbusRtuProtocolPlugin.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "plugins/protocols/modbus_rtu/parser/ModbusRtuProtocolPlugin.h"
|
||||
|
||||
#include "core/plugin_system/IProtocolPlugin.h"
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
#include "message_bus/pipeline/protocol/ProtocolEnvelope.h"
|
||||
#include "plugins/protocols/modbus_rtu/codec/ModbusRtuCodec.h"
|
||||
#include "plugins/protocols/modbus_rtu/framer/ModbusRtuFraming.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
namespace softbus::core::plugin_system
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using softbus::message_bus::pipeline::protocol::ModbusExceptionPdu;
|
||||
using softbus::message_bus::pipeline::protocol::ModbusRtuPdu;
|
||||
using softbus::message_bus::pipeline::protocol::ModbusRtuUnsupportedPdu;
|
||||
using softbus::message_bus::pipeline::protocol::ProtocolFamily;
|
||||
using softbus::message_bus::pipeline::protocol::ReadCoilsRequest;
|
||||
using softbus::message_bus::pipeline::protocol::ReadCoilsResponse;
|
||||
using softbus::message_bus::pipeline::protocol::ReadDiscreteInputsRequest;
|
||||
using softbus::message_bus::pipeline::protocol::ReadDiscreteInputsResponse;
|
||||
using softbus::message_bus::pipeline::protocol::ReadHoldingRegistersRequest;
|
||||
using softbus::message_bus::pipeline::protocol::ReadHoldingRegistersResponse;
|
||||
using softbus::message_bus::pipeline::protocol::ReadInputRegistersRequest;
|
||||
using softbus::message_bus::pipeline::protocol::ReadInputRegistersResponse;
|
||||
using softbus::message_bus::pipeline::protocol::WriteSingleCoilRequest;
|
||||
using softbus::message_bus::pipeline::protocol::WriteSingleCoilResponse;
|
||||
using softbus::message_bus::pipeline::protocol::WriteSingleRegisterRequest;
|
||||
using softbus::message_bus::pipeline::protocol::WriteSingleRegisterResponse;
|
||||
using softbus::message_bus::pipeline::protocol::WriteMultipleCoilsRequest;
|
||||
using softbus::message_bus::pipeline::protocol::WriteMultipleCoilsResponse;
|
||||
using softbus::message_bus::pipeline::protocol::WriteMultipleRegistersRequest;
|
||||
using softbus::message_bus::pipeline::protocol::WriteMultipleRegistersResponse;
|
||||
using softbus::message_bus::pipeline::protocol::decodeModbusRtu;
|
||||
|
||||
template <class... Ts>
|
||||
struct overloaded : Ts...
|
||||
{
|
||||
using Ts::operator()...;
|
||||
};
|
||||
template <class... Ts>
|
||||
overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
class ModbusRtuSession final : public IProtocolSession
|
||||
{
|
||||
public:
|
||||
bool parse(const softbus::message_bus::pipeline::PipelineContext& ctx,
|
||||
softbus::message_bus::pipeline::protocol::ProtocolEnvelope& out) override
|
||||
{
|
||||
using softbus::message_bus::pipeline::FrameKind;
|
||||
if (ctx.frameKind != FrameKind::CompleteFrame || !ctx.payload.valid()) {
|
||||
return false;
|
||||
}
|
||||
const std::size_t n = ctx.payloadSize ? ctx.payloadSize : ctx.payload.length;
|
||||
const std::uint8_t* p = ctx.payload.bytes();
|
||||
if (!p || n < 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ModbusRtuPdu pdu;
|
||||
if (!decodeModbusRtu(ctx.direction, p, n, pdu, nullptr)) {
|
||||
out.family = ProtocolFamily::None;
|
||||
out.pdu = {};
|
||||
return false;
|
||||
}
|
||||
out.family = ProtocolFamily::ModbusRtu;
|
||||
out.pdu = pdu;
|
||||
return true;
|
||||
}
|
||||
|
||||
void reset() override {}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
class ModbusRtuProtocolPlugin final : public IProtocolPlugin
|
||||
{
|
||||
public:
|
||||
QString pluginId() const override { return QStringLiteral("modbus_rtu"); }
|
||||
|
||||
bool supports(const QString& protocolHint) const override
|
||||
{
|
||||
return softbus::message_bus::pipeline::protocol::modbusrtu::isModbusRtuHint(protocolHint);
|
||||
}
|
||||
|
||||
std::unique_ptr<IProtocolSession> createSession() override
|
||||
{
|
||||
return std::make_unique<ModbusRtuSession>();
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<IProtocolPlugin> makeModbusRtuProtocolPlugin()
|
||||
{
|
||||
return std::make_shared<ModbusRtuProtocolPlugin>();
|
||||
}
|
||||
|
||||
IProtocolPlugin* createModbusRtuProtocolPluginRaw()
|
||||
{
|
||||
return new ModbusRtuProtocolPlugin();
|
||||
}
|
||||
|
||||
} // namespace softbus::core::plugin_system
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
// Modbus RTU 协议解析器插件
|
||||
#include <memory>
|
||||
|
||||
#include "core/plugin_system/IProtocolPlugin.h"
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "plugins/protocols/modbusrtu/framer/ModbusRtuFramerPlugin.h"
|
||||
#include "plugins/protocols/modbusrtu/parser/ModbusRtuProtocolPlugin.h"
|
||||
#include "plugins/protocols/modbus_rtu/framer/ModbusRtuFramerPlugin.h"
|
||||
#include "plugins/protocols/modbus_rtu/mapper/ModbusRtuProtocolMapperPlugin.h"
|
||||
#include "plugins/protocols/modbus_rtu/parser/ModbusRtuProtocolPlugin.h"
|
||||
|
||||
extern "C" int softbus_plugin_abi_version()
|
||||
{
|
||||
@@ -15,3 +16,8 @@ extern "C" softbus::core::plugin_system::IProtocolFramerPlugin* softbus_create_f
|
||||
{
|
||||
return softbus::message_bus::pipeline::protocol::modbusrtu::createModbusRtuFramerPluginRaw();
|
||||
}
|
||||
|
||||
extern "C" softbus::core::plugin_system::IProtocolMapperPlugin* softbus_create_mapper_plugin()
|
||||
{
|
||||
return softbus::message_bus::pipeline::protocol::modbusrtu::createModbusRtuProtocolMapperPluginRaw();
|
||||
}
|
||||
|
||||
@@ -1,249 +0,0 @@
|
||||
#include "plugins/protocols/modbusrtu/parser/ModbusRtuProtocolPlugin.h"
|
||||
|
||||
#include "core/plugin_system/IProtocolPlugin.h"
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
#include "message_bus/pipeline/protocol/ProtocolEnvelope.h"
|
||||
#include "plugins/protocols/modbusrtu/codec/ModbusRtuCodec.h"
|
||||
#include "plugins/protocols/modbusrtu/framer/ModbusRtuFraming.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
namespace softbus::core::plugin_system
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using softbus::message_bus::pipeline::protocol::ModbusExceptionPdu;
|
||||
using softbus::message_bus::pipeline::protocol::ModbusRtuPdu;
|
||||
using softbus::message_bus::pipeline::protocol::ModbusRtuUnsupportedPdu;
|
||||
using softbus::message_bus::pipeline::protocol::ProtocolFamily;
|
||||
using softbus::message_bus::pipeline::protocol::ReadCoilsRequest;
|
||||
using softbus::message_bus::pipeline::protocol::ReadCoilsResponse;
|
||||
using softbus::message_bus::pipeline::protocol::ReadDiscreteInputsRequest;
|
||||
using softbus::message_bus::pipeline::protocol::ReadDiscreteInputsResponse;
|
||||
using softbus::message_bus::pipeline::protocol::ReadHoldingRegistersRequest;
|
||||
using softbus::message_bus::pipeline::protocol::ReadHoldingRegistersResponse;
|
||||
using softbus::message_bus::pipeline::protocol::ReadInputRegistersRequest;
|
||||
using softbus::message_bus::pipeline::protocol::ReadInputRegistersResponse;
|
||||
using softbus::message_bus::pipeline::protocol::WriteSingleCoilRequest;
|
||||
using softbus::message_bus::pipeline::protocol::WriteSingleCoilResponse;
|
||||
using softbus::message_bus::pipeline::protocol::WriteSingleRegisterRequest;
|
||||
using softbus::message_bus::pipeline::protocol::WriteSingleRegisterResponse;
|
||||
using softbus::message_bus::pipeline::protocol::WriteMultipleCoilsRequest;
|
||||
using softbus::message_bus::pipeline::protocol::WriteMultipleCoilsResponse;
|
||||
using softbus::message_bus::pipeline::protocol::WriteMultipleRegistersRequest;
|
||||
using softbus::message_bus::pipeline::protocol::WriteMultipleRegistersResponse;
|
||||
using softbus::message_bus::pipeline::protocol::decodeModbusRtu;
|
||||
|
||||
template <class... Ts>
|
||||
struct overloaded : Ts...
|
||||
{
|
||||
using Ts::operator()...;
|
||||
};
|
||||
template <class... Ts>
|
||||
overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
void syncLegacyJson(const ModbusRtuPdu& pdu, QJsonObject& o)
|
||||
{
|
||||
o = QJsonObject();
|
||||
std::visit(
|
||||
overloaded{
|
||||
[&](const ModbusExceptionPdu& e) {
|
||||
o.insert(QStringLiteral("unitId"), e.unitId);
|
||||
o.insert(QStringLiteral("function"), e.function);
|
||||
o.insert(QStringLiteral("exceptionCode"), e.exceptionCode);
|
||||
o.insert(QStringLiteral("exception"), true);
|
||||
},
|
||||
[&](const ReadHoldingRegistersResponse& r) {
|
||||
QJsonArray regs;
|
||||
for (std::uint16_t v : r.registers) {
|
||||
regs.append(static_cast<int>(v));
|
||||
}
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 3);
|
||||
o.insert(QStringLiteral("byteCount"), r.registers.size() * 2);
|
||||
o.insert(QStringLiteral("registers"), regs);
|
||||
},
|
||||
[&](const ReadHoldingRegistersRequest& r) {
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 3);
|
||||
o.insert(QStringLiteral("startAddress"), r.startAddress);
|
||||
o.insert(QStringLiteral("quantity"), r.quantity);
|
||||
},
|
||||
[&](const ReadCoilsRequest& r) {
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 1);
|
||||
o.insert(QStringLiteral("startAddress"), r.startAddress);
|
||||
o.insert(QStringLiteral("quantity"), r.quantity);
|
||||
},
|
||||
[&](const ReadDiscreteInputsRequest& r) {
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 2);
|
||||
o.insert(QStringLiteral("startAddress"), r.startAddress);
|
||||
o.insert(QStringLiteral("quantity"), r.quantity);
|
||||
},
|
||||
[&](const ReadInputRegistersRequest& r) {
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 4);
|
||||
o.insert(QStringLiteral("startAddress"), r.startAddress);
|
||||
o.insert(QStringLiteral("quantity"), r.quantity);
|
||||
},
|
||||
[&](const ReadCoilsResponse& r) {
|
||||
QJsonArray bits;
|
||||
for (std::uint8_t b : r.coils) {
|
||||
bits.append(static_cast<int>(b));
|
||||
}
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 1);
|
||||
o.insert(QStringLiteral("byteCount"), r.coils.size());
|
||||
o.insert(QStringLiteral("coils"), bits);
|
||||
},
|
||||
[&](const ReadDiscreteInputsResponse& r) {
|
||||
QJsonArray bits;
|
||||
for (std::uint8_t b : r.discreteInputs) {
|
||||
bits.append(static_cast<int>(b));
|
||||
}
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 2);
|
||||
o.insert(QStringLiteral("byteCount"), r.discreteInputs.size());
|
||||
o.insert(QStringLiteral("discreteInputs"), bits);
|
||||
},
|
||||
[&](const ReadInputRegistersResponse& r) {
|
||||
QJsonArray regs;
|
||||
for (std::uint16_t v : r.inputRegisters) {
|
||||
regs.append(static_cast<int>(v));
|
||||
}
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 4);
|
||||
o.insert(QStringLiteral("byteCount"), r.inputRegisters.size() * 2);
|
||||
o.insert(QStringLiteral("inputRegisters"), regs);
|
||||
},
|
||||
[&](const WriteSingleCoilRequest& r) {
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 5);
|
||||
o.insert(QStringLiteral("address"), r.address);
|
||||
o.insert(QStringLiteral("value"), r.value);
|
||||
},
|
||||
[&](const WriteSingleCoilResponse& r) {
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 5);
|
||||
o.insert(QStringLiteral("address"), r.address);
|
||||
o.insert(QStringLiteral("value"), r.value);
|
||||
},
|
||||
[&](const WriteSingleRegisterRequest& r) {
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 6);
|
||||
o.insert(QStringLiteral("address"), r.address);
|
||||
o.insert(QStringLiteral("value"), r.value);
|
||||
},
|
||||
[&](const WriteSingleRegisterResponse& r) {
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 6);
|
||||
o.insert(QStringLiteral("address"), r.address);
|
||||
o.insert(QStringLiteral("value"), r.value);
|
||||
},
|
||||
[&](const WriteMultipleCoilsRequest& r) {
|
||||
QJsonArray vals;
|
||||
for (std::uint8_t b : r.values) {
|
||||
vals.append(static_cast<int>(b));
|
||||
}
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 15);
|
||||
o.insert(QStringLiteral("startAddress"), r.startAddress);
|
||||
o.insert(QStringLiteral("quantity"), r.quantity);
|
||||
o.insert(QStringLiteral("values"), vals);
|
||||
},
|
||||
[&](const WriteMultipleCoilsResponse& r) {
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 15);
|
||||
o.insert(QStringLiteral("startAddress"), r.startAddress);
|
||||
o.insert(QStringLiteral("quantity"), r.quantity);
|
||||
},
|
||||
[&](const WriteMultipleRegistersRequest& r) {
|
||||
QJsonArray vals;
|
||||
for (std::uint16_t v : r.values) {
|
||||
vals.append(static_cast<int>(v));
|
||||
}
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 16);
|
||||
o.insert(QStringLiteral("startAddress"), r.startAddress);
|
||||
o.insert(QStringLiteral("quantity"), r.quantity);
|
||||
o.insert(QStringLiteral("values"), vals);
|
||||
},
|
||||
[&](const WriteMultipleRegistersResponse& r) {
|
||||
o.insert(QStringLiteral("unitId"), r.unitId);
|
||||
o.insert(QStringLiteral("function"), 16);
|
||||
o.insert(QStringLiteral("startAddress"), r.startAddress);
|
||||
o.insert(QStringLiteral("quantity"), r.quantity);
|
||||
},
|
||||
[&](const ModbusRtuUnsupportedPdu&) {},
|
||||
[&](const auto&) {}},
|
||||
pdu);
|
||||
}
|
||||
|
||||
class ModbusRtuSession final : public IProtocolSession
|
||||
{
|
||||
public:
|
||||
bool feed(softbus::message_bus::pipeline::PipelineContext& ctx) override
|
||||
{
|
||||
using softbus::message_bus::pipeline::FrameKind;
|
||||
if (ctx.frameKind != FrameKind::CompleteFrame || !ctx.payload.valid()) {
|
||||
return false;
|
||||
}
|
||||
const std::size_t n = ctx.payloadSize ? ctx.payloadSize : ctx.payload.length;
|
||||
const std::uint8_t* p = ctx.payload.bytes();
|
||||
if (!p || n < 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ModbusRtuPdu pdu;
|
||||
if (!decodeModbusRtu(ctx.direction, p, n, pdu, nullptr)) {
|
||||
ctx.protocol.family = ProtocolFamily::None;
|
||||
ctx.protocol.pdu = {};
|
||||
ctx.parsed = QJsonObject();
|
||||
return false;
|
||||
}
|
||||
ctx.protocol.family = ProtocolFamily::ModbusRtu;
|
||||
ctx.protocol.pdu = pdu;
|
||||
syncLegacyJson(pdu, ctx.parsed);
|
||||
return true;
|
||||
}
|
||||
|
||||
void reset() override {}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
class ModbusRtuProtocolPlugin final : public IProtocolPlugin
|
||||
{
|
||||
public:
|
||||
QString pluginId() const override { return QStringLiteral("modbus_rtu"); }
|
||||
|
||||
bool supports(const QString& protocolHint) const override
|
||||
{
|
||||
return softbus::message_bus::pipeline::protocol::modbusrtu::isModbusRtuHint(protocolHint);
|
||||
}
|
||||
|
||||
std::unique_ptr<IProtocolSession> createSession() override
|
||||
{
|
||||
return std::make_unique<ModbusRtuSession>();
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<IProtocolPlugin> makeModbusRtuProtocolPlugin()
|
||||
{
|
||||
return std::make_shared<ModbusRtuProtocolPlugin>();
|
||||
}
|
||||
|
||||
IProtocolPlugin* createModbusRtuProtocolPluginRaw()
|
||||
{
|
||||
return new ModbusRtuProtocolPlugin();
|
||||
}
|
||||
|
||||
} // namespace softbus::core::plugin_system
|
||||
Reference in New Issue
Block a user