5.8 KiB
5.8 KiB
协议插件
路径: src/plugins
构建目标: protocol_modbus、protocol_canopen(SHARED 库)
层级: L2 协议层
1. 概述
协议插件以动态库(.so / .dll)形式实现 IFramer 与 IParser 接口,由 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= sourceIdvalue={"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"CoreServicePhase 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 开发步骤
- 实现
IFramer::extract()— 从字节流提取完整协议帧 - 实现
IParser::parseFrame()— 将帧解析为DOMMessage - 在
<name>_plugin.cpp中导出 C ABI 工厂函数 - 在
daemon_profile.json→plugins中注册插件名 - 在
CoreService中加载并注入PipelineEngine
6.4 DOMMessage 输出约定
| 字段 | 要求 |
|---|---|
id |
设为 sourceId(objectRef 路径) |
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.so、build/lib/libprotocol_canopen.so
9. Phase 2 规划
- modbus 插件读取
ObjectModelRegistry寄存器映射 - 实现 canopen 插件完整功能
- 支持多插件并行加载与协议自动选择
- 插件热加载与版本管理