跳到主要内容

OPC-UA 驱动

概述

基于 OPC Unified Architecture (IEC 62541) 的工业数据标准协议。

项目
opc_typeOPCUA
实现类plantpulse.driver.protocol.opcua.OPCUA_34_Driver
Eclipse Milo (milo-sdk-client)
read
write❌ (Phase 3 / 与 Sparkplug NCMD 一起)
安全Username/Password, Anonymous

与 Kepware、Matrikon、Prosys 等大多数 OPC-UA 服务器兼容。


OPC 注册表单

字段含义示例
opc_agent_ipOPC-UA 服务器 IP192.168.0.40
opc_agent_portOPC-UA 服务器 TCP 端口49320 (Kepware 默认)
timecycle轮询周期 (ms)1000
options.servernameendpoint 末尾的服务器名(Kepware 则留空)
options.username认证用户kopens
options.password认证密码***
options.discovery是否使用 discovery endpointfalse (为 true 时自动检索 endpoints)

生成的 endpoint URL 格式:

opc.tcp://<opc_agent_ip>:<opc_agent_port>/<servername>

usernamepassword 同时存在时使用 UsernameProvider,否则使用 AnonymousProvider


标签 plc_address 格式

OPC-UA 标准 NodeId 表示法。例如:

表示含义
ns=2;s=Simulator.Sine1namespace 2, string identifier Simulator.Sine1
ns=2;i=1234numeric identifier 1234
ns=3;g=09087e75-8e5e-499b-954f-f2a8624db28aGUID identifier
ns=2;b=Mb=opaque (bytestring) identifier

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 / Booltrue/false 字符串
String / TextUTF-8 字符串
DateTimeISO 字符串

format 在 OPC-UA 中通常不使用。如需后处理运算,请使用 fomula


常见错误与解决

消息 / 现象原因解决
connection refused服务器未运行、端口被阻断telnet <ip> <port> 确认通信
Bad_UserAccessDeniedusername/password 错误、不允许匿名在服务器侧注册用户或启用 anonymous
Bad_SecurityChecksFailed安全策略不匹配在服务器确认 None / Basic256Sha256 等策略。Phase 1 优先使用 MessageSecurityMode.None
endpointUrl 不匹配discovery=false 但服务器返回了其他主机名保持为 discovery=true 或在 hosts 文件中做映射
值始终为 0 / nullNodeId 拼写错误、namespace 编号不一致用 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 快速配置指南

  1. Kepware Server → Project → 添加通道 (例如 Simulator)。
  2. 添加设备 (例如 Simulator) → 模型 = 16 Bit Device
  3. 添加标签 → Sine1,type Float,scan rate 100ms 等。
  4. Project Properties → OPC UA → Server Endpoint 中启用端口 49320
  5. 启用 Anonymous 或用户账户。

→ Edge 注册表单:

字段
opc_agent_ipKepware 服务器 IP
opc_agent_port49320
options.servername(留空)
options.username/password上面创建的账户
plc_addressns=2;s=Simulator.Simulator.Sine1

示例集 (按数据类型)

OPC-UA 将变量节点的值(Variant)转换为 String 后返回。data_type 供后处理 (PLCValueFomula、Sparkplug DataTypeMapper) 在类型转换时使用。format 通常不使用。

Boolean

data_typeplc_address 示例备注
Booleanns=2;s=Simulator.Boolean1Kepware Simulator 的 Boolean tag
Booleanns=2;s=PLC.Status.RunningKepware Channel.Device.Tag
Booleanns=2;i=1003numeric NodeId

16/32-bit 整数

data_typeplc_address 示例备注
Integerns=2;s=Simulator.Random1Random integer 模拟
Integerns=2;s=Simulator.Counter1Counter
Integerns=2;s=PLC.D100Kepware MELSEC 通道暴露

64-bit 整数

data_typeplc_address 示例备注
Longns=2;s=Simulator.LongCounterUInt64 / Int64 节点
Longns=2;s=PLC.Cycle.Total累计计数器

实数

data_typeplc_address 示例备注
Floatns=2;s=Simulator.Sine1sine wave 模拟
Floatns=2;s=Simulator.Ramp1ramp wave
Doublens=2;s=PLC.Pressure精密测量值

字符串

data_typeplc_address 示例备注
Stringns=2;s=Simulator.User1.Name字符串节点
Stringns=2;s=PLC.Recipe.Active配方名

按 NodeId 格式

identifier 类型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=

Formula 应用

用途data_typefomula备注
单位换算Float${VALUE}*0.001g → kg 等
零点校正Float${VALUE}-${TAG_ZERO}可引用其他 OPCUA 标签
类型转换Float${VALUE}*1.0Integer → 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"}
]
}'