#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 #include #include #include #include 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 struct overloaded : Ts... { using Ts::operator()...; }; template overloaded(Ts...) -> overloaded; 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(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(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(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(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(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(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 createSession() override { return std::make_unique(); } }; std::shared_ptr makeModbusRtuProtocolPlugin() { return std::make_shared(); } IProtocolPlugin* createModbusRtuProtocolPluginRaw() { return new ModbusRtuProtocolPlugin(); } } // namespace softbus::core::plugin_system