146 lines
6.8 KiB
C++
146 lines
6.8 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(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
|
||
|