Closed zxzkf1992 closed 5 years ago
@zxzkf1992 I don't think that anyone tried this before but as IL2CPP can utilize .NetStandard 2.0 it should work.
@MD-V thanks for your reply. I have tried it yesterday. It works in Unity Editor, but not in HoloLens, there will give more than one error.
@zxzkf1992 Can you give more details about the error?
@MD-V Here is the error message given by HoloLens.
System.AggregateException: One or more errors occurred. --> System.UnauthorizedAccessException: Failed gettingthe path of a special folder: Access Denied. at System.Environment.GetFolderPath(System.Environment+SpecialFolder folder) at Opc.Ua.Utils.ReplaceSpecialFolderNames(System.Stringinput)
@zxzkf1992
Please check if the directories you configured for CertificateManagement in the ApplicationConfiguration are existing (and accessible) on the HoloLens and edit your ApplicationConfiguration to point to paths where your program has access to...
The properties you need to check are: ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath ApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath ApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StorePath ApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StorePath
@MD-V This program is rewritten on the NetCore Console Client sample. The code for my ApplicationConfiguration is as follows. There is no error running on Unity. Is it possible that this directory is not in HoloLens?
var config = new ApplicationConfiguration()
{
ApplicationName = "OpcUA-Test",
ApplicationUri = Utils.Format(@"urn:{0}:OpcUA-Test", Dns.GetHostName()),
ApplicationType = ApplicationType.Client,
SecurityConfiguration = new SecurityConfiguration
{
ApplicationCertificate = new CertificateIdentifier { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\MachineDefault", SubjectName = Utils.Format(@"CN={0}, DC={1}", "OpcUA-Test", Dns.GetHostName()) },
TrustedIssuerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Certificate Authorities" },
TrustedPeerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Applications" },
RejectedCertificateStore = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\RejectedCertificates" },
AutoAcceptUntrustedCertificates = true,
AddAppCertToTrustedStore = true
},
TransportConfigurations = new TransportConfigurationCollection(),
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 },
TraceConfiguration = new TraceConfiguration()
};
It works on Unity because you are running on standard windows and %CommonApplicationData% exists. I think you cannot use %CommonApplicationData% on HoloLens. You'll have to change this paths!
@MD-V I´m very new for the OPC UA. I don't understand the settings of ApplicationConfiguration. I have a problem now, this applicationConfiguraion I have to set up in the Client, or has been set up in the OPC UA library, I can call directly? Because in the NetCoreClient sample i don't see the code to set the ApplicaitonConfiguration.
Thank you very much for your patience.
You have to set the config up in the client. You can do it two ways: programmaticaly or load from an xml (see)
After loading the configuration you can adjust its values or you edit the xml file directly.
EDIT:
A little example (taken from .NetCoreConsoleClient, paths are just examples you will have to choose matching paths for the HoloLens)
ApplicationConfiguration config = await application.LoadApplicationConfiguration(false); config.SecurityConfiguration.ApplicationCertificate.StoreLocation = "./OPC Foundation/pki/own"; config.SecurityConfiguration.TrustedIssuerCertificates.StoreLocation = "./OPC Foundation/pki/issue"; config.SecurityConfiguration.TrustedPeerCertificates.StoreLocation = "./OPC Foundation/pki/trusted"; config.SecurityConfiguration.RejectedCertificateStore.StoreLocation = "./OPC Foundation/pki/rejected";
@MD-V Hello, I modified the code yesterday, set the path to the local folder of HoloLens, and now fix the problem of ApplicaitonConfiguration. But now the following error has occurred, is it because OPC UA still only supports Mono, but not IL2CPP?
System.TypeInitializationException: The type initializer for `Opc.UaServiceMessageContext' threw an exception.--->System.TypeInitializationException: The type initializer for ´Opc.Ua.EncodeableFactory' threw an exception.---> System.MissingMethodException: Default constructor not found for type Opc.Ua.Argument at system.RuntimeType.CreateInsatanceMono(System.Boolean nonPublic).
@zxzkf1992 Are you running with Release or Debug build on the HoloLens?
@MD-V yes, runing with Release build on the HoloLens
@zxzkf1992 Can you try running it with Debug? It seems that IL2CPP strips the ctor for Opc.Ua.Argument because its only used via Reflection...
@MD-V I just tried debug build on HoloLens and it has the same error as release build.
@zxzkf1992 Okay, i'm currently out of ideas. Is it possible for you to upload your project to github? We have a HoloLens so we could try to get it working.
@MD-V Ok, I can upload this project to GitHub, or can I package the project directly into a ZIP file and send it to you via email? You also have HoloLens, which sounds great. Have you tried using the OPC UA .Net standard library on HoloLens to connect to the OPC UA server?
@zxzkf1992 I don't like to post my mail address publicly here. How can I contact you?
@MD-V Sorry, I didn't think about it. I just created a new email address, you can send an email to this address awhujx25806@chacuo.net, so I will send the project to you.
@MD-V Hello, can you send an email to this address? I haven't received it until now. If you don't want to send an email, I uploaded my project to Google drive. I can share this link for you.
@zxzkf1992 I have sent one yesterday evening and another one just now. Can you please check again?
@zxzkf1992
Hello,
the problem is indeed the compilation with IL2CPP.
IL2CPP only emits code to C++ that is actually called (see here ).
The EncodableFactory of OPC UA uses Reflection to add all system types (see here and here).
So the default constructors for e.g. Opc.UA.Argument are never called explicitly and thereby not emitted by IL2CPP.
A workaround could be that you call all the default constructors of all IEncodable datatypes (there are unfortunately many!) explicitly in your code. It could look like this:
public async Task OpcUa_Connector()
{
// Add the default constructors of all IEncodable Types here
var argument = new Opc.Ua.Argument();
var enumValue = new Opc.Ua.EnumValueType();
....
....
....
//Get the HoloLens local folder address
Class1 dll = new Class1();
dll.CreatFolder();
string folderPath = dll.FolderPath;
//StorageFolder folder = ApplicationData.Current.LocalFolder;
//string folderpath = folder.Path;
//string filepath = folderpath + "";
//folder.CreateFolderAsync(folder_Name, CreationCollisionOption.ReplaceExisting);
//OpcUA Client
//create the application configuration
//work on HoloLens
var config = new ApplicationConfiguration()
{
ApplicationName = "OpcUA-Test",
I hope this helps.
EDIT:
You can also provide a link.xml and include Opc.Ua.Core. So IL2CPP will not strip the constructors...
See here: https://docs.unity3d.com/Manual/IL2CPP-BytecodeStripping.html
link.xml
<linker>
<assembly fullname="Opc.Ua.Core" preserve="all"/>
</linker>
Hi, i have the exact same issue. @zxzkf1992 would you mind sharing your OpcUa-Client? I would be really thankfull. Kind Regards Stefan
@MD-V thanks for the fast reply.
I allready created a link.xml in the assets folder.
`
`
The only thing i'm not shure about is which directory i must use instead of %CommonApplicationData%.
@Boehm92
Currently dont have a HoloLens here. Just use any path where you have write access to. e.g.: Path.GetFullPath(Windows.Storage.ApplicationData.Current.LocalFolder.Path)
@Boehm92 sorry, i replied to you so late. Because Application running on HoloLens is real UWP. So setting the Application directory must follow the UWP rules. You can search for how to set the path of the UWP application.
So, i created the link.xml file and also exchanged the directory from %CommonApplicationData% to %userprofile%. The code is working if i use the %CommonApplicationData% directory in the unity editor. But even if i change it to %userprofile% and load it to the hololens as release build it won't work. Following is the code. I'm really thankfull for any help because i try to establish a working opc ua communication via hololens for 3 weeks now and i think i nearly got it.
public void SubscripeToOpcUaServer(string OpcUaEndpoint, List
var config = new ApplicationConfiguration()
{
ApplicationName = "OpcUaClientconifg",
ApplicationUri = Utils.Format(@"urn:{0}:OpcUaClient", System.Net.Dns.GetHostName()),
ApplicationType = ApplicationType.Client,
SecurityConfiguration = new SecurityConfiguration
{
ApplicationCertificate = new CertificateIdentifier { StoreType = @"Directory", StorePath = @"%userprofile%\OPC Foundation\CertificateStores\MachineDefault", SubjectName = Utils.Format(@"CN={0}, DC={1}", "MyHomework", System.Net.Dns.GetHostName()) },
TrustedIssuerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%userprofile%\OPC Foundation\CertificateStores\UA Certificate Authorities" },
TrustedPeerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%userprofile%\OPC Foundation\CertificateStores\UA Applications" },
RejectedCertificateStore = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%userprofile%\OPC Foundation\CertificateStores\RejectedCertificates" },
AutoAcceptUntrustedCertificates = true,
AddAppCertToTrustedStore = true,
RejectSHA1SignedCertificates = false,
MinimumCertificateKeySize = 1024
//ApplicationCertificate = new CertificateIdentifier { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\MachineDefault", SubjectName = Utils.Format(@"CN={0}, DC={1}", "MyHomework", System.Net.Dns.GetHostName()) },
//TrustedIssuerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Certificate Authorities" },
//TrustedPeerCertificates = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\UA Applications" },
//RejectedCertificateStore = new CertificateTrustList { StoreType = @"Directory", StorePath = @"%CommonApplicationData%\OPC Foundation\CertificateStores\RejectedCertificates" },
//AutoAcceptUntrustedCertificates = true,
//AddAppCertToTrustedStore = true,
//RejectSHA1SignedCertificates = false,
//MinimumCertificateKeySize = 1024
},
TransportConfigurations = new TransportConfigurationCollection(),
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 },
TraceConfiguration = new TraceConfiguration()
};
config.Validate(ApplicationType.Client).GetAwaiter().GetResult();
if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
{
config.CertificateValidator.CertificateValidation += (s, e) => { e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted); };
}
var application = new ApplicationInstance
{
ApplicationName = "OpcUaClient",
ApplicationType = ApplicationType.Client,
ApplicationConfiguration = config
};
application.CheckApplicationInstanceCertificate(false, 2048).GetAwaiter().GetResult();
var selectedEndpoint = CoreClientUtils.SelectEndpoint(OpcUaEndpoint, useSecurity: false, operationTimeout: 15000); //"opc.tcp://141.60.104.13:4840"
session = Session.Create(config, new ConfiguredEndpoint(null, selectedEndpoint, EndpointConfiguration.Create(config)), false, "", 60000, null, null).GetAwaiter().GetResult();
{
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);
foreach (var rd in refs)
{
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);
}
var subscription = new Subscription(session.DefaultSubscription) { PublishingInterval = 1000 };
list = new List<MonitoredItem>();
foreach (var item in NoteIdList)
{
var monitoredItem = new MonitoredItem(subscription.DefaultItem)
{
StartNodeId = item
};
list.Add(monitoredItem);
}
subscription.AddItems(list);
session.AddSubscription(subscription);
subscription.Create();
}
}
@Boehm92 Please resolve the paths to full paths before using them e.g.
appCertPath = Environment.ExpandEnvironmentVariables(@"%userprofile%\OPC Foundation\CertificateStores\MachineDefault");
ApplicationCertificate = new CertificateIdentifier { StoreType = @"Directory", StorePath = appCertPath , SubjectName = Utils.Format(@"CN={0}, DC={1}", "MyHomework", System.Net.Dns.GetHostName()) },
EDIT: Please also make sure you have write access to the path you are using!
@MD-V thank you very much for your support What i did so far:
Environment.ExpandEnvironmentVariables
with the directorys from this link https://www.youtube.com/watch?v=Nk9l2knWTko&t=277sNullReferenceException: Object reference not set to an instance of an objectOpcUaCom.Update () (at Assets/Scripts/OpcUaCom.cs:33)
I get the same exception in the unity editor with these directory, but if change it to the %CommonApplicationData%-Directory the opc ua communication is working fine.Next thing i will try is to use the approach of the link https://stackoverflow.com/questions/44014883/creating-txt-file-on-hololens from MD-V If someone else has another idea i would be realy happy about to hear it
@zxzkf1992 it would be gread if you could post your directorys
Thanks again for the support
EDIT: i used the directory _appCertPath = Path.Combine(Application.persistentDataPath, "/OPC Foundation/CertificateStores/MachineDefault");
but still the same exception. I will change my approach to restfull api. If anyone get a working approach for an hololens opc ua client please let me know
Hello @zxzkf1992 ! I am trying to also connect to a server with Hololens via opc ua communcation. Would it be possible to share your code where you had to make changes to work in Hololens? The email is anneafutko@gmail.com .
I am developing a UWP application that allows HoloLens to connect to the OPC UA server. So I want to confirm, is the current version of UA .Net Standard now supporting Unity IL2CPP scripting backend, or can it only support .Net/Mono scripting backend?
I hope someone can reply to me as soon as possible. This question is very important to me, thanks a lot.