/* ========================================================================
* Copyright (c) 2005-2020 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* The complete license agreement can be found here:
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Collections;
using Opc.Ua;
using Opc.Ua.Client;
namespace Quickstarts.ConsoleReferenceClient
{
///
/// OPC UA Client with examples of basic functionality.
///
internal class UAClient
{
#region Private Fields
private readonly IOutput m_output;
private readonly Action m_validateResponse;
private ApplicationConfiguration m_configuration;
private Session m_session;
#endregion Private Fields
#region Public Constructors
///
/// Initializes a new instance of the UAClient class.
///
public UAClient(ApplicationConfiguration configuration, IOutput output, Action validateResponse)
{
m_validateResponse = validateResponse;
m_output = output;
m_configuration = configuration;
m_configuration.CertificateValidator.CertificateValidation += CertificateValidation;
}
#endregion Public Constructors
#region Public Events
///
/// Evento notifica variazione MonitoredItem
///
public event EventHandler eh_MonItChange;
#endregion Public Events
#region Public Properties
///
/// Gets or sets the server URL.
///
public string ServerUrl { get; set; } = "opc.tcp://localhost:62541/Quickstarts/ReferenceServer";
///
/// Gets the client session.
///
public Session Session => m_session;
#endregion Public Properties
#region Private Methods
///
/// Handles the certificate validation event.
/// This event is triggered every time an untrusted certificate is received from the server.
///
private void CertificateValidation(CertificateValidator sender, CertificateValidationEventArgs e)
{
bool certificateAccepted = true;
// ****
// Implement a custom logic to decide if the certificate should be
// accepted or not and set certificateAccepted flag accordingly.
// The certificate can be retrieved from the e.Certificate field
// ***
ServiceResult error = e.Error;
while (error != null)
{
m_output.WriteLine(error);
error = error.InnerResult;
}
if (certificateAccepted)
{
m_output.WriteLine("Untrusted Certificate accepted. SubjectName = {0}", e.Certificate.SubjectName);
}
e.AcceptAll = certificateAccepted;
}
///
/// Handle DataChange notifications from Server
///
private void OnMonitoredItemNotification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
{
try
{
// Log MonitoredItem Notification event
MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification;
// sollevo evento notifica vaziazione MonitoredItem
if (eh_MonItChange != null)
{
eh_MonItChange(this, new opcUaMonitItemChange(monitoredItem, notification));
}
m_output.WriteLine("Notification Received for Variable \"{0}\" and Value = {1}.", monitoredItem.DisplayName, notification.Value);
}
catch (Exception ex)
{
m_output.WriteLine("OnMonitoredItemNotification error: {0}", ex.Message);
}
}
#endregion Private Methods
#region Public Methods
///
/// Browse Server nodes
///
public Dictionary Browse(string fullConf)
{
Dictionary nodeIdNameList = new Dictionary();
if (m_session == null || m_session.Connected == false)
{
m_output.WriteLine("Session not connected!");
return nodeIdNameList;
}
try
{
// Create a Browser object
Browser browser = new Browser(m_session);
// Set browse parameters
browser.BrowseDirection = BrowseDirection.Forward;
browser.NodeClassMask = (int)NodeClass.Object | (int)NodeClass.Variable;
browser.ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences;
//NodeId nodeToBrowse = ObjectIds.Server;
//NodeId nodeToBrowse = new NodeId("ns=4,i=5001");
NodeId nodeToBrowse = new NodeId(fullConf);
// Call Browse service
m_output.WriteLine("Browsing {0} node...", nodeToBrowse);
ReferenceDescriptionCollection browseResults = browser.Browse(nodeToBrowse);
// Display the results
m_output.WriteLine("Browse returned {0} results:", browseResults.Count);
foreach (ReferenceDescription result in browseResults)
{
m_output.WriteLine($" NodeId = {result.NodeId}, DisplayName = {result.DisplayName.Text}, NodeClass = {result.NodeClass}, Others: {result.BinaryEncodingId} | {result.BrowseName}");
nodeIdNameList.Add(result.NodeId.ToString(), result.DisplayName.Text);
}
}
catch (Exception ex)
{
// Log Error
m_output.WriteLine($"Browse Error : {ex.Message}.");
}
return nodeIdNameList;
}
///
/// Browse Server nodes
///
public Dictionary Browse(ushort startNodeNS, uint startNodeVal)
{
Dictionary nodeIdNameList = new Dictionary();
if (m_session == null || m_session.Connected == false)
{
m_output.WriteLine("Session not connected!");
return nodeIdNameList;
}
try
{
// Create a Browser object
Browser browser = new Browser(m_session);
// Set browse parameters
browser.BrowseDirection = BrowseDirection.Forward;
browser.NodeClassMask = (int)NodeClass.Object | (int)NodeClass.Variable;
browser.ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences;
//NodeId nodeToBrowse = ObjectIds.Server;
//NodeId nodeToBrowse = new NodeId("ns=4,i=5001");
NodeId nodeToBrowse = new NodeId(startNodeVal, startNodeNS);
// Call Browse service
m_output.WriteLine("Browsing {0} node...", nodeToBrowse);
ReferenceDescriptionCollection browseResults = browser.Browse(nodeToBrowse);
// Display the results
m_output.WriteLine("Browse returned {0} results:", browseResults.Count);
foreach (ReferenceDescription result in browseResults)
{
m_output.WriteLine($" NodeId = {result.NodeId}, DisplayName = {result.DisplayName.Text}, NodeClass = {result.NodeClass}, Others: {result.BinaryEncodingId} | {result.BrowseName}");
nodeIdNameList.Add(result.NodeId.ToString(), result.DisplayName.Text);
}
}
catch (Exception ex)
{
// Log Error
m_output.WriteLine($"Browse Error : {ex.Message}.");
}
return nodeIdNameList;
}
///
/// Call UA method
///
public void CallMethod()
{
if (m_session == null || m_session.Connected == false)
{
m_output.WriteLine("Session not connected!");
return;
}
try
{
// Define the UA Method to call
// Parent node - Objects\CTT\Methods
// Method node - Objects\CTT\Methods\Add
NodeId objectId = new NodeId("ns=2;s=Methods");
NodeId methodId = new NodeId("ns=2;s=Methods_Add");
// Define the method parameters
// Input argument requires a Float and an UInt32 value
object[] inputArguments = new object[] { (float)10.5, (uint)10 };
IList