Update test client OPC-UA

This commit is contained in:
Samuele Locatelli
2021-04-28 11:11:02 +02:00
parent 5db4c690f7
commit 9b5460d32b
2 changed files with 346 additions and 251 deletions
@@ -2,7 +2,7 @@
* 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
@@ -11,7 +11,7 @@
* 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,
@@ -36,6 +36,8 @@ namespace Quickstarts.ConsoleReferenceClient
{
public static class Program
{
#region Public Methods
public static async Task Main(string[] args)
{
IOutput console = new ConsoleOutput();
@@ -54,6 +56,18 @@ namespace Quickstarts.ConsoleReferenceClient
// create the UA Client object and connect to configured server.
UAClient uaClient = new UAClient(application.ApplicationConfiguration, console, ClientBase.ValidateResponse);
console.WriteLine("Connection Format: opc.tcp://{srvUrl}:{port}");
console.WriteLine("Please enter server url (Enter for default):");
string srvUrl = Console.ReadLine();
if (!string.IsNullOrEmpty(srvUrl))
{
console.WriteLine("Please enter server port [4840]:");
string srvPort = Console.ReadLine();
srvPort = string.IsNullOrEmpty(srvPort) ? "4840" : srvPort;
uaClient.ServerUrl = $"opc.tcp://{srvUrl}:{srvPort}";
}
bool connected = await uaClient.ConnectAsync();
if (connected)
{
@@ -61,11 +75,11 @@ namespace Quickstarts.ConsoleReferenceClient
uaClient.ReadNodes();
uaClient.WriteNodes();
uaClient.Browse();
uaClient.CallMethod();
//uaClient.CallMethod();
uaClient.SubscribeToDataChanges();
// Wait for some DataChange notifications from MonitoredItems
await Task.Delay(20_000);
await Task.Delay(20_000 * 3 * 15);
uaClient.Disconnect();
}
@@ -83,5 +97,7 @@ namespace Quickstarts.ConsoleReferenceClient
console.WriteLine(ex.Message);
}
}
#endregion Public Methods
}
}
@@ -2,7 +2,7 @@
* 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
@@ -11,7 +11,7 @@
* 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,
@@ -39,9 +39,22 @@ namespace Quickstarts.ConsoleReferenceClient
/// <summary>
/// OPC UA Client with examples of basic functionality.
/// </summary>
class UAClient
internal class UAClient
{
#region Constructors
#region Private Fields
private readonly IOutput m_output;
private readonly Action<IList, IList> m_validateResponse;
private ApplicationConfiguration m_configuration;
private Session m_session;
#endregion Private Fields
#region Public Constructors
/// <summary>
/// Initializes a new instance of the UAClient class.
/// </summary>
@@ -52,21 +65,161 @@ namespace Quickstarts.ConsoleReferenceClient
m_configuration = configuration;
m_configuration.CertificateValidator.CertificateValidation += CertificateValidation;
}
#endregion
#endregion Public Constructors
#region Public Properties
/// <summary>
/// Gets the client session.
/// </summary>
public Session Session => m_session;
/// <summary>
/// Gets or sets the server URL.
/// </summary>
public string ServerUrl { get; set; } = "opc.tcp://localhost:62541/Quickstarts/ReferenceServer";
#endregion
/// <summary>
/// Gets the client session.
/// </summary>
public Session Session => m_session;
#endregion Public Properties
#region Private Methods
/// <summary>
/// Handles the certificate validation event.
/// This event is triggered every time an untrusted certificate is received from the server.
/// </summary>
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;
}
/// <summary>
/// Handle DataChange notifications from Server
/// </summary>
private void OnMonitoredItemNotification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
{
try
{
// Log MonitoredItem Notification event
MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification;
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
/// <summary>
/// Browse Server nodes
/// </summary>
public void Browse()
{
if (m_session == null || m_session.Connected == false)
{
m_output.WriteLine("Session not connected!");
return;
}
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");
// 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(" DisplayName = {0}, NodeClass = {1}", result.DisplayName.Text, result.NodeClass);
}
}
catch (Exception ex)
{
// Log Error
m_output.WriteLine($"Browse Error : {ex.Message}.");
}
}
/// <summary>
/// Call UA method
/// </summary>
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<object> outputArguments = null;
// Invoke Call service
m_output.WriteLine("Calling UAMethod for node {0} ...", methodId);
outputArguments = m_session.Call(objectId, methodId, inputArguments);
// Display results
m_output.WriteLine("Method call returned {0} output argument(s):", outputArguments.Count);
foreach (var outputArgument in outputArguments)
{
m_output.WriteLine(" OutputValue = {0}", outputArgument.ToString());
}
}
catch (Exception ex)
{
m_output.WriteLine("Method call error: {0}", ex.Message);
}
}
/// <summary>
/// Creates a session with the UA server
/// </summary>
@@ -197,15 +350,18 @@ namespace Quickstarts.ConsoleReferenceClient
{
m_output.WriteLine("Read Value = {0} , StatusCode = {1}", result.Value, result.StatusCode);
}
#endregion
#endregion Read a node by calling the Read Service
#region Read the Value attribute of a node by calling the Session.ReadValue method
// Read Server NamespaceArray
m_output.WriteLine("Reading Value of NamespaceArray node...");
DataValue namespaceArray = m_session.ReadValue(Variables.Server_NamespaceArray);
// Display the result
m_output.WriteLine($"NamespaceArray Value = {namespaceArray}");
#endregion
#endregion Read the Value attribute of a node by calling the Session.ReadValue method
}
catch (Exception ex)
{
@@ -214,6 +370,121 @@ namespace Quickstarts.ConsoleReferenceClient
}
}
/// <summary>
/// Create Subscription and MonitoredItems for DataChanges
/// </summary>
public void SubscribeToDataChanges()
{
if (m_session == null || m_session.Connected == false)
{
m_output.WriteLine("Session not connected!");
return;
}
try
{
// Create a subscription for receiving data change notifications
// Define Subscription parameters
Subscription subscription = new Subscription(m_session.DefaultSubscription);
subscription.DisplayName = "Steamware Console Subscription";
subscription.PublishingEnabled = true;
subscription.PublishingInterval = 1000;
m_session.AddSubscription(subscription);
// Create the subscription on Server side
subscription.Create();
m_output.WriteLine("New Subscription created with SubscriptionId = {0}.", subscription.Id);
// Create MonitoredItems for data changes
MonitoredItem IO_120_00_MonitoredItem = new MonitoredItem(subscription.DefaultItem);
// Int32 Node - Objects\CTT\Scalar\Simulation\Int32
IO_120_00_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_120.00");
IO_120_00_MonitoredItem.AttributeId = Attributes.Value;
IO_120_00_MonitoredItem.DisplayName = "IO_120 Variable";
IO_120_00_MonitoredItem.SamplingInterval = 1000;
IO_120_00_MonitoredItem.Notification += OnMonitoredItemNotification;
subscription.AddItem(IO_120_00_MonitoredItem);
MonitoredItem IO_120_01_MonitoredItem = new MonitoredItem(subscription.DefaultItem);
// Int32 Node - Objects\CTT\Scalar\Simulation\Int32
IO_120_01_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_120.01");
IO_120_01_MonitoredItem.AttributeId = Attributes.Value;
IO_120_01_MonitoredItem.DisplayName = "IO_120_01 Variable";
IO_120_01_MonitoredItem.SamplingInterval = 1000;
IO_120_01_MonitoredItem.Notification += OnMonitoredItemNotification;
subscription.AddItem(IO_120_01_MonitoredItem);
MonitoredItem IO_130_MonitoredItem = new MonitoredItem(subscription.DefaultItem);
// Int32 Node - Objects\CTT\Scalar\Simulation\Int32
IO_130_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_130");
IO_130_MonitoredItem.AttributeId = Attributes.Value;
IO_130_MonitoredItem.DisplayName = "IO_130 Variable";
IO_130_MonitoredItem.SamplingInterval = 1000;
IO_130_MonitoredItem.Notification += OnMonitoredItemNotification;
subscription.AddItem(IO_130_MonitoredItem);
MonitoredItem IO_135_MonitoredItem = new MonitoredItem(subscription.DefaultItem);
// Int32 Node - Objects\CTT\Scalar\Simulation\Int32
IO_135_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_135");
IO_135_MonitoredItem.AttributeId = Attributes.Value;
IO_135_MonitoredItem.DisplayName = "IO_135 Variable";
IO_135_MonitoredItem.SamplingInterval = 1000;
IO_135_MonitoredItem.Notification += OnMonitoredItemNotification;
subscription.AddItem(IO_135_MonitoredItem);
MonitoredItem IO_140_MonitoredItem = new MonitoredItem(subscription.DefaultItem);
// Int32 Node - Objects\CTT\Scalar\Simulation\Int32
IO_140_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_140");
IO_140_MonitoredItem.AttributeId = Attributes.Value;
IO_140_MonitoredItem.DisplayName = "IO_140 Variable";
IO_140_MonitoredItem.SamplingInterval = 1000;
IO_140_MonitoredItem.Notification += OnMonitoredItemNotification;
subscription.AddItem(IO_140_MonitoredItem);
//MonitoredItem intMonitoredItem = new MonitoredItem(subscription.DefaultItem);
//// Int32 Node - Objects\CTT\Scalar\Simulation\Int32
//intMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_Int32");
//intMonitoredItem.AttributeId = Attributes.Value;
//intMonitoredItem.DisplayName = "Int32 Variable";
//intMonitoredItem.SamplingInterval = 1000;
//intMonitoredItem.Notification += OnMonitoredItemNotification;
//subscription.AddItem(intMonitoredItem);
//MonitoredItem floatMonitoredItem = new MonitoredItem(subscription.DefaultItem);
//// Float Node - Objects\CTT\Scalar\Simulation\Float
//floatMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_Float");
//floatMonitoredItem.AttributeId = Attributes.Value;
//floatMonitoredItem.DisplayName = "Float Variable";
//floatMonitoredItem.SamplingInterval = 1000;
//floatMonitoredItem.Notification += OnMonitoredItemNotification;
//subscription.AddItem(floatMonitoredItem);
//MonitoredItem stringMonitoredItem = new MonitoredItem(subscription.DefaultItem);
//// String Node - Objects\CTT\Scalar\Simulation\String
//stringMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_String");
//stringMonitoredItem.AttributeId = Attributes.Value;
//stringMonitoredItem.DisplayName = "String Variable";
//stringMonitoredItem.SamplingInterval = 1000;
//stringMonitoredItem.Notification += OnMonitoredItemNotification;
//subscription.AddItem(stringMonitoredItem);
// Create the monitored items on Server side
subscription.ApplyChanges();
m_output.WriteLine("MonitoredItems created for SubscriptionId = {0}.", subscription.Id);
}
catch (Exception ex)
{
m_output.WriteLine("Subscribe error: {0}", ex.Message);
}
}
/// <summary>
/// Write a list of nodes to the Server
/// </summary>
@@ -231,28 +502,50 @@ namespace Quickstarts.ConsoleReferenceClient
WriteValueCollection nodesToWrite = new WriteValueCollection();
// Int32 Node - Objects\CTT\Scalar\Scalar_Static\Int32
WriteValue intWriteVal = new WriteValue();
intWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_Int32");
intWriteVal.AttributeId = Attributes.Value;
intWriteVal.Value = new DataValue();
intWriteVal.Value.Value = (int)100;
nodesToWrite.Add(intWriteVal);
WriteValue commWriteVal = new WriteValue();
commWriteVal.NodeId = new NodeId("ns=4;s=IO_151");
commWriteVal.AttributeId = Attributes.Value;
commWriteVal.Value = new DataValue();
commWriteVal.Value.Value = (int)111;
nodesToWrite.Add(commWriteVal);
// Float Node - Objects\CTT\Scalar\Scalar_Static\Float
WriteValue floatWriteVal = new WriteValue();
floatWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_Float");
floatWriteVal.AttributeId = Attributes.Value;
floatWriteVal.Value = new DataValue();
floatWriteVal.Value.Value = (float)100.5;
nodesToWrite.Add(floatWriteVal);
WriteValue artWriteVal = new WriteValue();
artWriteVal.NodeId = new NodeId("ns=4;s=IO_151");
artWriteVal.AttributeId = Attributes.Value;
artWriteVal.Value = new DataValue();
artWriteVal.Value.Value = (int)222;
nodesToWrite.Add(artWriteVal);
// String Node - Objects\CTT\Scalar\Scalar_Static\String
WriteValue stringWriteVal = new WriteValue();
stringWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_String");
stringWriteVal.AttributeId = Attributes.Value;
stringWriteVal.Value = new DataValue();
stringWriteVal.Value.Value = "String Test";
nodesToWrite.Add(stringWriteVal);
WriteValue qtyWriteVal = new WriteValue();
qtyWriteVal.NodeId = new NodeId("ns=4;s=IO_153");
qtyWriteVal.AttributeId = Attributes.Value;
qtyWriteVal.Value = new DataValue();
qtyWriteVal.Value.Value = (int)333;
nodesToWrite.Add(qtyWriteVal);
//// Int32 Node - Objects\CTT\Scalar\Scalar_Static\Int32
//WriteValue intWriteVal = new WriteValue();
//intWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_Int32");
//intWriteVal.AttributeId = Attributes.Value;
//intWriteVal.Value = new DataValue();
//intWriteVal.Value.Value = (int)100;
//nodesToWrite.Add(intWriteVal);
//// Float Node - Objects\CTT\Scalar\Scalar_Static\Float
//WriteValue floatWriteVal = new WriteValue();
//floatWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_Float");
//floatWriteVal.AttributeId = Attributes.Value;
//floatWriteVal.Value = new DataValue();
//floatWriteVal.Value.Value = (float)100.5;
//nodesToWrite.Add(floatWriteVal);
//// String Node - Objects\CTT\Scalar\Scalar_Static\String
//WriteValue stringWriteVal = new WriteValue();
//stringWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_String");
//stringWriteVal.AttributeId = Attributes.Value;
//stringWriteVal.Value = new DataValue();
//stringWriteVal.Value.Value = "String Test";
//nodesToWrite.Add(stringWriteVal);
// Write the node attributes
StatusCodeCollection results = null;
@@ -283,220 +576,6 @@ namespace Quickstarts.ConsoleReferenceClient
}
}
/// <summary>
/// Browse Server nodes
/// </summary>
public void Browse()
{
if (m_session == null || m_session.Connected == false)
{
m_output.WriteLine("Session not connected!");
return;
}
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;
// 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(" DisplayName = {0}, NodeClass = {1}", result.DisplayName.Text, result.NodeClass);
}
}
catch (Exception ex)
{
// Log Error
m_output.WriteLine($"Browse Error : {ex.Message}.");
}
}
/// <summary>
/// Call UA method
/// </summary>
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<object> outputArguments = null;
// Invoke Call service
m_output.WriteLine("Calling UAMethod for node {0} ...", methodId);
outputArguments = m_session.Call(objectId, methodId, inputArguments);
// Display results
m_output.WriteLine("Method call returned {0} output argument(s):", outputArguments.Count);
foreach (var outputArgument in outputArguments)
{
m_output.WriteLine(" OutputValue = {0}", outputArgument.ToString());
}
}
catch (Exception ex)
{
m_output.WriteLine("Method call error: {0}", ex.Message);
}
}
/// <summary>
/// Create Subscription and MonitoredItems for DataChanges
/// </summary>
public void SubscribeToDataChanges()
{
if (m_session == null || m_session.Connected == false)
{
m_output.WriteLine("Session not connected!");
return;
}
try
{
// Create a subscription for receiving data change notifications
// Define Subscription parameters
Subscription subscription = new Subscription(m_session.DefaultSubscription);
subscription.DisplayName = "Console ReferenceClient Subscription";
subscription.PublishingEnabled = true;
subscription.PublishingInterval = 1000;
m_session.AddSubscription(subscription);
// Create the subscription on Server side
subscription.Create();
m_output.WriteLine("New Subscription created with SubscriptionId = {0}.", subscription.Id);
// Create MonitoredItems for data changes
MonitoredItem intMonitoredItem = new MonitoredItem(subscription.DefaultItem);
// Int32 Node - Objects\CTT\Scalar\Simulation\Int32
intMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_Int32");
intMonitoredItem.AttributeId = Attributes.Value;
intMonitoredItem.DisplayName = "Int32 Variable";
intMonitoredItem.SamplingInterval = 1000;
intMonitoredItem.Notification += OnMonitoredItemNotification;
subscription.AddItem(intMonitoredItem);
MonitoredItem floatMonitoredItem = new MonitoredItem(subscription.DefaultItem);
// Float Node - Objects\CTT\Scalar\Simulation\Float
floatMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_Float");
floatMonitoredItem.AttributeId = Attributes.Value;
floatMonitoredItem.DisplayName = "Float Variable";
floatMonitoredItem.SamplingInterval = 1000;
floatMonitoredItem.Notification += OnMonitoredItemNotification;
subscription.AddItem(floatMonitoredItem);
MonitoredItem stringMonitoredItem = new MonitoredItem(subscription.DefaultItem);
// String Node - Objects\CTT\Scalar\Simulation\String
stringMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_String");
stringMonitoredItem.AttributeId = Attributes.Value;
stringMonitoredItem.DisplayName = "String Variable";
stringMonitoredItem.SamplingInterval = 1000;
stringMonitoredItem.Notification += OnMonitoredItemNotification;
subscription.AddItem(stringMonitoredItem);
// Create the monitored items on Server side
subscription.ApplyChanges();
m_output.WriteLine("MonitoredItems created for SubscriptionId = {0}.", subscription.Id);
}
catch (Exception ex)
{
m_output.WriteLine("Subscribe error: {0}", ex.Message);
}
}
#endregion
#region Private Methods
/// <summary>
/// Handle DataChange notifications from Server
/// </summary>
private void OnMonitoredItemNotification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e)
{
try
{
// Log MonitoredItem Notification event
MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification;
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);
}
}
/// <summary>
/// Handles the certificate validation event.
/// This event is triggered every time an untrusted certificate is received from the server.
/// </summary>
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;
}
#endregion
#region Private Fields
private ApplicationConfiguration m_configuration;
private Session m_session;
private readonly IOutput m_output;
private readonly Action<IList, IList> m_validateResponse;
#endregion
#endregion Public Methods
}
}