9.0 KiB
softbus_opcua
路径: src/softbus_opcua
构建目标: softbus_opcua(STATIC 库)
依赖: open62541 v1.4.6
层级: L2 服务层
1. 概述
softbus_opcua 基于 open62541 封装 OPC UA 服务端,将 SoftBus 对象模型动态映射为 OPC UA 地址空间,实现:
- 从
ObjectModelTree动态构建地址空间节点树 - 将
DOMMessage实时绑定到 UA Variable 节点 - 暴露
ExecuteCommand为 OPC UA Method(反向控制入口)
Phase 1 范围: 动态地址空间、Double Variable、ExecuteCommand Method;TLS 与 Event 为 stub。
2. CONSTRAINTS
- OPC UA 层不得引入 SoftBus 业务逻辑,仅负责地址空间构建、值绑定与方法转发。
- NodeId 策略统一:Namespace Index = 1,Identifier 类型 = String,值为
objectRef.toPath()。 - 所有 open62541 调用须包裹
#if SOFTBUS_HAS_OPCUA条件编译。 - Method 入参/出参均使用 JSON 字符串(UA String),与
softbus_api::ExecuteCommand对齐。 - Event 发射 Phase 1 为 stub,仅打日志,不得伪装为已生效功能。
- Phase 2 静态 NodeSet(
config/ua_model.xml)导入时,不得破坏动态构建的 NodeId 约定。
3. 组件架构
UaServerEngine ← open62541 生命周期管理
│
├── UaAddressSpaceBuilder ← JSON 模型 → UA 节点树
├── UaModelBinder ← DOMMessage → Variable 写值
├── UaMethodBinder ← ExecuteCommand Method 回调
└── UaEventBridge ← Event 发射(Phase 1 stub)
4. UaServerEngine
4.1 职责
管理 UA_Server 实例的创建、配置、运行与销毁。
4.2 公共 API
| 方法 | 入参 | 返回 | 说明 |
|---|---|---|---|
start(port, applicationName, security) |
端口、应用名、安全配置 | bool | 启动 OPC UA 服务 |
stop() |
— | void | 停止服务 |
iterate() |
— | void | 驱动事件循环(主循环调用) |
isRunning() |
— | bool | 运行状态 |
nativeServer() |
— | UA_Server* | 获取原生服务器指针 |
4.3 SecurityConfig
| 字段 | 类型 | Phase 1 |
|---|---|---|
enableTls |
bool | 未实现,忽略 |
certPath |
string | 未实现 |
keyPath |
string | 未实现 |
trustListPath |
string | 未实现 |
Phase 1 使用 UA_ServerConfig_setMinimal() 创建无安全策略的服务端。
4.4 配置来源
| 字段 | 配置路径 | 默认值 |
|---|---|---|
| 端口 | daemon_profile.json → opcua.port |
4840 |
| 应用名 | daemon_profile.json → opcua.applicationName |
SoftBusDaemon |
| TLS | daemon_profile.json → security.* |
关闭 |
连接端点: opc.tcp://localhost:4840
5. 地址空间
5.1 节点树结构
ObjectsFolder (NS0, 标准节点)
├── SoftBusControl (Object, NS1)
│ └── ExecuteCommand (Method, NS1)
│ ├── InputArguments: commandJson (String)
│ └── OutputArguments: resultJson (String)
└── {Site} (Object, NS1)
└── {System} (Object, NS1)
└── {Asset} (Object, NS1)
└── {stableDeviceKey} (Object, NS1)
└── {pointName} (Variable, NS1, Double, R/W)
5.2 示例(基于默认模型)
ObjectsFolder
├── SoftBusControl
│ └── ExecuteCommand
└── DemoSite
└── DemoSystem
└── DemoAsset
└── SimModbusDevice
└── Temperature (Double, 初始值 0.0)
5.3 NodeId 约定
| 节点类型 | Namespace | Identifier 类型 | Identifier 值 |
|---|---|---|---|
| Site | 1 | String | {siteName} |
| System | 1 | String | {systemName} |
| Asset | 1 | String | {assetName} |
| Device | 1 | String | {stableDeviceKey} |
| Point (Variable) | 1 | String | {objectRef.toPath()} |
| SoftBusControl | 1 | String | SoftBusControl |
| ExecuteCommand | 1 | String | ExecuteCommand |
Point 节点完整路径示例:
NodeId: ns=1;s=DemoSite/DemoSystem/DemoAsset/SimModbusDevice/Temperature
5.4 Variable 属性
| 属性 | 值 |
|---|---|
| DataType | Double (UA_TYPES_DOUBLE) |
| AccessLevel | Read + Write |
| TypeDefinition | BaseDataVariableType |
| 初始值 | 0.0 |
| ReferenceType | HasComponent |
5.5 模型映射规则
| softbus_model.json 字段 | OPC UA 节点 |
|---|---|
site |
Site Object |
system |
System Object(Site 子节点) |
asset |
Asset Object(System 子节点) |
devices[].stableDeviceKey |
Device Object(Asset 子节点) |
devices[].points[].name |
Variable(Device 子节点) |
构建完成后,UaModelBinder::registerPointNode(objectRef, nodeId) 建立 objectRef → UA_NodeId 映射。
6. UaModelBinder
6.1 职责
维护 objectRef → UA_NodeId 映射表,将 DOMMessage 实时写入对应 Variable。
6.2 公共 API
| 方法 | 说明 |
|---|---|
registerPointNode(objectRef, nodeId) |
注册映射(构建阶段调用) |
bind(DOMMessage) |
写值到 OPC UA Variable |
6.3 绑定逻辑
- 查找键 =
message.id(非空时)或message.sourceId - 从
message.value提取数值:- 优先
value["value"] - 备选
value["registerValue"]
- 优先
- 调用
UA_Server_writeValue(server, nodeId, doubleValue)
6.4 数据流
PipelineEngine::process(RawPacket)
→ ModbusParser → DOMMessage
→ UaModelBinder::bind(DOMMessage)
→ UA_Server_writeValue
→ OPC UA Client 可读
7. UaMethodBinder — ExecuteCommand Method
7.1 Method 定义
| 属性 | 值 |
|---|---|
| BrowseName | ExecuteCommand |
| Parent Object | SoftBusControl |
| InputArguments | commandJson (String) — JSON 格式的 ExecuteCommand |
| OutputArguments | resultJson (String) — JSON 格式响应 |
7.2 入参 JSON Schema
{
"traceId": "string (required)",
"objectRef": "string (required, 五层路径)",
"command": "string (required)",
"params": "object (required)"
}
注:OPC UA Method 入参不含
type字段,由ExecuteCommand::fromJson()直接解析。
7.3 出参 JSON Schema
成功:
{"success": true}
失败:
{"success": false, "error": "错误描述"}
7.4 调用流程
OPC UA Client 调用 ExecuteCommand(commandJson)
→ executeCommandMethod() 回调
→ nlohmann::json::parse(commandJson)
→ ExecuteCommand::fromJson() + validate()
→ dispatchCommand() → handler_(cmd)
→ CommandDispatcher → TCP 下行
→ 返回 resultJson
7.5 客户端调用示例(UaExpert)
- 连接
opc.tcp://localhost:4840 - 浏览至
Objects → SoftBusControl → ExecuteCommand - 右键调用 Method,输入:
{"traceId":"trace-ua-001","objectRef":"DemoSite/DemoSystem/DemoAsset/SimModbusDevice/Temperature","command":"write","params":{"value":42.5}}
8. UaEventBridge(Phase 1 stub)
| 方法 | 说明 | Phase 1 行为 |
|---|---|---|
emitHeartbeat() |
心跳事件 | 仅日志 |
emitDeviceOnline(objectRef) |
设备上线 | 仅日志 |
emitDeviceOffline(objectRef) |
设备离线 | 仅日志 |
emitParseError(traceId, detail) |
解析错误 | 仅日志 |
9. UaAddressSpaceBuilder
9.1 职责
从 ObjectModelTree 递归创建 OPC UA 对象树与 Variable 节点。
9.2 构建流程
- 获取
ObjectsFolder标准节点作为根 - 创建
SoftBusControlObject 与ExecuteCommandMethod - 按 Site → System → Asset → Device → Point 层级递归
UA_Server_addObjectNode/addVariableNode - 每个 Point 调用
binder->registerPointNode(objectRef, nodeId)
10. 条件编译
| 宏 | 说明 |
|---|---|
SOFTBUS_HAS_OPCUA |
CMake 选项 SOFTBUS_WITH_OPCUA=ON 时定义 |
SOFTBUS_WITH_OPCUA |
CMake option,默认 ON |
未启用时,所有 OPC UA 方法返回 false 或空操作。
11. open62541 配置
CMake 通过 SoftbusThirdParty.cmake 以 vendor 方式引入 third_party/open62541(v1.4.6):
| 选项 | 值 | 说明 |
|---|---|---|
| UA_ENABLE_SUBSCRIPTIONS | ON | 订阅支持 |
| UA_ENABLE_METHODCALLS | ON | 方法调用 |
| UA_ENABLE_DISCOVERY | ON | 发现服务 |
| UA_ENABLE_ENCRYPTION | OFF | Phase 1 无加密 |
12. Phase 路线图
| 阶段 | 功能 | 状态 |
|---|---|---|
| Phase 1 | 动态地址空间、Double Variable、ExecuteCommand、无 TLS | 当前 |
| Phase 2 | ua_model.xml NodeSet2 导入、TLS/mTLS、StatusCode 映射 |
规划 |
| Phase 2 | 真实 Event 发射(DeviceOnline/Offline、ParseError) | 规划 |
| Phase 3 | Subscription 优化、历史数据、多 DataType 支持 | 规划 |
12.1 Phase 2 NodeSet 占位
config/ua_model.xml 当前为空 shell,注释标明 Phase 2 可能导入静态 NodeSet2 XML,届时与动态构建策略需协调 NodeId 一致性。
13. 依赖
softbus_core(ObjectModelTree, DOMMessage, ObjectRef)softbus_api(ExecuteCommand)open62541(条件依赖)- 被依赖: softbus_daemon