using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Opc.Ua;
using Opc.Ua.Client;
namespace Xylem.Common.Hardware.Plc.Siemens.Client.TestbenchAdapter
{
public class UAClientHelperAPI
{
#region Construction
public UAClientHelperAPI()
{
// Creats the application configuration (containing the certificate) on construction
mApplicationConfig = CreateClientConfiguration();
}
#endregion
#region Properties
///
/// Keeps a session with an UA server.
///
private Session mSession = null;
///
/// Specifies this application.
///
private ApplicationConfiguration mApplicationConfig = null;
///
/// Provides the session being established with an OPC UA server.
///
public Session Session
{
get { return mSession; }
}
///
/// Provides the event handling for server certificates.
///
public CertificateValidationEventHandler CertificateValidationNotification = null;
///
/// Provides the event for value changes of a monitored item.
///
public MonitoredItemNotificationEventHandler ItemChangedNotification = null;
///
/// Provides the event for KeepAliveNotifications.
///
public KeepAliveEventHandler KeepAliveNotification = null;
#endregion
#region Discovery
/// Finds Servers based on a discovery url
/// The discovery url
/// ApplicationDescriptionCollection containing found servers
/// Throws and forwards any exception with short error description.
public ApplicationDescriptionCollection FindServers(string discoveryUrl)
{
//Create a URI using the discovery URL
Uri uri = new Uri(discoveryUrl);
try
{
//Ceate a DiscoveryClient
DiscoveryClient client = DiscoveryClient.Create(uri);
//Find servers
//ApplicationDescriptionCollection servers = client.FindServers(null);
ApplicationDescriptionCollection servers = client.FindServers(null);
return servers;
}
catch (Exception e)
{
//handle Exception here
throw e;
}
}
public IEnumerable BrowseNode(ReferenceDescriptionCollection search)
{
throw new NotImplementedException();
}
/// Finds Endpoints based on a server's url
/// The server's url
/// EndpointDescriptionCollection containing found Endpoints
/// Throws and forwards any exception with short error description.
public EndpointDescriptionCollection GetEndpoints(string serverUrl)
{
//Create a URI using the server's URL
Uri uri = new Uri(serverUrl);
try
{
//Create a DiscoveryClient
DiscoveryClient client = DiscoveryClient.Create(uri);
//Search for available endpoints
EndpointDescriptionCollection endpoints = client.GetEndpoints(null);
return endpoints;
}
catch (Exception e)
{
//handle Exception here
throw e;
}
}
#endregion
#region Connect/Disconnect
/// Establishes the connection to an OPC UA server and creates a session using a server url.
/// The Url of the endpoint as string.
/// The security policy to use
/// The message security mode to use
/// Autheticate anonymous or with username and password
/// The user name
/// The password
/// Throws and forwards any exception with short error description.
[Obsolete("Only use if no EndpointDescription of the server's endpoint is available")]
public void Connect(string url, string secPolicy, MessageSecurityMode msgSecMode, bool userAuth, string userName, string password)
{
try
{
//Secify application configuration
ApplicationConfiguration ApplicationConfig = mApplicationConfig;
//Hook up a validator function for a CertificateValidation event
mApplicationConfig.CertificateValidator.CertificateValidation += Notificatio_CertificateValidation;
//Create EndPoint description
EndpointDescription EndpointDescription = CreateEndpointDescription(url, secPolicy, msgSecMode);
//Create EndPoint configuration
EndpointConfiguration EndpointConfiguration = EndpointConfiguration.Create(ApplicationConfig);
//Create an Endpoint object to connect to server
ConfiguredEndpoint Endpoint = new ConfiguredEndpoint(null, EndpointDescription, EndpointConfiguration);
//Create anonymous user identity
UserIdentity UserIdentity;
if (userAuth)
{
UserIdentity = new UserIdentity(userName, password);
}
else
{
UserIdentity = new UserIdentity();
}
//Update certificate store before connection attempt
ApplicationConfig.CertificateValidator.Update(ApplicationConfig);
//Create and connect session
mSession = Session.Create(
ApplicationConfig,
Endpoint,
true,
"MySession",
60000,
UserIdentity,
null
);
mSession.KeepAlive += new KeepAliveEventHandler(Notification_KeepAlive);
}
catch (Exception e)
{
//handle Exception here
throw e;
}
}
/// Establishes the connection to an OPC UA server and creates a session using an EndpointDescription.
/// The EndpointDescription of the server's endpoint
/// Autheticate anonymous or with username and password
/// The user name
/// The password
/// Throws and forwards any exception with short error description.
public void Connect(EndpointDescription endpointDescription, bool userAuth, string userName, string password)
{
try
{
//Secify application configuration
ApplicationConfiguration ApplicationConfig = mApplicationConfig;
//Hook up a validator function for a CertificateValidation event
ApplicationConfig.CertificateValidator.CertificateValidation += Notificatio_CertificateValidation;
//Create EndPoint configuration
EndpointConfiguration EndpointConfiguration = EndpointConfiguration.Create(ApplicationConfig);
//Connect to server and get endpoints
ConfiguredEndpoint mEndpoint = new ConfiguredEndpoint(null, endpointDescription, EndpointConfiguration);
//Create the binding factory.
BindingFactory bindingFactory = BindingFactory.Create(mApplicationConfig, ServiceMessageContext.GlobalContext);
//Creat a session name
String sessionName = "MySession";
//Create user identity
UserIdentity UserIdentity;
if (userAuth)
{
UserIdentity = new UserIdentity(userName, password);
}
else
{
UserIdentity = new UserIdentity();
}
//Update certificate store before connection attempt
ApplicationConfig.CertificateValidator.Update(ApplicationConfig);
//Create and connect session
mSession = Session.Create(
ApplicationConfig,
mEndpoint,
true,
sessionName,
60000,
UserIdentity,
null
);
mSession.KeepAlive += new KeepAliveEventHandler(Notification_KeepAlive);
}
catch (Exception e)
{
//handle Exception here
throw e;
}
}
/// Closes an existing session and disconnects from the server.
/// Throws and forwards any exception with short error description.
public void Disconnect()
{
// Close the session.
try
{
mSession.Close(10000);
mSession.Dispose();
}
catch (Exception e)
{
//handle Exception here
throw e;
}
}
#endregion
#region Browse
/// Browses the root folder of an OPC UA server.
/// ReferenceDescriptionCollection of found nodes
/// Throws and forwards any exception with short error description.
public ReferenceDescriptionCollection BrowseRoot()
{
//Create a collection for the browse results
ReferenceDescriptionCollection referenceDescriptionCollection;
//Create a continuationPoint
byte[] continuationPoint;
try
{
//Browse the RootFolder for variables, objects and methods
mSession.Browse(null, null, ObjectIds.RootFolder, 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out continuationPoint, out referenceDescriptionCollection);
return referenceDescriptionCollection;
}
catch (Exception e)
{
//handle Exception here
throw e;
}
}
/// Browses a node ID provided by a ReferenceDescription
/// The ReferenceDescription
/// ReferenceDescriptionCollection of found nodes
/// Throws and forwards any exception with short error description.
public ReferenceDescriptionCollection BrowseNode(ReferenceDescription refDesc)
{
//Create a collection for the browse results
ReferenceDescriptionCollection referenceDescriptionCollection;
ReferenceDescriptionCollection nextreferenceDescriptionCollection;
//Create a continuationPoint
byte[] continuationPoint;
byte[] revisedContinuationPoint;
//Create a NodeId using the selected ReferenceDescription as browsing starting point
NodeId nodeId = ExpandedNodeId.ToNodeId(refDesc.NodeId, null);
try
{
//Browse from starting point for all object types
mSession.Browse(null, null, nodeId, 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, 0, out continuationPoint, out referenceDescriptionCollection);
while (continuationPoint != null)
{
mSession.BrowseNext(null, false, continuationPoint, out revisedContinuationPoint, out nextreferenceDescriptionCollection);
referenceDescriptionCollection.AddRange(nextreferenceDescriptionCollection);
continuationPoint = revisedContinuationPoint;
}
return referenceDescriptionCollection;
}
catch (Exception e)
{
//handle Exception here
throw e;
}
}
#endregion
#region Subscription
/// Creats a Subscription object to a server
/// The publishing interval
/// Subscription
/// Throws and forwards any exception with short error description.
public Subscription Subscribe(int publishingInterval)
{
//Create a Subscription object
Subscription subscription = new Subscription(mSession.DefaultSubscription);
//Enable publishing
subscription.PublishingEnabled = true;
//Set the publishing interval
subscription.PublishingInterval = publishingInterval;
//Add the subscription to the session
mSession.AddSubscription(subscription);
try
{
//Create/Activate the subscription
subscription.Create();
return subscription;
}
catch (Exception e)
{
//handle Exception here
throw e;
}
}
/// Ads a monitored item to an existing subscription
/// The subscription
/// The node Id as string
/// The name of the item to add
/// The sampling interval
/// The added item
/// Throws and forwards any exception with short error description.
public MonitoredItem AddMonitoredItem(Subscription subscription, string nodeIdString, string itemName, int samplingInterval)
{
//Create a monitored item
MonitoredItem monitoredItem = new MonitoredItem();
//Set the name of the item for assigning items and values later on; make sure item names differ
monitoredItem.DisplayName = itemName;
//Set the NodeId of the item
monitoredItem.StartNodeId = nodeIdString;
//Set the attribute Id (value here)
monitoredItem.AttributeId = Attributes.Value;
//Set reporting mode
monitoredItem.MonitoringMode = MonitoringMode.Reporting;
//Set the sampling interval (1 = fastest possible)
monitoredItem.SamplingInterval = samplingInterval;
//Set the queue size
monitoredItem.QueueSize = 1;
//Discard the oldest item after new one has been received
monitoredItem.DiscardOldest = true;
//Define event handler for this item and then add to monitoredItem
monitoredItem.Notification += new MonitoredItemNotificationEventHandler(Notification_MonitoredItem);
try
{
//Add the item to the subscription
subscription.AddItem(monitoredItem);
//Apply changes to the subscription
subscription.ApplyChanges();
return monitoredItem;
}
catch (Exception e)
{
//handle Exception here
throw e;
}
}
/// Removs a monitored item from an existing subscription
/// The subscription
/// The item
/// Throws and forwards any exception with short error description.
public MonitoredItem RemoveMonitoredItem(Subscription subscription, MonitoredItem monitoredItem)
{
try
{
//Add the item to the subscription
subscription.RemoveItem(monitoredItem);
//Apply changes to the subscription
subscription.ApplyChanges();
return null;
}
catch (Exception e)
{
//handle Exception here
throw e;
}
}
/// Removes an existing Subscription
/// The subscription
/// Throws and forwards any exception with short error description.
public void RemoveSubscription(Subscription subscription)
{
try
{
//Delete the subscription and all items submitted
subscription.Delete(true);
}
catch (Exception e)
{
//handle Exception here
throw e;
}
}
#endregion
#region Read/Write
/// Reads a node by node Id
/// The node Id as string
/// The read node
/// Throws and forwards any exception with short error description.
public Node ReadNode(String nodeIdString)
{
//Create a nodeId using the identifier string
NodeId nodeId = new NodeId(nodeIdString);
//Create a node
Node node = new Node();
try
{
//Read the dataValue
node = mSession.ReadNode(nodeId);
return node;
}
catch (Exception e)
{
//handle Exception here
throw e;
}
}
/// Reads values from node Ids
/// The node Ids as strings
/// The read values as strings
/// Throws and forwards any exception with short error description.
public object ReadValue(string nodeIdStrings)
{
List nodeIds = new List();
List types = new List();
List