OPC-UA 驱动
概览
基于 OPC Unified Architecture (IEC 62541) 的工业数据标准协议。
| 项目 | 值 |
|---|---|
opc_type | OPCUA |
| 实现类 | plantpulse.driver.protocol.opcua.OPCUA_34_Driver |
| 库 | Eclipse Milo (milo-sdk-client) |
| read | ✅ |
| write | ✅ (node.writeValue) |
| 安全 | 用户认证 Anonymous, Username/Password。通道安全 None · Sign · SignAndEncrypt · auto |
与 Kepware, Matrikon, Prosys 等绝大多数 OPC-UA 服务器兼容。
OPC 注册表单
| 字段 | 含义 | 示例 |
|---|---|---|
opc_agent_ip | OPC-UA 服务器 IP | 192.168.0.40 |
opc_agent_port | OPC-UA 服务器 TCP 端口 | 49320 (Kepware 默认) |
timecycle | 采集周期 (ms) | 1000 |
options.servername | endpoint 末尾的服务器名称 | (Kepware 则留空) |
options.username | 认证用户 | kopens |
options.password | 认证密码 | *** |
options.discovery | 若为 true,则在连接时从 RootFolder 开始浏览整个节点树并记录在日志中(非端点搜索 — 端点请使用界面的 [查询端点]) | false (建议) |
options.security_mode | 通道安全模式。None(默认) · Sign · SignAndEncrypt · auto(在 Sign · SignAndEncrypt 中选择最强模式)。若非 None,则不会降级为 None。忽略大小写,未知值设为 OPCUA_SECURITY_CONFIG_INVALID | SignAndEncrypt |
options.security_policy | auto(默认) · Basic256Sha256 · Aes128_Sha256_RsaOaep · Aes256_Sha256_RsaPss。auto 的优先级为 Aes256_Sha256_RsaPss > Basic256Sha256 > Aes128_Sha256_RsaOaep。若安全模式为 None 则忽略 | auto |
options.allow_deprecated_policy | 若为 true,则允许已弃用的 Basic256 · Basic128Rsa15 (auto 进入候选并可明确指定)。除 true/false 外的值为 OPCUA_SECURITY_CONFIG_INVALID | false |
生成的 endpoint URL 格式:
opc.tcp://<opc_agent_ip>:<opc_agent_port>/<servername>
若 username + password 同时存在则使用 UsernameProvider,否则使用 AnonymousProvider。
pki_dir(客户端证书与信任列表目录)并非输入框。仅在 edge-web 安全模式不为 None 时插入 $PE_DATA_DIR/pp-data/opcua-client,连接行中保存的值将被舍弃。
端点选择:
security_mode=None(OPCUA_34_Driver.selectEndpoint) — 仅在服务器公布的列表中选择MessageSecurityMode.None的项。优先选择公布了所用令牌类型 (UserName / Anonymous) 的端点,若无则选择第一个 None 端点。- 其他模式 (
OpcuaEndpointSelector.selectSecure) — 在同时满足接受模式、策略及所用令牌类型的端点中,选择最强的一个。若无,则不降级至 None,而是以OPCUA_NO_MATCHING_ENDPOINT失败。
所选端点 URL 的主机将替换为 opc_agent_ip(端口和路径使用服务器公布的值)。已知原因的失败(证书 · 安全设置 · 无匹配端点)将记录一行 OPCUA connect refused: error_code=<코드> opc_id=<OPC ID> ... WARN(同一原因仅记录一次)。OPCUA_CONNECT_FAILED · OPCUA_PKI_ERROR 每次均记录 OPCUA connect failed: ... ERROR 及堆栈信息。
服务器证书信任、Edge 证书下载及错误提示请参阅 OPC-UA 连接 — 安全连接。首次见到的服务器证书将被拒绝(首次连接无自动信任),需在界面由操作员信任后方可连接。
标签 plc_address 格式
OPC-UA 标准 NodeId 表示法。例如:
| 表示法 | 含义 |
|---|---|
ns=2;s=Simulator.Sine1 | 命名空间 2, 字符串标识符 Simulator.Sine1 |
ns=2;i=1234 | 数值标识符 1234 |
ns=3;g=09087e75-8e5e-499b-954f-f2a8624db28a | GUID 标识符 |
ns=2;b=Mb= | 不透明 (bytestring) 标识符 |
对于 Kepware,通常采用 ns=2;s=<Channel>.<Device>.<Tag> 格式。
data_type / format 映射
将 OPC-UA 变量节点的 Value 转换为 String 后返回。data_type 由后续阶段 (PLCValueFomula, Sparkplug 发布等) 用于转换。
data_type | 动作 |
|---|---|
Float / Double | 数值原样返回 |
Int / Integer / Int32 / Short / Long | 数值原样返回 |
Boolean / Bool | true/false 字符串 |
String / Text | UTF-8 字符串 |
DateTime | ISO 字符串 |
format 在 OPC-UA 中通常不使用。如需后处理公式,请使用 fomula。
常见错误 + 解决
| 消息 / 症状 | 原因 | 解决 |
|---|---|---|
connection refused | 服务器未运行,端口被封锁 | 通过 telnet <ip> <port> 确认通信 |
Bad_UserAccessDenied | 用户名/密码错误,禁止匿名访问 | 在服务器端注册用户或激活 anonymous |
OPCUA_CLIENT_CERT_REJECTED (Bad_SecurityChecksFailed 等) | 服务器不信任 Edge 客户端证书 | 将 Edge 证书 (.der) 加入服务器信任列表 |
OPCUA_NO_MATCHING_ENDPOINT | 服务器未公布该模式·策略·令牌的端点 | 通过界面的 [查询端点] 确认服务器提供的组合并进行匹配 |
| 端口不匹配导致连接失败 | 驱动仅将公布端点的主机更改为 opc_agent_ip,端口和路径维持原样 | 若通过 NAT·端口转发更改端口公开,请将其配置为与服务器公布的端口一致。无需 hosts 映射 |
| 值始终为 0 / null | NodeId 拼写错误,命名空间编号不一致 | 使用 UA Expert 等客户端验证相同 NodeId 的 read 操作 |
curl 注册示例
curl -X POST http://<edge-host>/api/v1/opc \
-H "Content-Type: application/json" \
-d '{
"opc_id": "OPC_UA_Kepware",
"opc_type": "OPCUA",
"opc_name": "Kepware",
"opc_agent_ip": "192.168.0.40",
"opc_agent_port": "49320",
"site_id": "SITE_00001",
"auto_collect": true,
"timecycle": 1000,
"options": {
"username": "kopens",
"password": "***",
"discovery": "false"
},
"tag_list": [
{
"tag_id": "OPC_UA_Kepware_TAG_00001",
"tag_name": "Sine1",
"plc_address": "ns=2;s=Simulator.Sine1",
"data_type": "Float",
"description": "Sine wave"
},
{
"tag_id": "OPC_UA_Kepware_TAG_00002",
"tag_name": "Random1",
"plc_address": "ns=2;s=Simulator.Random1",
"data_type": "Integer"
}
]
}'
读取值:
curl -s http://<edge-host>/api/v1/tag/OPC_UA_Kepware_TAG_00001/value | jq
参考:Kepware 快速配置指南
- Kepware Server → Project → 添加通道 (例如:
Simulator)。 - 添加设备 (例如:
Simulator) → 型号 =16 Bit Device。 - 添加标签 →
Sine1, 类型Float, 扫描率100ms等。 - 在
Project Properties → OPC UA → Server Endpoint中激活端口49320。 - 激活 Anonymous 或用户账户。若为安全连接,请在端点安全策略中开启
Basic256Sha256以上级别及 Sign and Encrypt,并将 Edge 证书加入信任列表。
→ Edge 注册表单:
| 字段 | 值 |
|---|---|
| opc_agent_ip | Kepware 服务器 IP |
| opc_agent_port | 49320 |
| options.servername | (留空) |
| options.username/password | 上述创建的账户 |
| plc_address | ns=2;s=Simulator.Simulator.Sine1 |
示例集 (按数据类型)
OPC-UA 将变量节点的值 (Variant) 转换为 String 后返回。data_type 由后处理 (PLCValueFomula, Sparkplug DataTypeMapper) 用于转换。format 通常不使用。
Boolean
data_type | plc_address 示例 | 备注 |
|---|---|---|
Boolean | ns=2;s=Simulator.Boolean1 | Kepware Simulator 的 Boolean 标签 |
Boolean | ns=2;s=PLC.Status.Running | Kepware Channel.Device.Tag |
Boolean | ns=2;i=1003 | 数值型 NodeId |
16/32-bit 整数
data_type | plc_address 示例 | 备注 |
|---|---|---|
Integer | ns=2;s=Simulator.Random1 | 随机整数模拟 |
Integer | ns=2;s=Simulator.Counter1 | 计数器 |
Integer | ns=2;s=PLC.D100 | Kepware MELSEC 通道公开 |
64-bit 整数
data_type | plc_address 示例 | 备注 |
|---|---|---|
Long | ns=2;s=Simulator.LongCounter | UInt64 / Int64 节点 |
Long | ns=2;s=PLC.Cycle.Total | 累积计数器 |
浮点数
data_type | plc_address 示例 | 备注 |
|---|---|---|
Float | ns=2;s=Simulator.Sine1 | 正弦波模拟 |
Float | ns=2;s=Simulator.Ramp1 | 锯齿波 |
Double | ns=2;s=PLC.Pressure | 精密测量值 |
字符串
data_type | plc_address 示例 | 备注 |
|---|---|---|
String | ns=2;s=Simulator.User1.Name | 字符串节点 |
String | ns=2;s=PLC.Recipe.Active | 配方名称 |
按 NodeId 格式
| 标识符类型 | plc_address 示例 |
|---|---|
String (s=) | ns=2;s=Simulator.Sine1 |
Numeric (i=) | ns=2;i=1234 |
GUID (g=) | ns=3;g=09087e75-8e5e-499b-954f-f2a8624db28a |
Opaque (b=) | ns=2;b=Mb= |
计算公式应用
| 用途 | data_type | fomula | 备注 |
|---|---|---|---|
| 单位转换 | Float | ${VALUE}*0.001 | g → kg 等 |
| 零点校准 | Float | ${VALUE}-${TAG_ZERO} | 可引用其他 OPCUA 标签 |
| 类型转换 | Float | ${VALUE}*1.0 | 强制 Integer → Float |
| 多项式 | Float | ${VALUE}*${VALUE}*0.0001 | 非线性 |
curl 综合示例 (所有类型)
curl -X POST http://<edge-host>/api/v1/opc \
-H "Content-Type: application/json" \
-d '{
"opc_id": "OPC_UA_FULL",
"opc_type": "OPCUA",
"opc_name": "Kepware Full",
"opc_agent_ip": "192.168.0.40",
"opc_agent_port": "49320",
"site_id": "SITE_00001",
"auto_collect": true,
"timecycle": 1000,
"options": { "discovery": "false" },
"tag_list": [
{"tag_id":"OPC_UA_FULL_T01", "tag_name":"BoolTag", "plc_address":"ns=2;s=Simulator.Boolean1", "data_type":"Boolean"},
{"tag_id":"OPC_UA_FULL_T02", "tag_name":"IntTag", "plc_address":"ns=2;s=Simulator.Random1", "data_type":"Integer"},
{"tag_id":"OPC_UA_FULL_T03", "tag_name":"LongTag", "plc_address":"ns=2;s=Simulator.LongCounter", "data_type":"Long"},
{"tag_id":"OPC_UA_FULL_T04", "tag_name":"FloatTag", "plc_address":"ns=2;s=Simulator.Sine1", "data_type":"Float"},
{"tag_id":"OPC_UA_FULL_T05", "tag_name":"DoubleTag", "plc_address":"ns=2;s=PLC.Pressure", "data_type":"Double"},
{"tag_id":"OPC_UA_FULL_T06", "tag_name":"StringTag", "plc_address":"ns=2;s=Simulator.User1.Name", "data_type":"String"},
{"tag_id":"OPC_UA_FULL_T07", "tag_name":"NumIdTag", "plc_address":"ns=2;i=1234", "data_type":"Integer"},
{"tag_id":"OPC_UA_FULL_T08", "tag_name":"ScaledTag", "plc_address":"ns=2;s=Simulator.Sine1", "data_type":"Float", "fomula":"${VALUE}*100"}
]
}'