using Opc.Ua;
using Opc.Ua.Client;
using Opc.Ua.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpcUaHelper
{
///
/// 一个二次封装了的OPC UA库,支持从opc ua服务器读写节点数据,批量读写,订阅,批量订阅,历史数据读取,方法调用操作。
///
public class OpcUaClient
{
#region Constructors
///
/// 默认的构造函数,实例化一个新的OPC UA类
///
public OpcUaClient( )
{
dic_subscriptions = new Dictionary( );
var certificateValidator = new CertificateValidator( );
certificateValidator.CertificateValidation += ( sender, eventArgs ) =>
{
if (ServiceResult.IsGood( eventArgs.Error ))
eventArgs.Accept = true;
else if (eventArgs.Error.StatusCode.Code == StatusCodes.BadCertificateUntrusted)
eventArgs.Accept = true;
else
throw new Exception( string.Format( "Failed to validate certificate with error code {0}: {1}", eventArgs.Error.Code, eventArgs.Error.AdditionalInfo ) );
};
SecurityConfiguration securityConfigurationcv = new SecurityConfiguration
{
AutoAcceptUntrustedCertificates = true,
RejectSHA1SignedCertificates = false,
MinimumCertificateKeySize = 1024,
};
certificateValidator.Update( securityConfigurationcv );
// Build the application configuration
application = new ApplicationInstance
{
ApplicationType = ApplicationType.Client,
ConfigSectionName = OpcUaName,
ApplicationConfiguration = new ApplicationConfiguration
{
ApplicationName = OpcUaName,
ApplicationType = ApplicationType.Client,
CertificateValidator = certificateValidator,
ServerConfiguration = new ServerConfiguration
{
MaxSubscriptionCount = 100000,
MaxMessageQueueSize = 1000000,
MaxNotificationQueueSize = 1000000,
MaxPublishRequestCount = 10000000,
},
SecurityConfiguration = new SecurityConfiguration
{
AutoAcceptUntrustedCertificates = true,
RejectSHA1SignedCertificates = false,
MinimumCertificateKeySize = 1024,
},
TransportQuotas = new TransportQuotas
{
OperationTimeout = 6000000,
MaxStringLength = int.MaxValue,
MaxByteStringLength = int.MaxValue,
MaxArrayLength = 65535,
MaxMessageSize = 419430400,
MaxBufferSize = 65535,
ChannelLifetime = -1,
SecurityTokenLifetime = -1
},
ClientConfiguration = new ClientConfiguration
{
DefaultSessionTimeout = -1,
MinSubscriptionLifetime = -1,
},
DisableHiResClock = true
}
};
// Assign a application certificate (when specified)
// if (ApplicationCertificate != null)
// application.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(_options.ApplicationCertificate);
m_configuration = application.ApplicationConfiguration;
}
#endregion
#region Connect And Disconnect
///
/// connect to server
///
/// remote url
public async Task ConnectServer( string serverUrl )
{
m_session = await Connect( serverUrl );
}
///
/// Creates a new session.
///
/// The new session object.
private async Task Connect( string serverUrl )
{
// disconnect from existing session.
Disconnect( );
if (m_configuration == null)
{
throw new ArgumentNullException( "m_configuration" );
}
// select the best endpoint.
EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint( serverUrl, UseSecurity );
EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create( m_configuration );
ConfiguredEndpoint endpoint = new ConfiguredEndpoint( null, endpointDescription, endpointConfiguration );
m_session = await Session.Create(
m_configuration,
endpoint,
false,
false,
(string.IsNullOrEmpty( OpcUaName )) ? m_configuration.ApplicationName : OpcUaName,
60000,
UserIdentity,
new string[] { } );
// set up keep alive callback.
m_session.KeepAlive += new KeepAliveEventHandler( Session_KeepAlive );
// update the client status
m_IsConnected = true;
// raise an event.
DoConnectComplete( null );
// return the new session.
return m_session;
}
///
/// Disconnects from the server.
///
public void Disconnect( )
{
UpdateStatus( false, DateTime.UtcNow, "Disconnected" );
// stop any reconnect operation.
if (m_reconnectHandler != null)
{
m_reconnectHandler.Dispose( );
m_reconnectHandler = null;
}
// disconnect any existing session.
if (m_session != null)
{
m_session.Close( 10000 );
m_session = null;
}
// update the client status
m_IsConnected = false;
// raise an event.
DoConnectComplete( null );
}
#endregion
#region Event Handlers
///
/// Report the client status
///
/// Whether the status represents an error.
/// The time associated with the status.
/// The status message.
/// Arguments used to format the status message.
private void UpdateStatus( bool error, DateTime time, string status, params object[] args )
{
m_OpcStatusChange?.Invoke( this, new OpcUaStatusEventArgs( )
{
Error = error,
Time = time.ToLocalTime( ),
Text = String.Format( status, args ),
} );
}
///
/// Handles a keep alive event from a session.
///
private void Session_KeepAlive( Session session, KeepAliveEventArgs e )
{
try
{
// check for events from discarded sessions.
if (!Object.ReferenceEquals( session, m_session ))
{
return;
}
// start reconnect sequence on communication error.
if (ServiceResult.IsBad( e.Status ))
{
if (m_reconnectPeriod <= 0)
{
UpdateStatus( true, e.CurrentTime, "Communication Error ({0})", e.Status );
return;
}
UpdateStatus( true, e.CurrentTime, "Reconnecting in {0}s", m_reconnectPeriod );
if (m_reconnectHandler == null)
{
m_ReconnectStarting?.Invoke( this, e );
m_reconnectHandler = new SessionReconnectHandler( );
m_reconnectHandler.BeginReconnect( m_session, m_reconnectPeriod * 1000, Server_ReconnectComplete );
}
return;
}
// update status.
UpdateStatus( false, e.CurrentTime, "Connected [{0}]", session.Endpoint.EndpointUrl );
// raise any additional notifications.
m_KeepAliveComplete?.Invoke( this, e );
}
catch (Exception exception)
{
#if !NETSTANDARD2_0 && !NETSTANDARD2_1
ClientUtils.HandleException( OpcUaName, exception );
#else
throw;
#endif
}
}
///
/// Handles a reconnect event complete from the reconnect handler.
///
private void Server_ReconnectComplete( object sender, EventArgs e )
{
try
{
// ignore callbacks from discarded objects.
if (!Object.ReferenceEquals( sender, m_reconnectHandler ))
{
return;
}
m_session = m_reconnectHandler.Session;
m_reconnectHandler.Dispose( );
m_reconnectHandler = null;
// raise any additional notifications.
m_ReconnectComplete?.Invoke( this, e );
}
catch (Exception exception)
{
#if !NETSTANDARD2_0 && !NETSTANDARD2_1
ClientUtils.HandleException( OpcUaName, exception );
#else
throw;
#endif
}
}
#endregion
#region LogOut Setting
<