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

221 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 协议插件
**路径:** `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
```cpp
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
```cpp
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 导出
每个插件须实现:
```cpp
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 模板
```cmake
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.json``plugins` 中注册插件名
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`
```json
{
"plugins": {
"modbus": "protocol_modbus",
"canopen": "protocol_canopen"
}
}
```
键名(如 `modbus`)用于代码中选择插件,值(如 `protocol_modbus`)用于文件名解析。
## 8. 构建
```bash
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 插件完整功能
- 支持多插件并行加载与协议自动选择
- 插件热加载与版本管理