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

146 lines
6.8 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/mapper/ModbusRtuProtocolMapperPlugin.h"
#include "plugins/protocols/modbus_rtu/framer/ModbusRtuFraming.h"
#include <QHash>
#include <utility>
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<std::uint64_t>(endpointHash) << 32)
| (static_cast<std::uint64_t>(static_cast<std::uint16_t>(protocol)) << 24)
| (static_cast<std::uint64_t>(slaveId) << 16)
| static_cast<std::uint64_t>(address);
}
std::vector<softbus::core::models::DOMMessage> map(
const softbus::core::models::RawBusMessage& 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()));
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<std::uint16_t>(baseAddress + static_cast<std::uint16_t>(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<double>(resp->registers[static_cast<qsizetype>(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<int>(resp->unitId));
pass.attributes.insert(QStringLiteral("registerAddress"), static_cast<int>(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<int>(resp->unitId));
msg.attributes.insert(QStringLiteral("registerAddress"), static_cast<int>(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<softbus::message_bus::pipeline::protocol::ReadHoldingRegistersRequest>(pdu)) {
m_lastReadHoldingStartAddress.insert(req->unitId, req->startAddress);
}
return out;
}
void reset() override {}
private:
softbus::core::plugin_system::MapperSessionContext m_context;
QHash<std::uint8_t, std::uint16_t> 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<softbus::core::plugin_system::IProtocolMapperSession> createMapperSession() override
{
return std::make_unique<ModbusRtuMapperSession>(softbus::core::plugin_system::MapperSessionContext{});
}
std::unique_ptr<softbus::core::plugin_system::IProtocolMapperSession> createMapperSession(
const softbus::core::plugin_system::MapperSessionContext& ctx) override
{
return std::make_unique<ModbusRtuMapperSession>(ctx);
}
};
} // 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