mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-17 05:11:13 +08:00
319 lines
13 KiB
C#
319 lines
13 KiB
C#
/* Copyright (c) 1996-2016, OPC Foundation. All rights reserved.
|
|
The source code in this file is covered under a dual-license scenario:
|
|
- RCL: for OPC Foundation members in good-standing
|
|
- GPL V2: everybody else
|
|
RCL license terms accompanied with this source code. See http://opcfoundation.org/License/RCL/1.00/
|
|
GNU General Public License as published by the Free Software Foundation;
|
|
version 2 of the License are accompanied with this source code. See http://opcfoundation.org/License/GPLv2
|
|
This source code is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Mono.Options;
|
|
using Opc.Ua;
|
|
using Opc.Ua.Client;
|
|
|
|
namespace NetCoreConsoleClient
|
|
{
|
|
public enum ExitCode : int
|
|
{
|
|
Ok = 0,
|
|
ErrorCreateApplication = 0x11,
|
|
ErrorDiscoverEndpoints = 0x12,
|
|
ErrorCreateSession = 0x13,
|
|
ErrorBrowseNamespace = 0x14,
|
|
ErrorCreateSubscription = 0x15,
|
|
ErrorMonitoredItem = 0x16,
|
|
ErrorAddSubscription = 0x17,
|
|
ErrorRunning = 0x18,
|
|
ErrorNoKeepAlive = 0x30,
|
|
ErrorInvalidCommandLine = 0x100
|
|
};
|
|
|
|
public class Program
|
|
{
|
|
static ExitCode exitCode;
|
|
|
|
public static int Main(string[] args)
|
|
{
|
|
Console.WriteLine(".Net Core OPC UA Console Client sample");
|
|
|
|
// command line options
|
|
bool showHelp = false;
|
|
int stopTimeout = Timeout.Infinite;
|
|
bool autoAccept = true;
|
|
|
|
Mono.Options.OptionSet options = new Mono.Options.OptionSet {
|
|
{ "h|help", "show this message and exit", h => showHelp = h != null },
|
|
{ "a|autoaccept", "auto accept certificates (for testing only)", a => autoAccept = a != null },
|
|
{ "t|timeout=", "the number of seconds until the client stops.", (int t) => stopTimeout = t * 1000 }
|
|
};
|
|
|
|
IList<string> extraArgs = null;
|
|
try
|
|
{
|
|
extraArgs = options.Parse(args);
|
|
if (extraArgs.Count > 1)
|
|
{
|
|
foreach (string extraArg in extraArgs)
|
|
{
|
|
Console.WriteLine("Error: Unknown option: {0}", extraArg);
|
|
showHelp = true;
|
|
}
|
|
}
|
|
}
|
|
catch (OptionException e)
|
|
{
|
|
Console.WriteLine(e.Message);
|
|
showHelp = true;
|
|
}
|
|
|
|
if (showHelp)
|
|
{
|
|
// show some app description message
|
|
Console.WriteLine(Utils.IsRunningOnMono() ?
|
|
"Usage: mono MonoConsoleClient.exe [OPTIONS] [ENDPOINTURL]" :
|
|
"Usage: dotnet NetCoreConsoleClient.dll [OPTIONS] [ENDPOINTURL]");
|
|
Console.WriteLine();
|
|
|
|
// output the options
|
|
Console.WriteLine("Options:");
|
|
options.WriteOptionDescriptions(Console.Out);
|
|
return (int)ExitCode.ErrorInvalidCommandLine;
|
|
}
|
|
|
|
string endpointURL;
|
|
if (extraArgs.Count == 0)
|
|
{
|
|
// use OPC UA .Net Sample server
|
|
endpointURL = "opc.tcp://localhost:51210/UA/SampleServer";
|
|
}
|
|
else
|
|
{
|
|
endpointURL = extraArgs[0];
|
|
}
|
|
try
|
|
{
|
|
ConsoleSampleClient(endpointURL, stopTimeout, autoAccept).Wait();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine("Exit due to Exception: {0}", e.Message);
|
|
}
|
|
|
|
return (int)exitCode;
|
|
}
|
|
|
|
public static async Task ConsoleSampleClient(string endpointURL, int timeOut, bool autoAccept)
|
|
{
|
|
Console.WriteLine("1 - Create an Application Configuration.");
|
|
exitCode = ExitCode.ErrorCreateApplication;
|
|
|
|
Utils.SetTraceOutput(Utils.TraceOutput.DebugAndFile);
|
|
var config = new ApplicationConfiguration()
|
|
{
|
|
ApplicationName = "UA Core Sample Client",
|
|
ApplicationType = ApplicationType.Client,
|
|
ApplicationUri = "urn:" + Utils.GetHostName() + ":OPCFoundation:CoreSampleClient",
|
|
SecurityConfiguration = new SecurityConfiguration
|
|
{
|
|
ApplicationCertificate = new CertificateIdentifier
|
|
{
|
|
StoreType = "X509Store",
|
|
StorePath = "CurrentUser\\My",
|
|
SubjectName = "UA Core Sample Client"
|
|
},
|
|
TrustedPeerCertificates = new CertificateTrustList
|
|
{
|
|
StoreType = "Directory",
|
|
StorePath = "OPC Foundation/CertificateStores/UA Applications",
|
|
},
|
|
TrustedIssuerCertificates = new CertificateTrustList
|
|
{
|
|
StoreType = "Directory",
|
|
StorePath = "OPC Foundation/CertificateStores/UA Certificate Authorities",
|
|
},
|
|
RejectedCertificateStore = new CertificateTrustList
|
|
{
|
|
StoreType = "Directory",
|
|
StorePath = "OPC Foundation/CertificateStores/RejectedCertificates",
|
|
},
|
|
NonceLength = 32,
|
|
AutoAcceptUntrustedCertificates = autoAccept
|
|
},
|
|
TransportConfigurations = new TransportConfigurationCollection(),
|
|
TransportQuotas = new TransportQuotas { OperationTimeout = 15000 },
|
|
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
|
|
};
|
|
|
|
await config.Validate(ApplicationType.Client);
|
|
|
|
bool haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null;
|
|
|
|
if (!haveAppCertificate)
|
|
{
|
|
Console.WriteLine(" INFO: Creating new application certificate: {0}", config.ApplicationName);
|
|
|
|
X509Certificate2 certificate = CertificateFactory.CreateCertificate(
|
|
config.SecurityConfiguration.ApplicationCertificate.StoreType,
|
|
config.SecurityConfiguration.ApplicationCertificate.StorePath,
|
|
null,
|
|
config.ApplicationUri,
|
|
config.ApplicationName,
|
|
config.SecurityConfiguration.ApplicationCertificate.SubjectName,
|
|
null,
|
|
CertificateFactory.defaultKeySize,
|
|
DateTime.UtcNow - TimeSpan.FromDays(1),
|
|
CertificateFactory.defaultLifeTime,
|
|
CertificateFactory.defaultHashSize,
|
|
false,
|
|
null,
|
|
null
|
|
);
|
|
|
|
config.SecurityConfiguration.ApplicationCertificate.Certificate = certificate;
|
|
|
|
}
|
|
|
|
haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null;
|
|
|
|
if (haveAppCertificate)
|
|
{
|
|
config.ApplicationUri = Utils.GetApplicationUriFromCertificate(config.SecurityConfiguration.ApplicationCertificate.Certificate);
|
|
|
|
if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
|
|
{
|
|
config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine(" WARN: missing application certificate, using unsecure connection.");
|
|
}
|
|
|
|
Console.WriteLine("2 - Discover endpoints of {0}.", endpointURL);
|
|
exitCode = ExitCode.ErrorDiscoverEndpoints;
|
|
var selectedEndpoint = CoreClientUtils.SelectEndpoint(endpointURL, haveAppCertificate, 15000);
|
|
Console.WriteLine(" Selected endpoint uses: {0}",
|
|
selectedEndpoint.SecurityPolicyUri.Substring(selectedEndpoint.SecurityPolicyUri.LastIndexOf('#') + 1));
|
|
|
|
Console.WriteLine("3 - Create a session with OPC UA server.");
|
|
exitCode = ExitCode.ErrorCreateSession;
|
|
var endpointConfiguration = EndpointConfiguration.Create(config);
|
|
var endpoint = new ConfiguredEndpoint(null, selectedEndpoint, endpointConfiguration);
|
|
var session = await Session.Create(config, endpoint, false, ".Net Core OPC UA Console Client", 60000, new UserIdentity(new AnonymousIdentityToken()), null);
|
|
|
|
Console.WriteLine("4 - Browse the OPC UA server namespace.");
|
|
exitCode = ExitCode.ErrorBrowseNamespace;
|
|
ReferenceDescriptionCollection references;
|
|
Byte[] continuationPoint;
|
|
|
|
references = session.FetchReferences(ObjectIds.ObjectsFolder);
|
|
|
|
session.Browse(
|
|
null,
|
|
null,
|
|
ObjectIds.ObjectsFolder,
|
|
0u,
|
|
BrowseDirection.Forward,
|
|
ReferenceTypeIds.HierarchicalReferences,
|
|
true,
|
|
(uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method,
|
|
out continuationPoint,
|
|
out references);
|
|
|
|
Console.WriteLine(" DisplayName, BrowseName, NodeClass");
|
|
foreach (var rd in references)
|
|
{
|
|
Console.WriteLine(" {0}, {1}, {2}", 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(" + {0}, {1}, {2}", nextRd.DisplayName, nextRd.BrowseName, nextRd.NodeClass);
|
|
}
|
|
}
|
|
|
|
Console.WriteLine("5 - Create a subscription with publishing interval of 1 second.");
|
|
exitCode = ExitCode.ErrorCreateSubscription;
|
|
var subscription = new Subscription(session.DefaultSubscription) { PublishingInterval = 1000 };
|
|
|
|
Console.WriteLine("6 - Add a list of items (server current time and status) to the subscription.");
|
|
exitCode = ExitCode.ErrorMonitoredItem;
|
|
var list = new List<MonitoredItem> {
|
|
new MonitoredItem(subscription.DefaultItem)
|
|
{
|
|
DisplayName = "ServerStatusCurrentTime", StartNodeId = "i="+Variables.Server_ServerStatus_CurrentTime.ToString()
|
|
}
|
|
};
|
|
list.ForEach(i => i.Notification += OnNotification);
|
|
subscription.AddItems(list);
|
|
|
|
Console.WriteLine("7 - Add the subscription to the session.");
|
|
exitCode = ExitCode.ErrorAddSubscription;
|
|
session.AddSubscription(subscription);
|
|
subscription.Create();
|
|
|
|
Console.WriteLine("8 - Running...Press Ctrl-C to exit...");
|
|
exitCode = ExitCode.ErrorRunning;
|
|
|
|
ManualResetEvent quitEvent = new ManualResetEvent(false);
|
|
try
|
|
{
|
|
Console.CancelKeyPress += (sender, eArgs) =>
|
|
{
|
|
quitEvent.Set();
|
|
eArgs.Cancel = true;
|
|
};
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
// wait for timeout or Ctrl-C
|
|
quitEvent.WaitOne(timeOut);
|
|
|
|
// return error conditions
|
|
if (session.KeepAliveStopped)
|
|
{
|
|
exitCode = ExitCode.ErrorNoKeepAlive;
|
|
return;
|
|
}
|
|
exitCode = ExitCode.Ok;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
private static void CertificateValidator_CertificateValidation(CertificateValidator validator, CertificateValidationEventArgs e)
|
|
{
|
|
Console.WriteLine("Accepted Certificate: {0}", e.Certificate.Subject);
|
|
e.Accept = (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted);
|
|
}
|
|
|
|
}
|
|
}
|