Files
softbus_OPC/docs/plugins.md
2026-06-09 17:27:24 +08:00

5.8 KiB
Raw Permalink Blame History

协议插件

路径: src/plugins
构建目标: protocol_modbusprotocol_canopenSHARED 库)
层级: L2 协议层

1. 概述

协议插件以动态库(.so / .dll)形式实现 IFramerIParser 接口,由 PluginLoader 在运行时加载。守护进程 Pipeline 通过插件完成原始字节的分帧与语义解析。

2. CONSTRAINTS

  • 插件须通过 C ABI 导出 create_framer / create_parser / destroy_* 函数。
  • 插件仅依赖 softbus_core,不得链接 daemon、opcua 或 transport。
  • 解析输出必须为 DOMMessage,不得引入传输层特定字段。
  • 新增协议插件须遵循相同目录结构与 CMake 宏 softbus_add_plugin
  • Phase 1 modbus 插件硬编码寄存器 40001不读取 ObjectModel 映射表。

3. 插件接口

3.1 IFramer

class IFramer {
public:
    virtual FrameResult extract(const uint8_t* data, std::size_t size) = 0;
    virtual const char* protocolName() const = 0;
};

FrameResult 字段:

字段 说明
success 是否成功提取完整帧
consumedBytes 已消费字节数
frameStartOffset 帧起始偏移
frame 提取的完整帧数据

3.2 IParser

class IParser {
public:
    virtual ParseResult parseFrame(const uint8_t* data, std::size_t size,
                                   const std::string& sourceId) = 0;
    virtual const char* protocolName() const = 0;
};

ParseResult 字段:

字段 说明
success 是否解析成功
message 输出的 DOMMessage

3.3 C ABI 导出

每个插件须实现:

extern "C" SOFTBUS_PLUGIN_API IFramer* create_framer();
extern "C" SOFTBUS_PLUGIN_API void destroy_framer(IFramer* framer);
extern "C" SOFTBUS_PLUGIN_API IParser* create_parser();
extern "C" SOFTBUS_PLUGIN_API void destroy_parser(IParser* parser);

4. protocol_modbus

路径: src/plugins/protocol_modbus
输出: libprotocol_modbus.so

4.1 组件

组件 文件 职责
ModbusFramer ModbusFramer.h/.cpp 识别 func=0x03 响应帧
ModbusParser ModbusParser.h/.cpp 解析寄存器值 → DOMMessage
modbus_plugin.cpp C ABI 导出 工厂函数

4.2 ModbusFramer

  • 识别 Modbus RTU 功能码 0x03读保持寄存器响应帧
  • 根据字节计数与数据长度判断帧完整性
  • 输出完整帧供 Parser 消费

4.3 ModbusParser

  • 解析 0x03 响应帧中的寄存器值
  • 应用缩放因子 0.1(硬编码)
  • 输出 DOMMessage
    • id = sourceId
    • value = {"registerValue": <scaled_value>}
    • quality = "Good"

4.4 Phase 1 限制

  • 仅支持功能码 0x03 响应
  • 硬编码寄存器地址 40001
  • 不读取 ObjectModelRegistry 的寄存器映射

4.5 数据流

RawPacket.payload (Modbus bytes)
  → ModbusFramer.extract() → 完整帧
  → ModbusParser.parseFrame() → DOMMessage
  → UaModelBinder.bind()

5. protocol_canopen

路径: src/plugins/protocol_canopen
输出: libprotocol_canopen.so

5.1 组件状态

组件 Phase 1 状态
CanopenFramer stub空实现
CanopenParser stub空实现
CanopenObjectDictionary stub
EdsDcfLoader stub
CanopenNodeManager stub
CanopenMapper stub
canopen_plugin.cpp C ABI 导出存在,功能未实现

5.2 规划结构

CanopenFramer        ← CAN 帧分帧
CanopenParser        ← PDO/SDO 解析
CanopenObjectDictionary ← 对象字典管理
EdsDcfLoader         ← EDS/DCF 文件加载
CanopenNodeManager   ← 节点状态管理
CanopenMapper        ← 对象字典 → DOMMessage 映射

5.3 集成状态

  • daemon_profile.json 已配置 "canopen": "protocol_canopen"
  • CoreService Phase 1 仅加载 modbus 插件canopen 未接入

6. 插件开发指南

6.1 目录结构

src/plugins/protocol_<name>/
├── CMakeLists.txt
├── include/<name>/
│   ├── <Name>Framer.h
│   └── <Name>Parser.h
└── src/
    ├── <Name>Framer.cpp
    ├── <Name>Parser.cpp
    └── <name>_plugin.cpp

6.2 CMakeLists.txt 模板

softbus_add_plugin(protocol_<name>
    SOURCES
        src/<Name>Framer.cpp
        src/<Name>Parser.cpp
        src/<name>_plugin.cpp
    DEPENDS softbus_core
)

6.3 开发步骤

  1. 实现 IFramer::extract() — 从字节流提取完整协议帧
  2. 实现 IParser::parseFrame() — 将帧解析为 DOMMessage
  3. <name>_plugin.cpp 中导出 C ABI 工厂函数
  4. daemon_profile.jsonplugins 中注册插件名
  5. CoreService 中加载并注入 PipelineEngine

6.4 DOMMessage 输出约定

字段 要求
id 设为 sourceIdobjectRef 路径)
sourceId 保持传入值
domain 来自模型或默认 "Process"
quality "Good" / "Bad" / "Uncertain"
value JSON 对象,至少含 "value""registerValue" 数值字段

7. 插件搜索与加载

守护进程通过 CoreService::resolvePluginPath() 搜索插件,配置文件 daemon_profile.json

{
  "plugins": {
    "modbus": "protocol_modbus",
    "canopen": "protocol_canopen"
  }
}

键名(如 modbus)用于代码中选择插件,值(如 protocol_modbus)用于文件名解析。

8. 构建

cmake --build build --target protocol_modbus
cmake --build build --target protocol_canopen

输出:build/lib/libprotocol_modbus.sobuild/lib/libprotocol_canopen.so

9. Phase 2 规划

  • modbus 插件读取 ObjectModelRegistry 寄存器映射
  • 实现 canopen 插件完整功能
  • 支持多插件并行加载与协议自动选择
  • 插件热加载与版本管理