You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C#通过OPC UA获取Siemens TP1200 Comfort节点的值

解决方案

首先,OPC UA客户端不会自动加载根节点的所有子节点——你得主动发起**浏览(Browse)**操作,或者直接通过节点路径/ID来定位目标变量。西门子TP1200 Comfort的OPC UA服务器里,HMI标签(变量)都在特定命名空间下,下面给你具体步骤和代码:

1. 先确认目标节点的命名空间索引

西门子HMI的OPC UA命名空间一般是urn:Siemens:SimaticHMI,你可以在连接成功后通过Session获取它的索引:

var namespaceIndex = session.NamespaceUris.FindIndex("urn:Siemens:SimaticHMI");

如果不确定命名空间字符串,可以先遍历所有命名空间:

for (int i = 0; i < session.NamespaceUris.Count; i++)
{
    Console.WriteLine($"索引{i}: {session.NamespaceUris[i]}");
}

2. 两种读取标签值的方法

方法一:通过节点路径读取

如果知道HMI标签的路径(比如Objects/Simatic HMI/TP1200/Tags/MyTag),可以用TranslateBrowsePathsToNodeIdsAsync把路径转成NodeId,再读值:

// 构造浏览路径
var browsePath = new BrowsePath(session.NamespaceUris.GetIndex("http://opcfoundation.org/UA/"), 
                               new[] { 
                                   new QualifiedName("Objects", 0),
                                   new QualifiedName("Simatic HMI", namespaceIndex),
                                   new QualifiedName("TP1200", namespaceIndex),
                                   new QualifiedName("Tags", namespaceIndex),
                                   new QualifiedName("MyTag", namespaceIndex)
                               });

// 转换路径到NodeId
var translateResult = await session.TranslateBrowsePathsToNodeIdsAsync(null, new[] { browsePath });
if (translateResult.Results[0].StatusCode.IsGood)
{
    var nodeId = translateResult.Results[0].TargetId.NodeId;
    // 读取值
    var readResult = await session.ReadValueAsync(nodeId);
    Console.WriteLine($"标签值:{readResult.Value}");
}

方法二:直接通过NodeId读取

如果已经知道标签的NodeId(比如从HMI的OPC UA配置里获取,格式一般是ns=2;s=Tags.MyTag),可以直接读:

var nodeId = new NodeId("s=Tags.MyTag", namespaceIndex); // 替换成你的标签NodeId
var value = await session.ReadValueAsync(nodeId);
Console.WriteLine($"当前值:{value.Value}");

3. 为什么根节点看不到子节点?

根节点(RootFolder)的子节点是Objects、Types、Views这些顶层节点,但UA客户端默认不会自动加载它们的子节点。如果你要浏览整个节点树,可以用BrowseAsync方法:

var browseResult = await session.BrowseAsync(null, null, ObjectIds.RootFolder, 0u, BrowseDirection.Forward, 
                                            ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object);
foreach (var reference in browseResult.References)
{
    Console.WriteLine($"根节点子节点:{reference.DisplayName.Text}");
}

不过对于HMI标签,直接用路径/ID读取比全树浏览效率高得多。

4. 封装自己的GetNodeValue方法

如果你想要类似GetNodeValue(NodeName)的方法,可以自己封装一个:

public async Task<DataValue> GetNodeValueAsync(Session session, string tagName, int namespaceIndex)
{
    var browsePath = new BrowsePath(session.NamespaceUris.GetIndex("http://opcfoundation.org/UA/"), 
                                   new[] { 
                                       new QualifiedName("Objects", 0),
                                       new QualifiedName("Simatic HMI", namespaceIndex),
                                       new QualifiedName("TP1200", namespaceIndex),
                                       new QualifiedName("Tags", namespaceIndex),
                                       new QualifiedName(tagName, namespaceIndex)
                                   });
    var translateResult = await session.TranslateBrowsePathsToNodeIdsAsync(null, new[] { browsePath });
    if (!translateResult.Results[0].StatusCode.IsGood)
        throw new Exception($"无法找到节点:{tagName}");
    return await session.ReadValueAsync(translateResult.Results[0].TargetId.NodeId);
}

调用的时候:

var tagValue = await GetNodeValueAsync(session, "MyTag", namespaceIndex);
Console.WriteLine(tagValue.Value);

内容的提问来源于stack exchange,提问作者Álvaro García

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 23:10:45