#include "plugins/protocols/modbus_rtu/mapper/ModbusRtuProtocolMapperPlugin.h" #include "plugins/protocols/modbus_rtu/framer/ModbusRtuFraming.h" #include #include namespace softbus::message_bus::pipeline::protocol::modbusrtu { namespace { class ModbusRtuMapperSession final : public softbus::core::plugin_system::IProtocolMapperSession { public: explicit ModbusRtuMapperSession(softbus::core::plugin_system::MapperSessionContext context) : m_context(std::move(context)) { } static std::uint64_t buildCompositeKey(std::uint32_t endpointHash, softbus::core::models::ProtocolType protocol, std::uint8_t slaveId, std::uint16_t address) { return (static_cast(endpointHash) << 32) | (static_cast(static_cast(protocol)) << 24) | (static_cast(slaveId) << 16) | static_cast(address); } std::vector map( const softbus::core::models::RawBusMessage& rawContext, const softbus::message_bus::pipeline::protocol::ProtocolEnvelope& envelope) override { std::vector out; if (envelope.family != softbus::message_bus::pipeline::protocol::ProtocolFamily::ModbusRtu) { return out; } const auto* pdu = std::get_if(&envelope.pdu); if (!pdu) { return out; } if (const auto* resp = std::get_if(pdu)) { out.reserve(static_cast(resp->registers.size())); const std::uint16_t baseAddress = m_lastReadHoldingStartAddress.value(resp->unitId, 0); for (int i = 0; i < resp->registers.size(); ++i) { const auto addr = static_cast(baseAddress + static_cast(i)); const auto compKey = buildCompositeKey( rawContext.endpointHash, rawContext.protocol, resp->unitId, addr); const auto mapRule = m_context.mappingLookup ? m_context.mappingLookup->find(compKey) : std::nullopt; const double rawValue = static_cast(resp->registers[static_cast(i)]); if (!mapRule.has_value()) { if (m_context.discoverySink) { softbus::core::plugin_system::DiscoveryRecord rec; rec.compositeKey = compKey; rec.endpointHash = rawContext.endpointHash; rec.protocol = rawContext.protocol; rec.slaveId = resp->unitId; rec.registerAddress = addr; rec.rawValue = rawValue; rec.lastSeenMs = rawContext.timestampMs; m_context.discoverySink->reportUnmapped(rec); } // 无 metadata 映射时仍产出 DOM,便于 DynamicRuleRegistry 的 transform 等下游逻辑生效 // (compositeKey 仍按与映射表相同的算法计算,便于后续在 UI 里绑定映射) softbus::core::models::DOMMessage pass; pass.messageId = QStringLiteral("modbus.unmapped:%1").arg(compKey); pass.timestamp = rawContext.timestampMs; pass.value = rawValue; pass.quality = softbus::core::models::DataQuality::GOOD; pass.attributes.insert(QStringLiteral("sourceEndpoint"), QString::number(rawContext.endpointHash)); pass.attributes.insert(QStringLiteral("compositeKey"), QString::number(compKey)); pass.attributes.insert(QStringLiteral("slaveId"), static_cast(resp->unitId)); pass.attributes.insert(QStringLiteral("registerAddress"), static_cast(addr)); pass.attributes.insert(QStringLiteral("unmapped"), true); out.push_back(std::move(pass)); continue; } softbus::core::models::DOMMessage msg; msg.messageId = mapRule->domPath; msg.timestamp = rawContext.timestampMs; msg.value = (rawValue * mapRule->scale) + mapRule->offset; msg.quality = softbus::core::models::DataQuality::GOOD; msg.attributes.insert(QStringLiteral("sourceEndpoint"), QString::number(rawContext.endpointHash)); msg.attributes.insert(QStringLiteral("compositeKey"), QString::number(compKey)); msg.attributes.insert(QStringLiteral("slaveId"), static_cast(resp->unitId)); msg.attributes.insert(QStringLiteral("registerAddress"), static_cast(addr)); if (!mapRule->unit.isEmpty()) { msg.attributes.insert(QStringLiteral("unit"), mapRule->unit); } out.push_back(std::move(msg)); } return out; } if (const auto* req = std::get_if(pdu)) { m_lastReadHoldingStartAddress.insert(req->unitId, req->startAddress); } return out; } void reset() override {} private: softbus::core::plugin_system::MapperSessionContext m_context; QHash m_lastReadHoldingStartAddress; }; class ModbusRtuProtocolMapperPlugin final : public softbus::core::plugin_system::IProtocolMapperPlugin { public: QString pluginId() const override { return QStringLiteral("modbus_rtu_mapper"); } softbus::core::models::ProtocolType protocolType() const override { return softbus::core::models::ProtocolType::MODBUS_RTU; } std::unique_ptr createMapperSession() override { return std::make_unique(softbus::core::plugin_system::MapperSessionContext{}); } std::unique_ptr createMapperSession( const softbus::core::plugin_system::MapperSessionContext& ctx) override { return std::make_unique(ctx); } }; } // namespace std::shared_ptr makeModbusRtuProtocolMapperPlugin() { return std::make_shared(); } softbus::core::plugin_system::IProtocolMapperPlugin* createModbusRtuProtocolMapperPluginRaw() { return new ModbusRtuProtocolMapperPlugin(); } } // namespace softbus::message_bus::pipeline::protocol::modbusrtu