152 lines
7.1 KiB
C++
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
|