C# 通过Unity3D创建OPC UA客户端

C# 通过Unity3D创建OPC UA客户端,c#,unity3d,opc-ua,C#,Unity3d,Opc Ua,实际上曾经问过我这个问题,但似乎没有人给我预期的答案:( 我试图在Unity3D中创建一个OPC UA客户端。更具体地说,它类似于:一个只有文本的简单场景。该文本显示从OPC UA服务器读取的变量值。 我添加了这段代码(在stackoverflow上找到),但它不起作用 using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using Opc.Ua; using

实际上曾经问过我这个问题,但似乎没有人给我预期的答案:( 我试图在Unity3D中创建一个OPC UA客户端。更具体地说,它类似于:一个只有文本的简单场景。该文本显示从OPC UA服务器读取的变量值。 我添加了这段代码(在stackoverflow上找到),但它不起作用

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using Opc.Ua; 
using Opc.Ua.Client;
using Opc.Ua.Configuration;

public class main : MonoBehaviour
{

private async void Start()
{
    Console.WriteLine("Step 1 - Create a config.");
    var config = new ApplicationConfiguration()
    {
        ApplicationName = "test-opc",
        ApplicationType = ApplicationType.Client,
        SecurityConfiguration = new SecurityConfiguration { ApplicationCertificate = new CertificateIdentifier() },
        TransportConfigurations = new TransportConfigurationCollection(),
        TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
        ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
    };
    await config.Validate(ApplicationType.Client);
    if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
    {
        config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted); };
    }

    Console.WriteLine("Step 2 - Create a session with your server.");
    using (var session = await Session.Create(config, new ConfiguredEndpoint(null, new EndpointDescription("opc.tcp://localhost:4841")), true, "", 60000, null, null))
    {
        Console.WriteLine("Step 3 - Browse the server namespace.");
        ReferenceDescriptionCollection refs;
        byte[] cp;
        session.Browse(null, null, ObjectIds.ObjectsFolder, 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out cp, out refs);
        Console.WriteLine("DisplayName: BrowseName, NodeClass");
        foreach (var rd in refs)
        {
            Console.WriteLine(rd.DisplayName + ": " + rd.BrowseName + ", " + rd.NodeClass);
            ReferenceDescriptionCollection nextRefs;
            byte[] nextCp;
            session.Browse(null, null, ExpandedNodeId.ToNodeId(rd.NodeId, session.NamespaceUris), 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out nextCp, out nextRefs);
            foreach (var nextRd in nextRefs)
            {
                Console.WriteLine("+ " + nextRd.DisplayName + ": " + nextRd.BrowseName + ", " + nextRd.NodeClass);
            }
        }

        Console.WriteLine("Step 4 - Create a subscription. Set a faster publishing interval if you wish.");
        var subscription = new Subscription(session.DefaultSubscription) { PublishingInterval = 1000 };

        Console.WriteLine("Step 5 - Add a list of items you wish to monitor to the subscription.");
        var list = new List<MonitoredItem> {
            new MonitoredItem(subscription.DefaultItem) { DisplayName = "aaatime", StartNodeId = "i=10004" } };
        list.ForEach(i => i.Notification += OnNotification);
        subscription.AddItems(list);

        Console.WriteLine("Step 6 - Add the subscription to the session.");
        session.AddSubscription(subscription);
        subscription.Create();

        Console.WriteLine("Finished client initialization");
    }
}

private static void OnNotification(MonitoredItem item, MonitoredItemNotificationEventArgs e)
{
    foreach (var value in item.DequeueValues())
    {
        Console.WriteLine("{0}: {1}, {2}, {3}", item.DisplayName, value.Value, value.SourceTimestamp, value.StatusCode);
    }
}
}
使用系统集合;
使用System.Collections.Generic;
使用UnityEngine;
使用制度;
使用Opc.Ua;
使用Opc.Ua.Client;
使用Opc.Ua.Configuration;
公共课主要内容:单一行为
{
私有异步void Start()
{
WriteLine(“步骤1-创建配置”);
var config=新应用程序配置()
{
ApplicationName=“测试opc”,
ApplicationType=ApplicationType.Client,
SecurityConfiguration=new SecurityConfiguration{ApplicationCertificate=new CertificateIdentifier()},
TransportConfigurations=新的TransportConfigurationCollection(),
TransportQuotas=新的TransportQuotas{OperationTimeout=15000},
ClientConfiguration=new ClientConfiguration{DefaultSessionTimeout=60000}
};
等待config.Validate(ApplicationType.Client);
if(config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
{
config.CertificateValidator.CertificateValidation+=(s,e)=>{e.Accept=(e.Error.StatusCode==StatusCodes.BadCertificateUntrusted);};
}
WriteLine(“第2步-创建与服务器的会话”);
使用(var session=await session.Create(配置,新配置的数据点(null,新端点描述(“opc”)。tcp://localhost:4841“”),真“”,60000,空,空)
{
WriteLine(“步骤3-浏览服务器名称空间”);
参考描述集合参考;
字节[]cp;
session.Browse(null,null,objectId.ObjectsFolder,0u,browsedDirection.Forward,ReferenceTypeId.HierarchicalReferences,true,(uint)NodeClass.Variable |(uint)NodeClass.Object |(uint)NodeClass.Method,out cp,out refs);
Console.WriteLine(“显示名称:BrowseName,NodeClass”);
foreach(参考文献中的变量rd)
{
Console.WriteLine(rd.DisplayName+“:“+rd.BrowseName+”,“+rd.NodeClass);
参考描述集合的下一步;
字节[]nextCp;
session.Browse(null,null,ExpandedNodeId.ToNodeId(rd.NodeId,session.NamespaceUris),0u,browsedDirection.Forward,referenceTypeId.HierarchicalReferences,true,(uint)NodeClass.Variable |(uint)NodeClass.Object |(uint)NodeClass.Method,out-nextCp,out-nextRefs);
foreach(nextRefs中的var nextRd)
{
Console.WriteLine(“+”+nextRd.DisplayName+”:“+nextRd.BrowseName+”,“+nextRd.NodeClass”);
}
}
WriteLine(“第4步-创建订阅。如果愿意,请设置更快的发布间隔。”);
var subscription=新订阅(session.DefaultSubscription){PublishingInterval=1000};
WriteLine(“第5步-向订阅中添加要监视的项目列表”);
变量列表=新列表{
新的MonitoredItem(subscription.DefaultItem){DisplayName=“aaatime”,StartNodeId=“i=10004”};
list.ForEach(i=>i.Notification+=OnNotification);
订阅。附加项(列表);
WriteLine(“步骤6-将订阅添加到会话中”);
会话.添加订阅(订阅);
subscription.Create();
Console.WriteLine(“完成客户端初始化”);
}
}
私有静态void OnNotification(MonitoredItem项,MonitoredItemNotificationEventArgs e)
{
foreach(item.DequeueValues()中的var值)
{
WriteLine(“{0}:{1},{2},{3}”,item.DisplayName,value.value,value.SourceTimestamp,value.StatusCode);
}
}
}
按照我的预期,它会是这样的:当我按下Play时,Unity应用程序运行并连接到我的OPC UA服务器,然后,它从服务器读取变量的值,并以文本形式显示该值。所以我要做的是创建一个Unity项目->场景->画布->文本,一个C脚本(上面的代码)。但是,当我将脚本添加到画布时,会出现如下通知:无法添加脚本,请确保没有编译器错误,并且文件名和类名匹配。我想我已经检查了所有这些,但没有任何错误。
你能为我的问题提出一些解决方案吗?

P/S:代码来自此线程:

一种解决方案是,如果您不熟悉opc ua,可以启动opc ua客户端并发出REST请求。这可以通过使用类似Konektilo()的opc ua到REST转换器和unity()的REST客户端来实现


我还体验到,一些opc ua客户端并不是在所有可以运行unity应用程序的平台上工作。

我创建了一个适用于unity的opc ua客户端,示例来自

但我也喜欢@M.List和他的Rest OPC UA网关的想法,因为unity有自己的Rest通信库

但是,如果您需要使用opc ua,请在下面简要说明如何在我的项目中运行它 我首先在visual studio中的一个普通控制台应用程序中尝试了该示例。测试成功后,我将控制台应用程序的所有dll复制到unity中自己创建的插件文件夹中。如果在unity项目中创建一个名为plugins的文件夹,则可以将unity Autonomy包含的dll放入项目中以供使用。您需要所有这些dll 之后,我用示例中的代码创建了一个脚本“opcUaClient”。Unity的启动方法是示例的主要方法,更新方法是OnNotification方法 到目前为止,我只能在按下play按钮时在unity中运行这个客户端。我无法将它部署到android或hololens

但最简单的方法是从unity asset store中的games4automation下载OPC UA客户端。我试过了,效果很好

雷加