From 4a96d8ec211321d4d95c24202590eb34db05a1c4 Mon Sep 17 00:00:00 2001 From: Qianyin Date: Thu, 7 Mar 2024 17:47:05 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DOPCFoundation.OPC.UA.dll?= =?UTF-8?q?=E5=BC=95=E8=B5=B7=E7=9A=84=E5=86=85=E5=AD=98=E6=BA=A2=E5=87=BA?= =?UTF-8?q?=20--=20https://files.opcfoundation.org/SecurityBulletins/OPC%2?= =?UTF-8?q?0Foundation%20Security%20Bulletin%20CVE-2023-27321.pdf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OpcUaHelper.Standard.csproj | 5 +- OpcUaHelper/FormUtils.cs | 2 +- OpcUaHelper/OpcUaClient.cs | 736 ++++++++++-------- 3 files changed, 395 insertions(+), 348 deletions(-) diff --git a/OpcUaHelper.Standard/OpcUaHelper.Standard.csproj b/OpcUaHelper.Standard/OpcUaHelper.Standard.csproj index 7b25335..2ff7b61 100644 --- a/OpcUaHelper.Standard/OpcUaHelper.Standard.csproj +++ b/OpcUaHelper.Standard/OpcUaHelper.Standard.csproj @@ -23,9 +23,8 @@ - - - + + diff --git a/OpcUaHelper/FormUtils.cs b/OpcUaHelper/FormUtils.cs index ff766d7..8bcbfe0 100644 --- a/OpcUaHelper/FormUtils.cs +++ b/OpcUaHelper/FormUtils.cs @@ -385,7 +385,7 @@ public static EndpointDescription SelectEndpoint( string discoveryUrl, bool useS /// /// The references found. Null if an error occurred. /// - public static ReferenceDescriptionCollection Browse( Session session, BrowseDescriptionCollection nodesToBrowse, bool throwOnError ) + public static ReferenceDescriptionCollection Browse( ISession session, BrowseDescriptionCollection nodesToBrowse, bool throwOnError ) { try { diff --git a/OpcUaHelper/OpcUaClient.cs b/OpcUaHelper/OpcUaClient.cs index 22d291a..bfc06fc 100644 --- a/OpcUaHelper/OpcUaClient.cs +++ b/OpcUaHelper/OpcUaClient.cs @@ -1,9 +1,10 @@ -using Opc.Ua; -using Opc.Ua.Client; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Opc.Ua; +using Opc.Ua.Client; +using Opc.Ua.Configuration; namespace OpcUaHelper { @@ -17,19 +18,19 @@ public class OpcUaClient /// /// 默认的构造函数,实例化一个新的OPC UA类 /// - public OpcUaClient( ) + public OpcUaClient() { - dic_subscriptions = new Dictionary( ); + dic_subscriptions = new Dictionary(); - var certificateValidator = new CertificateValidator( ); - certificateValidator.CertificateValidation += ( sender, eventArgs ) => + var certificateValidator = new CertificateValidator(); + certificateValidator.CertificateValidation += (sender, eventArgs) => { - if (ServiceResult.IsGood( eventArgs.Error )) + 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 ) ); + throw new Exception(string.Format("Failed to validate certificate with error code {0}: {1}", eventArgs.Error.Code, eventArgs.Error.AdditionalInfo)); }; SecurityConfiguration securityConfigurationcv = new SecurityConfiguration @@ -38,71 +39,58 @@ public OpcUaClient( ) RejectSHA1SignedCertificates = false, MinimumCertificateKeySize = 1024, }; - certificateValidator.Update( securityConfigurationcv ); + certificateValidator.Update(securityConfigurationcv); // Build the application configuration - var configuration = new ApplicationConfiguration + application = new ApplicationInstance { - ApplicationName = OpcUaName, ApplicationType = ApplicationType.Client, - CertificateValidator = certificateValidator, - ApplicationUri = "urn:MyClient", //Kepp this syntax - ProductUri = "OpcUaClient", - - ServerConfiguration = new ServerConfiguration - { - MaxSubscriptionCount = 100000, - MaxMessageQueueSize = 1000000, - MaxNotificationQueueSize = 1000000, - MaxPublishRequestCount = 10000000, - }, - - SecurityConfiguration = new SecurityConfiguration + ConfigSectionName = OpcUaName, + ApplicationConfiguration = new ApplicationConfiguration { - AutoAcceptUntrustedCertificates = true, - RejectSHA1SignedCertificates = false, - MinimumCertificateKeySize = 1024, - SuppressNonceValidationErrors = true, + ApplicationName = OpcUaName, + ApplicationType = ApplicationType.Client, + CertificateValidator = certificateValidator, + ServerConfiguration = new ServerConfiguration + { + MaxSubscriptionCount = 100000, + MaxMessageQueueSize = 1000000, + MaxNotificationQueueSize = 1000000, + MaxPublishRequestCount = 10000000, + }, - ApplicationCertificate = new CertificateIdentifier + SecurityConfiguration = new SecurityConfiguration { - StoreType = CertificateStoreType.X509Store, - StorePath = "CurrentUser\\My", - SubjectName = OpcUaName, + AutoAcceptUntrustedCertificates = true, + RejectSHA1SignedCertificates = false, + MinimumCertificateKeySize = 1024, }, - TrustedIssuerCertificates = new CertificateTrustList + + TransportQuotas = new TransportQuotas { - StoreType = CertificateStoreType.X509Store, - StorePath = "CurrentUser\\Root", + OperationTimeout = 6000000, + MaxStringLength = int.MaxValue, + MaxByteStringLength = int.MaxValue, + MaxArrayLength = 65535, + MaxMessageSize = 419430400, + MaxBufferSize = 65535, + ChannelLifetime = -1, + SecurityTokenLifetime = -1 }, - TrustedPeerCertificates = new CertificateTrustList + ClientConfiguration = new ClientConfiguration { - StoreType = CertificateStoreType.X509Store, - StorePath = "CurrentUser\\Root", - } - }, - - 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 + DefaultSessionTimeout = -1, + MinSubscriptionLifetime = -1, + }, + DisableHiResClock = true + } }; - configuration.Validate( ApplicationType.Client ); - m_configuration = configuration; + // Assign a application certificate (when specified) + // if (ApplicationCertificate != null) + // application.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(_options.ApplicationCertificate); + + m_configuration = application.ApplicationConfiguration; } #endregion Constructors @@ -113,49 +101,49 @@ public OpcUaClient( ) /// connect to server /// /// remote url - public async Task ConnectServer( string serverUrl ) + public async Task ConnectServer(string serverUrl) { - m_session = await Connect( serverUrl ); + m_session = await Connect(serverUrl); } /// /// Creates a new session. /// /// The new session object. - private async Task Connect( string serverUrl ) + private async Task Connect(string serverUrl) { // disconnect from existing session. - Disconnect( ); + Disconnect(); if (m_configuration == null) { - throw new ArgumentNullException( "_configuration" ); + throw new ArgumentNullException("m_configuration"); } // select the best endpoint. - EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint( serverUrl, UseSecurity ); - EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create( m_configuration ); + EndpointDescription endpointDescription = CoreClientUtils.SelectEndpoint(serverUrl, UseSecurity); - ConfiguredEndpoint endpoint = new ConfiguredEndpoint( null, endpointDescription, endpointConfiguration ); + EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(m_configuration); + ConfiguredEndpoint endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration); - m_session = await Session.Create( + m_session = await Opc.Ua.Client.Session.Create( m_configuration, endpoint, false, false, - (string.IsNullOrEmpty( OpcUaName )) ? m_configuration.ApplicationName : OpcUaName, + (string.IsNullOrEmpty(OpcUaName)) ? m_configuration.ApplicationName : OpcUaName, 60000, UserIdentity, - new string[] { } ); + new string[] { }); // set up keep alive callback. - m_session.KeepAlive += new KeepAliveEventHandler( Session_KeepAlive ); + m_session.KeepAlive += new KeepAliveEventHandler(Session_KeepAlive); // update the client status m_IsConnected = true; // raise an event. - DoConnectComplete( null ); + DoConnectComplete(null); // return the new session. return m_session; @@ -164,21 +152,21 @@ private async Task Connect( string serverUrl ) /// /// Disconnects from the server. /// - public void Disconnect( ) + public void Disconnect() { - UpdateStatus( false, DateTime.UtcNow, "Disconnected" ); + UpdateStatus(false, DateTime.UtcNow, "Disconnected"); // stop any reconnect operation. - if (m_reConnectHandler != null) + if (m_reconnectHandler != null) { - m_reConnectHandler.Dispose( ); - m_reConnectHandler = null; + m_reconnectHandler.Dispose(); + m_reconnectHandler = null; } // disconnect any existing session. if (m_session != null) { - m_session.Close( 10000 ); + m_session.Close(10000); m_session = null; } @@ -186,7 +174,7 @@ public void Disconnect( ) m_IsConnected = false; // raise an event. - DoConnectComplete( null ); + DoConnectComplete(null); } #endregion Connect And Disconnect @@ -200,56 +188,56 @@ public void Disconnect( ) /// 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 ) + private void UpdateStatus(bool error, DateTime time, string status, params object[] args) { - m_OpcStatusChange?.Invoke( this, new OpcUaStatusEventArgs( ) + m_OpcStatusChange?.Invoke(this, new OpcUaStatusEventArgs() { Error = error, - Time = time.ToLocalTime( ), - Text = String.Format( status, args ), - } ); + Time = time.ToLocalTime(), + Text = String.Format(status, args), + }); } /// /// Handles a keep alive event from a session. /// - private void Session_KeepAlive( Session session, KeepAliveEventArgs e ) + private void Session_KeepAlive(ISession session, KeepAliveEventArgs e) { try { // check for events from discarded sessions. - if (!Object.ReferenceEquals( session, m_session )) + if (!Object.ReferenceEquals(session, m_session)) { return; } // start reconnect sequence on communication error. - if (ServiceResult.IsBad( e.Status )) + if (ServiceResult.IsBad(e.Status)) { if (m_reconnectPeriod <= 0) { - UpdateStatus( true, e.CurrentTime, "Communication Error ({0})", e.Status ); + UpdateStatus(true, e.CurrentTime, "Communication Error ({0})", e.Status); return; } - UpdateStatus( true, e.CurrentTime, "Reconnecting in {0}s", m_reconnectPeriod ); + UpdateStatus(true, e.CurrentTime, "Reconnecting in {0}s", m_reconnectPeriod); - if (m_reConnectHandler == null) + if (m_reconnectHandler == null) { - m_ReconnectStarting?.Invoke( this, e ); + m_ReconnectStarting?.Invoke(this, e); - m_reConnectHandler = new SessionReconnectHandler( ); - m_reConnectHandler.BeginReconnect( m_session, m_reconnectPeriod * 1000, Server_ReconnectComplete ); + 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 ); + UpdateStatus(false, e.CurrentTime, "Connected [{0}]", session.Endpoint.EndpointUrl); // raise any additional notifications. - m_KeepAliveComplete?.Invoke( this, e ); + m_KeepAliveComplete?.Invoke(this, e); } catch (Exception exception) { @@ -264,22 +252,22 @@ private void Session_KeepAlive( Session session, KeepAliveEventArgs e ) /// /// Handles a reconnect event complete from the reconnect handler. /// - private void Server_ReconnectComplete( object sender, EventArgs e ) + private void Server_ReconnectComplete(object sender, EventArgs e) { try { // ignore callbacks from discarded objects. - if (!Object.ReferenceEquals( sender, m_reConnectHandler )) + if (!Object.ReferenceEquals(sender, m_reconnectHandler)) { return; } - m_session = m_reConnectHandler.Session; - m_reConnectHandler.Dispose( ); - m_reConnectHandler = null; + m_session = m_reconnectHandler.Session; + m_reconnectHandler.Dispose(); + m_reconnectHandler = null; // raise any additional notifications. - m_ReconnectComplete?.Invoke( this, e ); + m_ReconnectComplete?.Invoke(this, e); } catch (Exception exception) { @@ -300,10 +288,10 @@ private void Server_ReconnectComplete( object sender, EventArgs e ) /// /// 完整的文件路径 /// 是否删除原文件 - public void SetLogPathName( string filePath, bool deleteExisting ) + public void SetLogPathName(string filePath, bool deleteExisting) { - Utils.SetTraceLog( filePath, deleteExisting ); - Utils.SetTraceMask( 515 ); + Utils.SetTraceLog(filePath, deleteExisting); + Utils.SetTraceMask(515); } #endregion LogOut Setting @@ -332,7 +320,7 @@ public bool UseSecurity /// /// The currently active session. /// - public Session Session + public ISession Session { get { return m_session; } } @@ -402,7 +390,13 @@ public event EventHandler OpcStatusChange /// /// 配置信息 /// - public ApplicationConfiguration AppConfig => m_configuration; + public ApplicationConfiguration AppConfig + { + get + { + return m_configuration; + } + } #endregion Public Members @@ -413,14 +407,14 @@ public event EventHandler OpcStatusChange /// /// node id /// DataValue - public DataValue ReadNode( NodeId nodeId ) + public DataValue ReadNode(NodeId nodeId) { ReadValueIdCollection nodesToRead = new ReadValueIdCollection { new ReadValueId( ) { NodeId = nodeId, - AttributeId = Attributes.Value + AttributeId = Opc.Ua.Attributes.Value } }; @@ -431,10 +425,10 @@ public DataValue ReadNode( NodeId nodeId ) TimestampsToReturn.Neither, nodesToRead, out DataValueCollection results, - out DiagnosticInfoCollection diagnosticInfos ); + out DiagnosticInfoCollection diagnosticInfos); - ClientBase.ValidateResponse( results, nodesToRead ); - ClientBase.ValidateDiagnosticInfos( diagnosticInfos, nodesToRead ); + ClientBase.ValidateResponse(results, nodesToRead); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); return results[0]; } @@ -445,9 +439,9 @@ public DataValue ReadNode( NodeId nodeId ) /// type of value /// node id /// 实际值 - public T ReadNode( string tag ) + public T ReadNode(string tag) { - DataValue dataValue = ReadNode( new NodeId( tag ) ); + DataValue dataValue = ReadNode(new NodeId(tag)); return (T)dataValue.Value; } @@ -457,19 +451,19 @@ public T ReadNode( string tag ) /// The type of tag to read /// tag值 /// The value retrieved from the OPC - public Task ReadNodeAsync( string tag ) + public Task ReadNodeAsync(string tag) { ReadValueIdCollection nodesToRead = new ReadValueIdCollection { new ReadValueId() { NodeId = new NodeId(tag), - AttributeId = Attributes.Value + AttributeId = Opc.Ua.Attributes.Value } }; // Wrap the ReadAsync logic in a TaskCompletionSource, so we can use C# async/await syntax to call it: - var taskCompletionSource = new TaskCompletionSource( ); + var taskCompletionSource = new TaskCompletionSource(); m_session.BeginRead( requestHeader: null, maxAge: 0, @@ -482,21 +476,21 @@ public Task ReadNodeAsync( string tag ) var response = m_session.EndRead( result: ar, results: out results, - diagnosticInfos: out diag ); + diagnosticInfos: out diag); try { - CheckReturnValue( response.ServiceResult ); - CheckReturnValue( results[0].StatusCode ); + CheckReturnValue(response.ServiceResult); + CheckReturnValue(results[0].StatusCode); var val = results[0]; - taskCompletionSource.TrySetResult( (T)val.Value ); + taskCompletionSource.TrySetResult((T)val.Value); } catch (Exception ex) { - taskCompletionSource.TrySetException( ex ); + taskCompletionSource.TrySetException(ex); } }, - asyncState: null ); + asyncState: null); return taskCompletionSource.Task; } @@ -506,16 +500,16 @@ public Task ReadNodeAsync( string tag ) /// /// all NodeIds /// all values - public List ReadNodes( NodeId[] nodeIds ) + public List ReadNodes(NodeId[] nodeIds) { - ReadValueIdCollection nodesToRead = new ReadValueIdCollection( ); + ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); for (int i = 0; i < nodeIds.Length; i++) { - nodesToRead.Add( new ReadValueId( ) + nodesToRead.Add(new ReadValueId() { NodeId = nodeIds[i], - AttributeId = Attributes.Value - } ); + AttributeId = Opc.Ua.Attributes.Value + }); } // 读取当前的值 @@ -525,12 +519,12 @@ public List ReadNodes( NodeId[] nodeIds ) TimestampsToReturn.Neither, nodesToRead, out DataValueCollection results, - out DiagnosticInfoCollection diagnosticInfos ); + out DiagnosticInfoCollection diagnosticInfos); - ClientBase.ValidateResponse( results, nodesToRead ); - ClientBase.ValidateDiagnosticInfos( diagnosticInfos, nodesToRead ); + ClientBase.ValidateResponse(results, nodesToRead); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - return results.ToList( ); + return results.ToList(); } /// @@ -538,19 +532,19 @@ public List ReadNodes( NodeId[] nodeIds ) /// /// all NodeIds /// all values - public Task> ReadNodesAsync( NodeId[] nodeIds ) + public Task> ReadNodesAsync(NodeId[] nodeIds) { - ReadValueIdCollection nodesToRead = new ReadValueIdCollection( ); + ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); for (int i = 0; i < nodeIds.Length; i++) { - nodesToRead.Add( new ReadValueId( ) + nodesToRead.Add(new ReadValueId() { NodeId = nodeIds[i], - AttributeId = Attributes.Value - } ); + AttributeId = Opc.Ua.Attributes.Value + }); } - var taskCompletionSource = new TaskCompletionSource>( ); + var taskCompletionSource = new TaskCompletionSource>(); // 读取当前的值 m_session.BeginRead( null, @@ -564,19 +558,19 @@ public Task> ReadNodesAsync( NodeId[] nodeIds ) var response = m_session.EndRead( result: ar, results: out results, - diagnosticInfos: out diag ); + diagnosticInfos: out diag); try { - CheckReturnValue( response.ServiceResult ); - taskCompletionSource.TrySetResult( results.ToList( ) ); + CheckReturnValue(response.ServiceResult); + taskCompletionSource.TrySetResult(results.ToList()); } catch (Exception ex) { - taskCompletionSource.TrySetException( ex ); + taskCompletionSource.TrySetException(ex); } }, - asyncState: null ); + asyncState: null); return taskCompletionSource.Task; } @@ -586,17 +580,17 @@ public Task> ReadNodesAsync( NodeId[] nodeIds ) /// /// 所以的节点数组信息 /// all values - public List ReadNodes( string[] tags ) + public List ReadNodes(string[] tags) { - List result = new List( ); - ReadValueIdCollection nodesToRead = new ReadValueIdCollection( ); + List result = new List(); + ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); for (int i = 0; i < tags.Length; i++) { - nodesToRead.Add( new ReadValueId( ) + nodesToRead.Add(new ReadValueId() { - NodeId = new NodeId( tags[i] ), - AttributeId = Attributes.Value - } ); + NodeId = new NodeId(tags[i]), + AttributeId = Opc.Ua.Attributes.Value + }); } // 读取当前的值 @@ -606,14 +600,14 @@ public List ReadNodes( string[] tags ) TimestampsToReturn.Neither, nodesToRead, out DataValueCollection results, - out DiagnosticInfoCollection diagnosticInfos ); + out DiagnosticInfoCollection diagnosticInfos); - ClientBase.ValidateResponse( results, nodesToRead ); - ClientBase.ValidateDiagnosticInfos( diagnosticInfos, nodesToRead ); + ClientBase.ValidateResponse(results, nodesToRead); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); foreach (var item in results) { - result.Add( (T)item.Value ); + result.Add((T)item.Value); } return result; } @@ -623,19 +617,19 @@ public List ReadNodes( string[] tags ) /// /// all NodeIds /// all values - public Task> ReadNodesAsync( string[] tags ) + public Task> ReadNodesAsync(string[] tags) { - ReadValueIdCollection nodesToRead = new ReadValueIdCollection( ); + ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); for (int i = 0; i < tags.Length; i++) { - nodesToRead.Add( new ReadValueId( ) + nodesToRead.Add(new ReadValueId() { - NodeId = new NodeId( tags[i] ), - AttributeId = Attributes.Value - } ); + NodeId = new NodeId(tags[i]), + AttributeId = Opc.Ua.Attributes.Value + }); } - var taskCompletionSource = new TaskCompletionSource>( ); + var taskCompletionSource = new TaskCompletionSource>(); // 读取当前的值 m_session.BeginRead( null, @@ -649,24 +643,24 @@ public Task> ReadNodesAsync( string[] tags ) var response = m_session.EndRead( result: ar, results: out results, - diagnosticInfos: out diag ); + diagnosticInfos: out diag); try { - CheckReturnValue( response.ServiceResult ); - List result = new List( ); + CheckReturnValue(response.ServiceResult); + List result = new List(); foreach (var item in results) { - result.Add( (T)item.Value ); + result.Add((T)item.Value); } - taskCompletionSource.TrySetResult( result ); + taskCompletionSource.TrySetResult(result); } catch (Exception ex) { - taskCompletionSource.TrySetException( ex ); + taskCompletionSource.TrySetException(ex); } }, - asyncState: null ); + asyncState: null); return taskCompletionSource.Task; } @@ -678,12 +672,12 @@ public Task> ReadNodesAsync( string[] tags ) /// 节点名称 /// 值 /// if success True,otherwise False - public bool WriteNode( string tag, T value ) + public bool WriteNode(string tag, T value) { - WriteValue valueToWrite = new WriteValue( ) + WriteValue valueToWrite = new WriteValue() { - NodeId = new NodeId( tag ), - AttributeId = Attributes.Value + NodeId = new NodeId(tag), + AttributeId = Opc.Ua.Attributes.Value }; valueToWrite.Value.Value = value; valueToWrite.Value.StatusCode = StatusCodes.Good; @@ -701,17 +695,17 @@ public bool WriteNode( string tag, T value ) null, valuesToWrite, out StatusCodeCollection results, - out DiagnosticInfoCollection diagnosticInfos ); + out DiagnosticInfoCollection diagnosticInfos); - ClientBase.ValidateResponse( results, valuesToWrite ); - ClientBase.ValidateDiagnosticInfos( diagnosticInfos, valuesToWrite ); + ClientBase.ValidateResponse(results, valuesToWrite); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToWrite); - if (StatusCode.IsBad( results[0] )) + if (StatusCode.IsBad(results[0])) { - throw new ServiceResultException( results[0] ); + throw new ServiceResultException(results[0]); } - return !StatusCode.IsBad( results[0] ); + return !StatusCode.IsBad(results[0]); } /// @@ -720,12 +714,12 @@ public bool WriteNode( string tag, T value ) /// The type of tag to write on /// The fully-qualified identifier of the tag. You can specify a subfolder by using a comma delimited name. E.g: the tag `foo.bar` writes on the tag `bar` on the folder `foo` /// The value for the item to write - public Task WriteNodeAsync( string tag, T value ) + public Task WriteNodeAsync(string tag, T value) { - WriteValue valueToWrite = new WriteValue( ) + WriteValue valueToWrite = new WriteValue() { - NodeId = new NodeId( tag ), - AttributeId = Attributes.Value, + NodeId = new NodeId(tag), + AttributeId = Opc.Ua.Attributes.Value, }; valueToWrite.Value.Value = value; valueToWrite.Value.StatusCode = StatusCodes.Good; @@ -737,7 +731,7 @@ public Task WriteNodeAsync( string tag, T value ) }; // Wrap the WriteAsync logic in a TaskCompletionSource, so we can use C# async/await syntax to call it: - var taskCompletionSource = new TaskCompletionSource( ); + var taskCompletionSource = new TaskCompletionSource(); m_session.BeginWrite( requestHeader: null, nodesToWrite: valuesToWrite, @@ -746,20 +740,20 @@ public Task WriteNodeAsync( string tag, T value ) var response = m_session.EndWrite( result: ar, results: out StatusCodeCollection results, - diagnosticInfos: out DiagnosticInfoCollection diag ); + diagnosticInfos: out DiagnosticInfoCollection diag); try { - ClientBase.ValidateResponse( results, valuesToWrite ); - ClientBase.ValidateDiagnosticInfos( diag, valuesToWrite ); - taskCompletionSource.SetResult( StatusCode.IsGood( results[0] ) ); + ClientBase.ValidateResponse(results, valuesToWrite); + ClientBase.ValidateDiagnosticInfos(diag, valuesToWrite); + taskCompletionSource.SetResult(StatusCode.IsGood(results[0])); } catch (Exception ex) { - taskCompletionSource.TrySetException( ex ); + taskCompletionSource.TrySetException(ex); } }, - asyncState: null ); + asyncState: null); return taskCompletionSource.Task; } @@ -769,24 +763,24 @@ public Task WriteNodeAsync( string tag, T value ) /// 节点名称数组 /// 节点的值数据 /// 所有的是否都写入成功 - public bool WriteNodes( string[] tags, object[] values ) + public bool WriteNodes(string[] tags, object[] values) { - WriteValueCollection valuesToWrite = new WriteValueCollection( ); + WriteValueCollection valuesToWrite = new WriteValueCollection(); for (int i = 0; i < tags.Length; i++) { if (i < values.Length) { - WriteValue valueToWrite = new WriteValue( ) + WriteValue valueToWrite = new WriteValue() { - NodeId = new NodeId( tags[i] ), - AttributeId = Attributes.Value + NodeId = new NodeId(tags[i]), + AttributeId = Opc.Ua.Attributes.Value }; valueToWrite.Value.Value = values[i]; valueToWrite.Value.StatusCode = StatusCodes.Good; valueToWrite.Value.ServerTimestamp = DateTime.MinValue; valueToWrite.Value.SourceTimestamp = DateTime.MinValue; - valuesToWrite.Add( valueToWrite ); + valuesToWrite.Add(valueToWrite); } } @@ -796,15 +790,15 @@ public bool WriteNodes( string[] tags, object[] values ) null, valuesToWrite, out StatusCodeCollection results, - out DiagnosticInfoCollection diagnosticInfos ); + out DiagnosticInfoCollection diagnosticInfos); - ClientBase.ValidateResponse( results, valuesToWrite ); - ClientBase.ValidateDiagnosticInfos( diagnosticInfos, valuesToWrite ); + ClientBase.ValidateResponse(results, valuesToWrite); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToWrite); bool result = true; foreach (var r in results) { - if (StatusCode.IsBad( r )) + if (StatusCode.IsBad(r)) { result = false; break; @@ -814,6 +808,56 @@ public bool WriteNodes( string[] tags, object[] values ) return result; } + public (bool res, string msg) WriteNodesWithResult(string[] tags, object[] values) + { + WriteValueCollection valuesToWrite = new WriteValueCollection(); + + for (int i = 0; i < tags.Length; i++) + { + if (i < values.Length) + { + WriteValue valueToWrite = new WriteValue() + { + NodeId = new NodeId(tags[i]), + AttributeId = Opc.Ua.Attributes.Value + }; + valueToWrite.Value.Value = values[i]; + valueToWrite.Value.StatusCode = StatusCodes.Good; + valueToWrite.Value.ServerTimestamp = DateTime.MinValue; + valueToWrite.Value.SourceTimestamp = DateTime.MinValue; + valuesToWrite.Add(valueToWrite); + } + } + + // 写入当前的值 + + m_session.Write( + null, + valuesToWrite, + out StatusCodeCollection results, + out DiagnosticInfoCollection diagnosticInfos); + + ClientBase.ValidateResponse(results, valuesToWrite); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, valuesToWrite); + + bool result = true; + string msg = string.Empty; + + int j = 0; + foreach (var r in results) + { + if (StatusCode.IsBad(r)) + { + result = false; + msg = $"节点 '{tags[j]}' 写入失败,{new ServiceResultException(results[j]).Message}"; + break; + } + j++; + } + + return (result, msg); + } + #endregion Node Write/Read Support #region DeleteNode Support @@ -823,25 +867,25 @@ public bool WriteNodes( string[] tags, object[] values ) /// /// 节点文本描述 /// 是否删除成功 - public bool DeleteExsistNode( string tag ) + public bool DeleteExsistNode(string tag) { - DeleteNodesItemCollection waitDelete = new DeleteNodesItemCollection( ); + DeleteNodesItemCollection waitDelete = new DeleteNodesItemCollection(); - DeleteNodesItem nodesItem = new DeleteNodesItem( ) + DeleteNodesItem nodesItem = new DeleteNodesItem() { - NodeId = new NodeId( tag ), + NodeId = new NodeId(tag), }; m_session.DeleteNodes( null, waitDelete, out StatusCodeCollection results, - out DiagnosticInfoCollection diagnosticInfos ); + out DiagnosticInfoCollection diagnosticInfos); - ClientBase.ValidateResponse( results, waitDelete ); - ClientBase.ValidateDiagnosticInfos( diagnosticInfos, waitDelete ); + ClientBase.ValidateResponse(results, waitDelete); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, waitDelete); - return !StatusCode.IsBad( results[0] ); + return !StatusCode.IsBad(results[0]); } #endregion DeleteNode Support @@ -852,27 +896,27 @@ public bool DeleteExsistNode( string tag ) /// 新增一个节点数据 /// /// 父节点tag名称 - [Obsolete( "还未经过测试,无法使用" )] - public void AddNewNode( NodeId parent ) + [Obsolete("还未经过测试,无法使用")] + public void AddNewNode(NodeId parent) { // Create a Variable node. - AddNodesItem node2 = new AddNodesItem( ); - node2.ParentNodeId = new NodeId( parent ); + AddNodesItem node2 = new AddNodesItem(); + node2.ParentNodeId = new NodeId(parent); node2.ReferenceTypeId = ReferenceTypes.HasComponent; node2.RequestedNewNodeId = null; - node2.BrowseName = new QualifiedName( "DataVariable1" ); + node2.BrowseName = new QualifiedName("DataVariable1"); node2.NodeClass = NodeClass.Variable; node2.NodeAttributes = null; node2.TypeDefinition = VariableTypeIds.BaseDataVariableType; //specify node attributes. - VariableAttributes node2Attribtues = new VariableAttributes( ); + VariableAttributes node2Attribtues = new VariableAttributes(); node2Attribtues.DisplayName = "DataVariable1"; node2Attribtues.Description = "DataVariable1 Description"; - node2Attribtues.Value = new Variant( 123 ); + node2Attribtues.Value = new Variant(123); node2Attribtues.DataType = (uint)BuiltInType.Int32; node2Attribtues.ValueRank = ValueRanks.Scalar; - node2Attribtues.ArrayDimensions = new UInt32Collection( ); + node2Attribtues.ArrayDimensions = new UInt32Collection(); node2Attribtues.AccessLevel = AccessLevels.CurrentReadOrWrite; node2Attribtues.UserAccessLevel = AccessLevels.CurrentReadOrWrite; node2Attribtues.MinimumSamplingInterval = 0; @@ -881,18 +925,21 @@ public void AddNewNode( NodeId parent ) node2Attribtues.UserWriteMask = (uint)AttributeWriteMask.None; node2Attribtues.SpecifiedAttributes = (uint)NodeAttributesMask.All; - node2.NodeAttributes = new ExtensionObject( node2Attribtues ); + node2.NodeAttributes = new ExtensionObject(node2Attribtues); - AddNodesItemCollection nodesToAdd = new AddNodesItemCollection { node2 }; + AddNodesItemCollection nodesToAdd = new AddNodesItemCollection + { + node2 + }; m_session.AddNodes( null, nodesToAdd, out AddNodesResultCollection results, - out DiagnosticInfoCollection diagnosticInfos ); + out DiagnosticInfoCollection diagnosticInfos); - ClientBase.ValidateResponse( results, nodesToAdd ); - ClientBase.ValidateDiagnosticInfos( diagnosticInfos, nodesToAdd ); + ClientBase.ValidateResponse(results, nodesToAdd); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToAdd); } #endregion Test Function @@ -905,9 +952,9 @@ public void AddNewNode( NodeId parent ) /// 关键字 /// tag /// 回调方法 - public void AddSubscription( string key, string tag, Action callback ) + public void AddSubscription(string key, string tag, Action callback) { - AddSubscription( key, new string[] { tag }, callback ); + AddSubscription(key, new string[] { tag }, callback); } /// @@ -916,9 +963,9 @@ public void AddSubscription( string key, string tag, Action关键字 /// 节点名称数组 /// 回调方法 - public void AddSubscription( string key, string[] tags, Action callback ) + public void AddSubscription(string key, string[] tags, Action callback) { - Subscription m_subscription = new Subscription( m_session.DefaultSubscription ); + Subscription m_subscription = new Subscription(m_session.DefaultSubscription); m_subscription.PublishingEnabled = true; m_subscription.PublishingInterval = 0; @@ -932,34 +979,34 @@ public void AddSubscription( string key, string[] tags, Action + item.Notification += (MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs args) => { - callback?.Invoke( key, monitoredItem, args ); + callback?.Invoke(key, monitoredItem, args); }; - m_subscription.AddItem( item ); + m_subscription.AddItem(item); } - m_session.AddSubscription( m_subscription ); - m_subscription.Create( ); + m_session.AddSubscription(m_subscription); + m_subscription.Create(); lock (dic_subscriptions) { - if (dic_subscriptions.ContainsKey( key )) + if (dic_subscriptions.ContainsKey(key)) { // remove - dic_subscriptions[key].Delete( true ); - m_session.RemoveSubscription( dic_subscriptions[key] ); - dic_subscriptions[key].Dispose( ); + dic_subscriptions[key].Delete(true); + m_session.RemoveSubscription(dic_subscriptions[key]); + dic_subscriptions[key].Dispose(); dic_subscriptions[key] = m_subscription; } else { - dic_subscriptions.Add( key, m_subscription ); + dic_subscriptions.Add(key, m_subscription); } } } @@ -968,17 +1015,17 @@ public void AddSubscription( string key, string[] tags, Action /// 订阅关键值 - public void RemoveSubscription( string key ) + public void RemoveSubscription(string key) { lock (dic_subscriptions) { - if (dic_subscriptions.ContainsKey( key )) + if (dic_subscriptions.ContainsKey(key)) { // remove - dic_subscriptions[key].Delete( true ); - m_session.RemoveSubscription( dic_subscriptions[key] ); - dic_subscriptions[key].Dispose( ); - dic_subscriptions.Remove( key ); + dic_subscriptions[key].Delete(true); + m_session.RemoveSubscription(dic_subscriptions[key]); + dic_subscriptions[key].Dispose(); + dic_subscriptions.Remove(key); } } } @@ -986,17 +1033,17 @@ public void RemoveSubscription( string key ) /// /// 移除所有的订阅消息 /// - public void RemoveAllSubscription( ) + public void RemoveAllSubscription() { lock (dic_subscriptions) { foreach (var item in dic_subscriptions) { - item.Value.Delete( true ); - m_session.RemoveSubscription( item.Value ); - item.Value.Dispose( ); + item.Value.Delete(true); + m_session.RemoveSubscription(item.Value); + item.Value.Dispose(); } - dic_subscriptions.Clear( ); + dic_subscriptions.Clear(); } } @@ -1013,11 +1060,11 @@ public void RemoveAllSubscription( ) /// 读取的个数 /// 是否包含边界 /// 读取的数据列表 - public IEnumerable ReadHistoryRawDataValues( string tag, DateTime start, DateTime end, uint count = 1, bool containBound = false ) + public IEnumerable ReadHistoryRawDataValues(string tag, DateTime start, DateTime end, uint count = 1, bool containBound = false) { - HistoryReadValueId m_nodeToContinue = new HistoryReadValueId( ) + HistoryReadValueId m_nodeToContinue = new HistoryReadValueId() { - NodeId = new NodeId( tag ), + NodeId = new NodeId(tag), }; ReadRawModifiedDetails m_details = new ReadRawModifiedDetails @@ -1029,27 +1076,27 @@ public IEnumerable ReadHistoryRawDataValues( string tag, DateTime sta ReturnBounds = containBound }; - HistoryReadValueIdCollection nodesToRead = new HistoryReadValueIdCollection( ); - nodesToRead.Add( m_nodeToContinue ); + HistoryReadValueIdCollection nodesToRead = new HistoryReadValueIdCollection(); + nodesToRead.Add(m_nodeToContinue); m_session.HistoryRead( null, - new ExtensionObject( m_details ), + new ExtensionObject(m_details), TimestampsToReturn.Both, false, nodesToRead, out HistoryReadResultCollection results, - out DiagnosticInfoCollection diagnosticInfos ); + out DiagnosticInfoCollection diagnosticInfos); - ClientBase.ValidateResponse( results, nodesToRead ); - ClientBase.ValidateDiagnosticInfos( diagnosticInfos, nodesToRead ); + ClientBase.ValidateResponse(results, nodesToRead); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - if (StatusCode.IsBad( results[0].StatusCode )) + if (StatusCode.IsBad(results[0].StatusCode)) { - throw new ServiceResultException( results[0].StatusCode ); + throw new ServiceResultException(results[0].StatusCode); } - HistoryData values = ExtensionObject.ToEncodeable( results[0].HistoryData ) as HistoryData; + HistoryData values = ExtensionObject.ToEncodeable(results[0].HistoryData) as HistoryData; foreach (var value in values.DataValues) { yield return value; @@ -1065,43 +1112,43 @@ public IEnumerable ReadHistoryRawDataValues( string tag, DateTime sta /// 读取的个数 /// 是否包含边界 /// 读取的数据列表 - public IEnumerable ReadHistoryRawDataValues( string tag, DateTime start, DateTime end, uint count = 1, bool containBound = false ) + public IEnumerable ReadHistoryRawDataValues(string tag, DateTime start, DateTime end, uint count = 1, bool containBound = false) { - HistoryReadValueId m_nodeToContinue = new HistoryReadValueId( ) + HistoryReadValueId m_nodeToContinue = new HistoryReadValueId() { - NodeId = new NodeId( tag ), + NodeId = new NodeId(tag), }; ReadRawModifiedDetails m_details = new ReadRawModifiedDetails { - StartTime = start.ToUniversalTime( ), - EndTime = end.ToUniversalTime( ), + StartTime = start.ToUniversalTime(), + EndTime = end.ToUniversalTime(), NumValuesPerNode = count, IsReadModified = false, ReturnBounds = containBound }; - HistoryReadValueIdCollection nodesToRead = new HistoryReadValueIdCollection( ); - nodesToRead.Add( m_nodeToContinue ); + HistoryReadValueIdCollection nodesToRead = new HistoryReadValueIdCollection(); + nodesToRead.Add(m_nodeToContinue); m_session.HistoryRead( null, - new ExtensionObject( m_details ), + new ExtensionObject(m_details), TimestampsToReturn.Both, false, nodesToRead, out HistoryReadResultCollection results, - out DiagnosticInfoCollection diagnosticInfos ); + out DiagnosticInfoCollection diagnosticInfos); - ClientBase.ValidateResponse( results, nodesToRead ); - ClientBase.ValidateDiagnosticInfos( diagnosticInfos, nodesToRead ); + ClientBase.ValidateResponse(results, nodesToRead); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - if (StatusCode.IsBad( results[0].StatusCode )) + if (StatusCode.IsBad(results[0].StatusCode)) { - throw new ServiceResultException( results[0].StatusCode ); + throw new ServiceResultException(results[0].StatusCode); } - HistoryData values = ExtensionObject.ToEncodeable( results[0].HistoryData ) as HistoryData; + HistoryData values = ExtensionObject.ToEncodeable(results[0].HistoryData) as HistoryData; foreach (var value in values.DataValues) { yield return (T)value.Value; @@ -1117,12 +1164,12 @@ public IEnumerable ReadHistoryRawDataValues( string tag, DateTime start, D /// /// 节点值 /// 引用节点描述 - public ReferenceDescription[] BrowseNodeReference( string tag ) + public ReferenceDescription[] BrowseNodeReference(string tag) { - NodeId sourceId = new NodeId( tag ); + NodeId sourceId = new NodeId(tag); // 该节点可以读取到方法 - BrowseDescription nodeToBrowse1 = new BrowseDescription( ); + BrowseDescription nodeToBrowse1 = new BrowseDescription(); nodeToBrowse1.NodeId = sourceId; nodeToBrowse1.BrowseDirection = BrowseDirection.Forward; @@ -1133,7 +1180,7 @@ public ReferenceDescription[] BrowseNodeReference( string tag ) // 该节点无论怎么样都读取不到方法 // find all nodes organized by the node. - BrowseDescription nodeToBrowse2 = new BrowseDescription( ); + BrowseDescription nodeToBrowse2 = new BrowseDescription(); nodeToBrowse2.NodeId = sourceId; nodeToBrowse2.BrowseDirection = BrowseDirection.Forward; @@ -1142,14 +1189,14 @@ public ReferenceDescription[] BrowseNodeReference( string tag ) nodeToBrowse2.NodeClassMask = (uint)(NodeClass.Object | NodeClass.Variable); nodeToBrowse2.ResultMask = (uint)BrowseResultMask.All; - BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection( ); - nodesToBrowse.Add( nodeToBrowse1 ); - nodesToBrowse.Add( nodeToBrowse2 ); + BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); + nodesToBrowse.Add(nodeToBrowse1); + nodesToBrowse.Add(nodeToBrowse2); // fetch references from the server. - ReferenceDescriptionCollection references = FormUtils.Browse( m_session, nodesToBrowse, false ); + ReferenceDescriptionCollection references = FormUtils.Browse(m_session, nodesToBrowse, false); - return references.ToArray( ); + return references.ToArray(); } #endregion BrowseNode Support @@ -1161,25 +1208,25 @@ public ReferenceDescription[] BrowseNodeReference( string tag ) /// /// 节点信息 /// 节点的特性值 - public OpcNodeAttribute[] ReadNoteAttributes( string tag ) + public OpcNodeAttribute[] ReadNoteAttributes(string tag) { - NodeId sourceId = new NodeId( tag ); - ReadValueIdCollection nodesToRead = new ReadValueIdCollection( ); + NodeId sourceId = new NodeId(tag); + ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); // attempt to read all possible attributes. // 尝试着去读取所有可能的特性 - for (uint ii = Attributes.NodeClass; ii <= Attributes.UserExecutable; ii++) + for (uint ii = Opc.Ua.Attributes.NodeClass; ii <= Opc.Ua.Attributes.UserExecutable; ii++) { - ReadValueId nodeToRead = new ReadValueId( ); + ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = sourceId; nodeToRead.AttributeId = ii; - nodesToRead.Add( nodeToRead ); + nodesToRead.Add(nodeToRead); } int startOfProperties = nodesToRead.Count; // find all of the pror of the node. - BrowseDescription nodeToBrowse1 = new BrowseDescription( ); + BrowseDescription nodeToBrowse1 = new BrowseDescription(); nodeToBrowse1.NodeId = sourceId; nodeToBrowse1.BrowseDirection = BrowseDirection.Forward; @@ -1188,11 +1235,11 @@ public OpcNodeAttribute[] ReadNoteAttributes( string tag ) nodeToBrowse1.NodeClassMask = 0; nodeToBrowse1.ResultMask = (uint)BrowseResultMask.All; - BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection( ); - nodesToBrowse.Add( nodeToBrowse1 ); + BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); + nodesToBrowse.Add(nodeToBrowse1); // fetch property references from the server. - ReferenceDescriptionCollection references = FormUtils.Browse( m_session, nodesToBrowse, false ); + ReferenceDescriptionCollection references = FormUtils.Browse(m_session, nodesToBrowse, false); if (references == null) { @@ -1207,10 +1254,10 @@ public OpcNodeAttribute[] ReadNoteAttributes( string tag ) continue; } - ReadValueId nodeToRead = new ReadValueId( ); + ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = (NodeId)references[ii].NodeId; - nodeToRead.AttributeId = Attributes.Value; - nodesToRead.Add( nodeToRead ); + nodeToRead.AttributeId = Opc.Ua.Attributes.Value; + nodesToRead.Add(nodeToRead); } // read all values. @@ -1223,17 +1270,17 @@ public OpcNodeAttribute[] ReadNoteAttributes( string tag ) TimestampsToReturn.Neither, nodesToRead, out results, - out diagnosticInfos ); + out diagnosticInfos); - ClientBase.ValidateResponse( results, nodesToRead ); - ClientBase.ValidateDiagnosticInfos( diagnosticInfos, nodesToRead ); + ClientBase.ValidateResponse(results, nodesToRead); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); // process results. - List nodeAttribute = new List( ); + List nodeAttribute = new List(); for (int ii = 0; ii < results.Count; ii++) { - OpcNodeAttribute item = new OpcNodeAttribute( ); + OpcNodeAttribute item = new OpcNodeAttribute(); // process attribute value. if (ii < startOfProperties) @@ -1245,21 +1292,21 @@ public OpcNodeAttribute[] ReadNoteAttributes( string tag ) } // get the name of the attribute. - item.Name = Attributes.GetBrowseName( nodesToRead[ii].AttributeId ); + item.Name = Opc.Ua.Attributes.GetBrowseName(nodesToRead[ii].AttributeId); // display any unexpected error. - if (StatusCode.IsBad( results[ii].StatusCode )) + if (StatusCode.IsBad(results[ii].StatusCode)) { - item.Type = Utils.Format( "{0}", Attributes.GetDataTypeId( nodesToRead[ii].AttributeId ) ); - item.Value = Utils.Format( "{0}", results[ii].StatusCode ); + item.Type = Utils.Format("{0}", Opc.Ua.Attributes.GetDataTypeId(nodesToRead[ii].AttributeId)); + item.Value = Utils.Format("{0}", results[ii].StatusCode); } // display the value. else { - TypeInfo typeInfo = TypeInfo.Construct( results[ii].Value ); + TypeInfo typeInfo = TypeInfo.Construct(results[ii].Value); - item.Type = typeInfo.BuiltInType.ToString( ); + item.Type = typeInfo.BuiltInType.ToString(); if (typeInfo.ValueRank >= ValueRanks.OneOrMoreDimensions) { @@ -1280,21 +1327,21 @@ public OpcNodeAttribute[] ReadNoteAttributes( string tag ) } // get the name of the property. - item.Name = Utils.Format( "{0}", references[ii - startOfProperties] ); + item.Name = Utils.Format("{0}", references[ii - startOfProperties]); // display any unexpected error. - if (StatusCode.IsBad( results[ii].StatusCode )) + if (StatusCode.IsBad(results[ii].StatusCode)) { item.Type = String.Empty; - item.Value = Utils.Format( "{0}", results[ii].StatusCode ); + item.Value = Utils.Format("{0}", results[ii].StatusCode); } // display the value. else { - TypeInfo typeInfo = TypeInfo.Construct( results[ii].Value ); + TypeInfo typeInfo = TypeInfo.Construct(results[ii].Value); - item.Type = typeInfo.BuiltInType.ToString( ); + item.Type = typeInfo.BuiltInType.ToString(); if (typeInfo.ValueRank >= ValueRanks.OneOrMoreDimensions) { @@ -1305,10 +1352,10 @@ public OpcNodeAttribute[] ReadNoteAttributes( string tag ) } } - nodeAttribute.Add( item ); + nodeAttribute.Add(item); } - return nodeAttribute.ToArray( ); + return nodeAttribute.ToArray(); } /// @@ -1316,25 +1363,25 @@ public OpcNodeAttribute[] ReadNoteAttributes( string tag ) /// /// 节点值 /// 所有的数据 - public DataValue[] ReadNoteDataValueAttributes( string tag ) + public DataValue[] ReadNoteDataValueAttributes(string tag) { - NodeId sourceId = new NodeId( tag ); - ReadValueIdCollection nodesToRead = new ReadValueIdCollection( ); + NodeId sourceId = new NodeId(tag); + ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); // attempt to read all possible attributes. // 尝试着去读取所有可能的特性 - for (uint ii = Attributes.NodeId; ii <= Attributes.UserExecutable; ii++) + for (uint ii = Opc.Ua.Attributes.NodeId; ii <= Opc.Ua.Attributes.UserExecutable; ii++) { - ReadValueId nodeToRead = new ReadValueId( ); + ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = sourceId; nodeToRead.AttributeId = ii; - nodesToRead.Add( nodeToRead ); + nodesToRead.Add(nodeToRead); } int startOfProperties = nodesToRead.Count; // find all of the pror of the node. - BrowseDescription nodeToBrowse1 = new BrowseDescription( ); + BrowseDescription nodeToBrowse1 = new BrowseDescription(); nodeToBrowse1.NodeId = sourceId; nodeToBrowse1.BrowseDirection = BrowseDirection.Forward; @@ -1343,11 +1390,11 @@ public DataValue[] ReadNoteDataValueAttributes( string tag ) nodeToBrowse1.NodeClassMask = 0; nodeToBrowse1.ResultMask = (uint)BrowseResultMask.All; - BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection( ); - nodesToBrowse.Add( nodeToBrowse1 ); + BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); + nodesToBrowse.Add(nodeToBrowse1); // fetch property references from the server. - ReferenceDescriptionCollection references = FormUtils.Browse( m_session, nodesToBrowse, false ); + ReferenceDescriptionCollection references = FormUtils.Browse(m_session, nodesToBrowse, false); if (references == null) { @@ -1362,10 +1409,10 @@ public DataValue[] ReadNoteDataValueAttributes( string tag ) continue; } - ReadValueId nodeToRead = new ReadValueId( ); + ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = (NodeId)references[ii].NodeId; - nodeToRead.AttributeId = Attributes.Value; - nodesToRead.Add( nodeToRead ); + nodeToRead.AttributeId = Opc.Ua.Attributes.Value; + nodesToRead.Add(nodeToRead); } // read all values. @@ -1378,12 +1425,12 @@ public DataValue[] ReadNoteDataValueAttributes( string tag ) TimestampsToReturn.Neither, nodesToRead, out results, - out diagnosticInfos ); + out diagnosticInfos); - ClientBase.ValidateResponse( results, nodesToRead ); - ClientBase.ValidateDiagnosticInfos( diagnosticInfos, nodesToRead ); + ClientBase.ValidateResponse(results, nodesToRead); + ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); - return results.ToArray( ); + return results.ToArray(); } #endregion Read Attributes Support @@ -1397,7 +1444,7 @@ public DataValue[] ReadNoteDataValueAttributes( string tag ) /// 方法的节点tag /// 传递的参数 /// 输出的结果值 - public object[] CallMethodByNodeId( string tagParent, string tag, params object[] args ) + public object[] CallMethodByNodeId(string tagParent, string tag, params object[] args) { if (m_session == null) { @@ -1405,11 +1452,11 @@ public object[] CallMethodByNodeId( string tagParent, string tag, params object[ } IList outputArguments = m_session.Call( - new NodeId( tagParent ), - new NodeId( tag ), - args ); + new NodeId(tagParent), + new NodeId(tag), + args); - return outputArguments.ToArray( ); + return outputArguments.ToArray(); } #endregion Method Call Support @@ -1419,28 +1466,29 @@ public object[] CallMethodByNodeId( string tagParent, string tag, params object[ /// /// Raises the connect complete event on the main GUI thread. /// - private void DoConnectComplete( object state ) + private void DoConnectComplete(object state) { - m_ConnectComplete?.Invoke( this, null ); + m_ConnectComplete?.Invoke(this, null); } - private void CheckReturnValue( StatusCode status ) + private void CheckReturnValue(StatusCode status) { - if (!StatusCode.IsGood( status )) - throw new Exception( string.Format( "Invalid response from the server. (Response Status: {0})", status ) ); + if (!StatusCode.IsGood(status)) + throw new Exception(string.Format("Invalid response from the server. (Response Status: {0})", status)); } #endregion Private Methods #region Private Fields + private ApplicationInstance application; private ApplicationConfiguration m_configuration; - private Session m_session; + private ISession m_session; private bool m_IsConnected; //是否已经连接过 private int m_reconnectPeriod = 10; // 重连状态 private bool m_useSecurity; - private SessionReconnectHandler m_reConnectHandler; + private SessionReconnectHandler m_reconnectHandler; private EventHandler m_ReconnectComplete; private EventHandler m_ReconnectStarting; private EventHandler m_KeepAliveComplete; @@ -1451,4 +1499,4 @@ private void CheckReturnValue( StatusCode status ) #endregion Private Fields } -} \ No newline at end of file +}