Files
softbus_daemon/plugins/protocols/modbus_rtu/mapper/ModbusRtuProtocolMapperPlugin.cpp
flower_linux 7280fca08d dommessage
2026-04-28 21:56:56 +08:00

152 lines
7.1 KiB
C++

#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(rawContext, 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);
}
const bool sniff = m_context.sniffingEnabled ? m_context.sniffingEnabled() : false;
if (!sniff) {
continue;
}
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.pointId = mapRule->pointId.isEmpty() ? mapRule->domPath : mapRule->pointId;
msg.metadataId = mapRule->metadataId;
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));
msg.attributes.insert(QStringLiteral("mappingSource"), mapRule->sourceTag);
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