DolphinDB OPC-UA协议接入:工业标准通信

目录

    • 摘要
    • 一、OPC-UA协议概述
      • [1.1 什么是OPC-UA](#1.1 什么是OPC-UA)
      • [1.2 OPC-UA特点](#1.2 OPC-UA特点)
      • [1.3 OPC-UA vs OPC-DA](#1.3 OPC-UA vs OPC-DA)
    • [二、DolphinDB OPC-UA插件](#二、DolphinDB OPC-UA插件)
      • [2.1 插件安装](#2.1 插件安装)
      • [2.2 连接配置](#2.2 连接配置)
    • 三、OPC-UA连接
      • [3.1 创建连接](#3.1 创建连接)
      • [3.2 浏览节点](#3.2 浏览节点)
      • [3.3 节点标识](#3.3 节点标识)
    • 四、数据读取
      • [4.1 读取单个节点](#4.1 读取单个节点)
      • [4.2 批量读取](#4.2 批量读取)
      • [4.3 读取历史数据](#4.3 读取历史数据)
    • 五、数据订阅
      • [5.1 创建订阅](#5.1 创建订阅)
      • [5.2 订阅配置](#5.2 订阅配置)
      • [5.3 取消订阅](#5.3 取消订阅)
    • 六、数据写入
      • [6.1 写入单个节点](#6.1 写入单个节点)
      • [6.2 批量写入](#6.2 批量写入)
    • 七、实战案例
      • [7.1 PLC数据采集系统](#7.1 PLC数据采集系统)
    • 八、总结
    • 参考资料

摘要

本文深入讲解DolphinDB OPC-UA协议接入技术。从OPC-UA协议原理到插件配置,从节点浏览到数据订阅,从实时采集到历史数据读取,全面介绍OPC-UA数据采集的核心方法。通过丰富的代码示例,帮助读者掌握工业标准通信的核心技能。


一、OPC-UA协议概述

1.1 什么是OPC-UA

OPC-UA(Open Platform Communications Unified Architecture)是工业自动化标准通信协议:
#mermaid-svg-ADHkGOE1wf32uOip{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ADHkGOE1wf32uOip .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ADHkGOE1wf32uOip .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ADHkGOE1wf32uOip .error-icon{fill:#552222;}#mermaid-svg-ADHkGOE1wf32uOip .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ADHkGOE1wf32uOip .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ADHkGOE1wf32uOip .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ADHkGOE1wf32uOip .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ADHkGOE1wf32uOip .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ADHkGOE1wf32uOip .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ADHkGOE1wf32uOip .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ADHkGOE1wf32uOip .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ADHkGOE1wf32uOip .marker.cross{stroke:#333333;}#mermaid-svg-ADHkGOE1wf32uOip svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ADHkGOE1wf32uOip p{margin:0;}#mermaid-svg-ADHkGOE1wf32uOip .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ADHkGOE1wf32uOip .cluster-label text{fill:#333;}#mermaid-svg-ADHkGOE1wf32uOip .cluster-label span{color:#333;}#mermaid-svg-ADHkGOE1wf32uOip .cluster-label span p{background-color:transparent;}#mermaid-svg-ADHkGOE1wf32uOip .label text,#mermaid-svg-ADHkGOE1wf32uOip span{fill:#333;color:#333;}#mermaid-svg-ADHkGOE1wf32uOip .node rect,#mermaid-svg-ADHkGOE1wf32uOip .node circle,#mermaid-svg-ADHkGOE1wf32uOip .node ellipse,#mermaid-svg-ADHkGOE1wf32uOip .node polygon,#mermaid-svg-ADHkGOE1wf32uOip .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ADHkGOE1wf32uOip .rough-node .label text,#mermaid-svg-ADHkGOE1wf32uOip .node .label text,#mermaid-svg-ADHkGOE1wf32uOip .image-shape .label,#mermaid-svg-ADHkGOE1wf32uOip .icon-shape .label{text-anchor:middle;}#mermaid-svg-ADHkGOE1wf32uOip .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ADHkGOE1wf32uOip .rough-node .label,#mermaid-svg-ADHkGOE1wf32uOip .node .label,#mermaid-svg-ADHkGOE1wf32uOip .image-shape .label,#mermaid-svg-ADHkGOE1wf32uOip .icon-shape .label{text-align:center;}#mermaid-svg-ADHkGOE1wf32uOip .node.clickable{cursor:pointer;}#mermaid-svg-ADHkGOE1wf32uOip .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ADHkGOE1wf32uOip .arrowheadPath{fill:#333333;}#mermaid-svg-ADHkGOE1wf32uOip .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ADHkGOE1wf32uOip .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ADHkGOE1wf32uOip .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ADHkGOE1wf32uOip .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ADHkGOE1wf32uOip .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ADHkGOE1wf32uOip .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ADHkGOE1wf32uOip .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ADHkGOE1wf32uOip .cluster text{fill:#333;}#mermaid-svg-ADHkGOE1wf32uOip .cluster span{color:#333;}#mermaid-svg-ADHkGOE1wf32uOip div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ADHkGOE1wf32uOip .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ADHkGOE1wf32uOip rect.text{fill:none;stroke-width:0;}#mermaid-svg-ADHkGOE1wf32uOip .icon-shape,#mermaid-svg-ADHkGOE1wf32uOip .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ADHkGOE1wf32uOip .icon-shape p,#mermaid-svg-ADHkGOE1wf32uOip .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ADHkGOE1wf32uOip .icon-shape .label rect,#mermaid-svg-ADHkGOE1wf32uOip .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ADHkGOE1wf32uOip .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ADHkGOE1wf32uOip .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ADHkGOE1wf32uOip :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} OPC-UA架构
PLC/DCS
OPC-UA Server
传感器
设备
OPC-UA Client
DolphinDB
SCADA
MES

1.2 OPC-UA特点

特点 说明
平台无关 跨平台支持
安全通信 加密认证
信息模型 标准化数据模型
订阅机制 变化通知

1.3 OPC-UA vs OPC-DA

特性 OPC-DA OPC-UA
平台 Windows only 跨平台
协议 DCOM TCP/HTTP
安全
推荐

二、DolphinDB OPC-UA插件

2.1 插件安装

python 复制代码
// 检查插件
getLoadedPlugins()

// 加载OPC-UA插件
loadPlugin("opcua")

// 查看插件函数
opcua::getPluginFunctions()

2.2 连接配置

python 复制代码
// OPC-UA连接配置
config = dict(STRING, ANY, [
    ["endpointUrl", "opc.tcp://localhost:4840"],
    ["securityMode", "None"],  // None/Sign/SignAndEncrypt
    ["securityPolicy", "None"], // None/Basic128Rsa15/Basic256/Aes256
    ["username", "admin"],
    ["password", "password"]
])

三、OPC-UA连接

3.1 创建连接

python 复制代码
// 连接OPC-UA服务器
conn = opcua::connect("opc.tcp://localhost:4840")

// 带认证连接
conn = opcua::connect(
    "opc.tcp://localhost:4840",
    "admin",
    "password"
)

// 查看连接状态
opcua::getStatus(conn)

// 断开连接
opcua::disconnect(conn)

3.2 浏览节点

python 复制代码
// 浏览根节点
nodes = opcua::browse(conn, "i=84")  // Root节点

// 浏览Objects节点
objects = opcua::browse(conn, "i=85")  // Objects节点

// 浏览设备节点
deviceNodes = opcua::browse(conn, "ns=2;s=Device1")

3.3 节点标识

python 复制代码
// 节点标识格式
// i=数字 -> 整数标识符
// s=字符串 -> 字符串标识符
// g=GUID -> GUID标识符
// b=字节串 -> 字节串标识符

// 示例
nodeId = "ns=2;s=Temperature"  // 命名空间2,字符串标识符
nodeId = "i=2258"              // 整数标识符

四、数据读取

4.1 读取单个节点

python 复制代码
// 读取节点值
value = opcua::read(conn, "ns=2;s=Temperature")

// 读取带时间戳
result = opcua::readWithTimestamp(conn, "ns=2;s=Temperature")
print("值: " + string(result.value))
print("时间: " + string(result.timestamp))
print("质量: " + string(result.quality))

4.2 批量读取

python 复制代码
// 批量读取多个节点
nodeIds = [
    "ns=2;s=Temperature",
    "ns=2;s=Humidity",
    "ns=2;s=Pressure"
]

values = opcua::readBatch(conn, nodeIds)

// 结果
for (i in 0..nodeIds.size()) {
    print(nodeIds[i] + " = " + string(values[i]))
}

4.3 读取历史数据

python 复制代码
// 读取历史数据
startTime = now() - 3600000  // 1小时前
endTime = now()

history = opcua::readHistory(
    conn,
    "ns=2;s=Temperature",
    startTime,
    endTime
)

// 历史数据格式
select top 10 * from history

五、数据订阅

5.1 创建订阅

python 复制代码
// 创建流表
share streamTable(1:0, 
    `node_id`timestamp`value`quality,
    [STRING, TIMESTAMP, DOUBLE, INT]) as opcua_stream

// 创建订阅
subscription = opcua::createSubscription(conn, 1000)  // 采样间隔1秒

// 添加监控项
opcua::addMonitoredItem(subscription, "ns=2;s=Temperature", opcua_stream)
opcua::addMonitoredItem(subscription, "ns=2;s=Humidity", opcua_stream)
opcua::addMonitoredItem(subscription, "ns=2;s=Pressure", opcua_stream)

// 查看订阅
opcua::getSubscriptionStat(subscription)

5.2 订阅配置

python 复制代码
// 订阅参数配置
subscription = opcua::createSubscription(
    conn,
    1000,     // 采样间隔(毫秒)
    100,      // 队列大小
    true,     // 数据变化触发
    10        // 环形缓冲区大小
)

// 监控项配置
opcua::addMonitoredItem(
    subscription,
    "ns=2;s=Temperature",
    opcua_stream,
    0.5       // 死区(变化超过0.5才触发)
)

5.3 取消订阅

python 复制代码
// 删除监控项
opcua::removeMonitoredItem(subscription, "ns=2;s=Temperature")

// 删除订阅
opcua::deleteSubscription(subscription)

六、数据写入

6.1 写入单个节点

python 复制代码
// 写入节点值
opcua::write(conn, "ns=2;s=Setpoint", 25.0)

// 写入带时间戳
opcua::writeWithTimestamp(
    conn,
    "ns=2;s=Setpoint",
    25.0,
    now()
)

6.2 批量写入

python 复制代码
// 批量写入
nodeIds = ["ns=2;s=Setpoint1", "ns=2;s=Setpoint2", "ns=2;s=Setpoint3"]
values = [25.0, 30.0, 35.0]

opcua::writeBatch(conn, nodeIds, values)

七、实战案例

7.1 PLC数据采集系统

python 复制代码
// ========== PLC数据采集系统 ==========

// 1. 创建分布式表
db = database("dfs://plc_db", VALUE, 1..100)
schema = table(1:0, 
    `device_id`timestamp`temperature`pressure`flow_rate,
    [SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE])
db.createPartitionedTable(schema, `plc_data, `device_id)

// 2. 创建流表
share streamTable(100000:0, 
    `device_id`timestamp`temperature`pressure`flow_rate,
    [SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE]) as plc_stream

// 3. 启用持久化
enableTablePersistence(plc_stream, true, true, 1000000)

// 4. 订阅流表写入分布式表
subscribeTable(, "plc_stream", "persist", -1,
    def(msg) {
        loadTable("dfs://plc_db", "plc_data").append!(msg)
    }, 10000, 5000)

// 5. 连接OPC-UA服务器
conn = opcua::connect("opc.tcp://plc-server:4840")

// 6. 创建订阅
subscription = opcua::createSubscription(conn, 1000)

// 7. 添加监控项
opcua::addMonitoredItem(subscription, "ns=2;s=Temperature", plc_stream)
opcua::addMonitoredItem(subscription, "ns=2;s=Pressure", plc_stream)
opcua::addMonitoredItem(subscription, "ns=2;s=FlowRate", plc_stream)

// 8. 监控函数
def monitorPlc() {
    print("=== PLC数据采集监控 ===")
    print("OPC-UA状态: " + opcua::getStatus(conn))
    print("流表行数: " + string(exec count(*) from plc_stream))
    
    t = loadTable("dfs://plc_db", "plc_data")
    print("分布式表行数: " + string(exec count(*) from t))
}

monitorPlc()

print("PLC数据采集系统启动完成")

八、总结

本文详细介绍了DolphinDB OPC-UA协议接入:

  1. OPC-UA协议:工业标准、安全通信、信息模型
  2. 插件配置:安装、加载、连接
  3. 节点浏览:浏览节点、节点标识
  4. 数据读取:单点读取、批量读取、历史数据
  5. 数据订阅:创建订阅、监控项配置
  6. 数据写入:单点写入、批量写入

思考题

  1. OPC-UA相比OPC-DA有什么优势?
  2. 如何设计高可用的OPC-UA数据采集系统?
  3. 如何处理OPC-UA连接断开问题?

参考资料


相关推荐
yxl874646461 小时前
磐创PCTG-9013 Modbus转ProfibusDP工业协议转换器
网络·科技·物联网·gateway·信息与通信
蚂蚁数据AntData2 小时前
从ChatBI到业务记忆:重新定义数据智能的生产力边界
大数据·网络·数据库·人工智能·算法
W.W.H.2 小时前
Ping 与 TCP:网络连通性探测的两种维度
网络·网络协议·tcp/ip
IT WorryFree2 小时前
基于Fortinet MIB实现设备资产管理完整方案
运维·服务器·网络
yngsqq2 小时前
电脑联网win10
网络
蔷薇灵动2 小时前
放弃与Mythos 拼手速,用零信任与微隔离重铸网络的确定性秩序
网络·安全
实在智能RPA3 小时前
航空Agent落地效果评估指标:2026年企业级智能自动化价值度量体系拆解
java·网络·人工智能·ai·自动化
vensli3 小时前
体验专题——Android 应用瘦身实战
android·网络
Multipath7123 小时前
急救车上的“信号堡垒”:多链路聚合路由如何让生命连线永不掉线
网络·5g·安全·实时音视频