public static LogEntry For(DeleteSubscriptionsRequest request) { LogEntry entry = new LogEntry("DeleteSubscriptionsRequest"); entry.Add("RequestHeader", For(request.RequestHeader)); entry.Add("SubscriptionIds", For(request.SubscriptionIds)); return(entry); }
public async Task DeleteDataSubscriptionAsync() { var deleteSubRequest = new DeleteSubscriptionsRequest { SubscriptionIds = subscriptions.ToArray() }; var deleteSubResponse = await channel.DeleteSubscriptionsAsync(deleteSubRequest); _logger.LogInformation($"Deleted Subscriptions '{subscriptions[0]}' at {DateTime.Now}."); subscriptions.RemoveAt(0); }
/// <summary> /// Sends publish requests to the server. /// </summary> /// <param name="token">A cancellation token.</param> /// <returns>A task.</returns> internal async Task PublishAsync(CancellationToken token = default(CancellationToken)) { var publishRequest = new PublishRequest { RequestHeader = new RequestHeader { TimeoutHint = PublishTimeoutHint, ReturnDiagnostics = this.DiagnosticsHint }, SubscriptionAcknowledgements = new SubscriptionAcknowledgement[0] }; while (!token.IsCancellationRequested) { try { var publishResponse = await this.PublishAsync(publishRequest).ConfigureAwait(false); // Views and view models may be abandoned at any time. This code detects when a subscription // is garbage collected, and deletes the corresponding subscription from the server. publishResponse.MoreNotifications = true; // set flag indicates message unhandled. this.publishEvent.Publish(publishResponse); // If event was not handled, if (publishResponse.MoreNotifications) { // subscription was garbage collected. So delete from server. var request = new DeleteSubscriptionsRequest { SubscriptionIds = new uint[] { publishResponse.SubscriptionId } }; await this.DeleteSubscriptionsAsync(request).ConfigureAwait(false); } publishRequest = new PublishRequest { RequestHeader = new RequestHeader { TimeoutHint = PublishTimeoutHint, ReturnDiagnostics = this.DiagnosticsHint }, SubscriptionAcknowledgements = new[] { new SubscriptionAcknowledgement { SequenceNumber = publishResponse.NotificationMessage.SequenceNumber, SubscriptionId = publishResponse.SubscriptionId } } }; } catch (ServiceResultException ex) { if (!token.IsCancellationRequested) { Trace.TraceWarning($"UaTcpSessionClient error publishing subscription. {ex.Message}"); // short delay, then retry. await Task.Delay((int)DefaultPublishingInterval).ConfigureAwait(false); } } } }
public async Task DeleteSubscriptionsAsync() { var response = new DeleteSubscriptionsResponse(); var request = new DeleteSubscriptionsRequest(); var channel = new TestRequestChannel(response); var ret = await channel.DeleteSubscriptionsAsync(request); ret .Should().BeSameAs(response); channel.Request .Should().BeSameAs(request); }
/// <summary> /// 删除订阅关系 /// </summary> /// <param name="req"><see cref="DeleteSubscriptionsRequest"/></param> /// <returns><see cref="DeleteSubscriptionsResponse"/></returns> public DeleteSubscriptionsResponse DeleteSubscriptionsSync(DeleteSubscriptionsRequest req) { JsonResponseModel <DeleteSubscriptionsResponse> rsp = null; try { var strResp = this.InternalRequestSync(req, "DeleteSubscriptions"); rsp = JsonConvert.DeserializeObject <JsonResponseModel <DeleteSubscriptionsResponse> >(strResp); } catch (JsonSerializationException e) { throw new TencentCloudSDKException(e.Message); } return(rsp.Response); }
/// <summary> /// The state machine manages the state of the subscription. /// </summary> /// <param name="token">A cancellation token.</param> /// <returns>A task.</returns> private async Task StateMachineAsync(CancellationToken token = default(CancellationToken)) { while (!token.IsCancellationRequested) { await this.whenSubscribed.Task; this.progress.Report(CommunicationState.Opening); try { // get a channel. this.innerChannel = await this.application.GetChannelAsync(this.endpointUrl, token); try { // create the subscription. var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = this.publishingInterval, RequestedMaxKeepAliveCount = this.keepAliveCount, RequestedLifetimeCount = Math.Max(this.lifetimeCount, 3 * this.keepAliveCount), PublishingEnabled = true }; var subscriptionResponse = await this.innerChannel.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(true); // link up the dataflow blocks var id = this.subscriptionId = subscriptionResponse.SubscriptionId; var linkToken = this.innerChannel.LinkTo(this.actionBlock, pr => pr.SubscriptionId == id); try { // create the monitored items. var items = this.monitoredItems.ToList(); if (items.Count > 0) { var requests = items.Select(m => new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = m.NodeId, AttributeId = m.AttributeId, IndexRange = m.IndexRange }, MonitoringMode = m.MonitoringMode, RequestedParameters = new MonitoringParameters { ClientHandle = m.ClientId, DiscardOldest = m.DiscardOldest, QueueSize = m.QueueSize, SamplingInterval = m.SamplingInterval, Filter = m.Filter } }).ToArray(); var itemsRequest = new CreateMonitoredItemsRequest { SubscriptionId = id, ItemsToCreate = requests, }; var itemsResponse = await this.innerChannel.CreateMonitoredItemsAsync(itemsRequest); for (int i = 0; i < itemsResponse.Results.Length; i++) { var item = items[i]; var result = itemsResponse.Results[i]; item.OnCreateResult(result); if (StatusCode.IsBad(result.StatusCode)) { this.logger?.LogError($"Error creating MonitoredItem for {item.NodeId}. {StatusCodes.GetDefaultMessage(result.StatusCode)}"); } } } this.progress.Report(CommunicationState.Opened); // wait here until channel is closing, unsubscribed or token cancelled. try { await Task.WhenAny( this.WhenChannelClosingAsync(this.innerChannel, token), this.whenUnsubscribed.Task); } catch { } finally { this.progress.Report(CommunicationState.Closing); } } catch (Exception ex) { this.logger?.LogError($"Error creating MonitoredItems. {ex.Message}"); this.progress.Report(CommunicationState.Faulted); } finally { linkToken.Dispose(); } if (this.innerChannel.State == CommunicationState.Opened) { try { // delete the subscription. var deleteRequest = new DeleteSubscriptionsRequest { SubscriptionIds = new uint[] { id } }; await this.innerChannel.DeleteSubscriptionsAsync(deleteRequest); } catch (Exception ex) { this.logger?.LogError($"Error deleting subscription. {ex.Message}"); await Task.Delay(2000); } } this.progress.Report(CommunicationState.Closed); } catch (Exception ex) { this.logger?.LogError($"Error creating subscription. {ex.Message}"); this.progress.Report(CommunicationState.Faulted); await Task.Delay(2000); } } catch (Exception ex) { this.logger?.LogTrace($"Error getting channel. {ex.Message}"); this.progress.Report(CommunicationState.Faulted); await Task.Delay(2000); } } }
/// <summary> /// Creates the subscriptions on the server. /// </summary> /// <param name="token">A cancellation token. </param> /// <returns>A task.</returns> private async Task AutoCreateSubscriptionsAsync(CancellationToken token = default(CancellationToken)) { var tcs = new TaskCompletionSource <bool>(); NotifyCollectionChangedEventHandler handler = async(o, e) => { if (e.Action == NotifyCollectionChangedAction.Add) { foreach (var subscription in e.NewItems.OfType <Subscription>()) { var target = subscription.Target; if (target == null) { continue; } try { // create the subscription. var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = subscription.PublishingInterval, RequestedMaxKeepAliveCount = subscription.KeepAliveCount, RequestedLifetimeCount = Math.Max(subscription.LifetimeCount, 3 * subscription.KeepAliveCount), PublishingEnabled = subscription.PublishingEnabled }; var subscriptionResponse = await this.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false); var id = subscription.SubscriptionId = subscriptionResponse.SubscriptionId; // add the items. if (subscription.MonitoredItems.Count > 0) { var items = subscription.MonitoredItems.ToList(); var requests = items.Select(m => new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = m.NodeId, AttributeId = m.AttributeId, IndexRange = m.IndexRange }, MonitoringMode = m.MonitoringMode, RequestedParameters = new MonitoringParameters { ClientHandle = m.ClientId, DiscardOldest = m.DiscardOldest, QueueSize = m.QueueSize, SamplingInterval = m.SamplingInterval, Filter = m.Filter } }).ToArray(); var itemsRequest = new CreateMonitoredItemsRequest { SubscriptionId = id, ItemsToCreate = requests, }; var itemsResponse = await this.CreateMonitoredItemsAsync(itemsRequest).ConfigureAwait(false); for (int i = 0; i < itemsResponse.Results.Length; i++) { var item = items[i]; var result = itemsResponse.Results[i]; item.OnCreateResult(target, result); if (StatusCode.IsBad(result.StatusCode)) { this.Logger?.LogError($"Error creating MonitoredItem for {item.NodeId}. {StatusCodes.GetDefaultMessage(result.StatusCode)}"); } } } } catch (ServiceResultException ex) { this.Logger?.LogError($"Error creating subscription. {ex.Message}"); this.innerChannel.Fault(ex); } } } else if (e.Action == NotifyCollectionChangedAction.Remove) { try { // delete the subscriptions. var request = new DeleteSubscriptionsRequest { SubscriptionIds = e.OldItems.OfType <Subscription>().Select(s => s.SubscriptionId).ToArray() }; await this.DeleteSubscriptionsAsync(request).ConfigureAwait(false); } catch (ServiceResultException ex) { this.Logger?.LogError($"Error deleting subscriptions. {ex.Message}"); } } }; using (token.Register(state => ((TaskCompletionSource <bool>)state).TrySetResult(true), tcs, false)) { try { handler.Invoke(this.subscriptions, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, this.subscriptions.ToList())); this.subscriptions.CollectionChanged += handler; await tcs.Task; } finally { this.subscriptions.CollectionChanged -= handler; foreach (var subscription in this.subscriptions) { subscription.SubscriptionId = 0; } } } }
internal async Task SubscribeAsync(CancellationToken token = default(CancellationToken)) { while (!token.IsCancellationRequested) { await whenSubscribed.Task; progress.Report(CommunicationState.Opening); try { try { var linkToken = await CreateSubscriptionAsync(); try { //Add items to the subscription...using AddTagAsync progress.Report(CommunicationState.Opened); try { await Task.WhenAny(opcConnection.WhenChannelClosingAsync(opcConnection.Channel, token), whenUnsubscribed.Task); } catch { } finally { progress.Report(CommunicationState.Closing); } } catch (Exception ex) { logger?.LogError($"Error creating MonitoredItems. {ex.Message}"); progress.Report(CommunicationState.Faulted); } finally { linkToken.Dispose(); } if (opcConnection.Channel.State == CommunicationState.Opened) { try { var deleteRequest = new DeleteSubscriptionsRequest { SubscriptionIds = new uint[] { subscriptionId } }; await opcConnection.Channel.DeleteSubscriptionsAsync(deleteRequest); } catch (Exception ex) { this.logger?.LogError($"Error deleting subscription. {ex.Message}"); await Task.Delay(2000); } } progress.Report(CommunicationState.Closed); } catch (Exception ex) { this.logger?.LogError($"Error creating subscription. {ex.Message}"); this.progress.Report(CommunicationState.Faulted); await Task.Delay(2000); } } catch (Exception ex) { this.logger?.LogTrace($"Error getting channel. {ex.Message}"); this.progress.Report(CommunicationState.Faulted); await Task.Delay(2000); } } }
/// <summary> /// The state machine manages the state of the subscription. /// </summary> /// <param name="token">A cancellation token.</param> /// <returns>A task.</returns> private async Task StateMachineAsync(CancellationToken token = default) { while (!token.IsCancellationRequested) { await this.whenSubscribed.Task; this.progress.Report(CommunicationState.Opening); try { if (this.endpointUrl is null) { throw new InvalidOperationException("The endpointUrl field must not be null. Please, use the Subscription attribute properly."); } // get a channel. this.innerChannel = await this.application.GetChannelAsync(this.endpointUrl, token); try { // create the subscription. var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = this.publishingInterval, RequestedMaxKeepAliveCount = this.keepAliveCount, RequestedLifetimeCount = Math.Max(this.lifetimeCount, 3 * this.keepAliveCount), PublishingEnabled = true }; var subscriptionResponse = await this.innerChannel.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false); // link up the dataflow blocks var id = this.subscriptionId = subscriptionResponse.SubscriptionId; var linkToken = this.innerChannel.LinkTo(this.actionBlock, pr => pr.SubscriptionId == id); try { // create the monitored items. var items = this.monitoredItems.ToList(); if (items.Count > 0) { var requests = items.Select(m => new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = ExpandedNodeId.ToNodeId(m.NodeId, this.InnerChannel.NamespaceUris), AttributeId = m.AttributeId, IndexRange = m.IndexRange }, MonitoringMode = m.MonitoringMode, RequestedParameters = new MonitoringParameters { ClientHandle = m.ClientId, DiscardOldest = m.DiscardOldest, QueueSize = m.QueueSize, SamplingInterval = m.SamplingInterval, Filter = m.Filter } }).ToArray(); //split requests array to MaxMonitoredItemsPerCall chunks int maxmonitoreditemspercall = 100; MonitoredItemCreateRequest[] requests_chunk; int chunk_size; for (int i_chunk = 0; i_chunk < requests.Length; i_chunk += maxmonitoreditemspercall) { chunk_size = Math.Min(maxmonitoreditemspercall, requests.Length - i_chunk); requests_chunk = new MonitoredItemCreateRequest[chunk_size]; Array.Copy(requests, i_chunk, requests_chunk, 0, chunk_size); var itemsRequest = new CreateMonitoredItemsRequest { SubscriptionId = id, ItemsToCreate = requests_chunk, }; var itemsResponse = await this.innerChannel.CreateMonitoredItemsAsync(itemsRequest); if (itemsResponse.Results is { } results) { for (int i = 0; i < results.Length; i++) { var item = items[i]; var result = results[i]; if (result is null) { this.logger?.LogError($"Error creating MonitoredItem for {item.NodeId}. The result is null."); continue; } item.OnCreateResult(result); if (StatusCode.IsBad(result.StatusCode)) { this.logger?.LogError($"Error creating MonitoredItem for {item.NodeId}. {StatusCodes.GetDefaultMessage(result.StatusCode)}"); } } } } } this.progress.Report(CommunicationState.Opened); // wait here until channel is closing, unsubscribed or token cancelled. try { await Task.WhenAny( this.WhenChannelClosingAsync(this.innerChannel, token), this.whenUnsubscribed.Task); } catch { } finally { this.progress.Report(CommunicationState.Closing); } } catch (Exception ex) { this.logger?.LogError($"Error creating MonitoredItems. {ex.Message}"); this.progress.Report(CommunicationState.Faulted); } finally { linkToken.Dispose(); } if (this.innerChannel.State == CommunicationState.Opened) { try { // delete the subscription. var deleteRequest = new DeleteSubscriptionsRequest { SubscriptionIds = new uint[] { id } }; await this.innerChannel.DeleteSubscriptionsAsync(deleteRequest); } catch (Exception ex) { this.logger?.LogError($"Error deleting subscription. {ex.Message}"); await Task.Delay(2000); } } this.progress.Report(CommunicationState.Closed); } catch (Exception ex) { this.logger?.LogError($"Error creating subscription. {ex.Message}"); this.progress.Report(CommunicationState.Faulted); await Task.Delay(2000); } } catch (Exception ex) { this.logger?.LogTrace($"Error getting channel. {ex.Message}"); this.progress.Report(CommunicationState.Faulted); await Task.Delay(2000); } } }
private static async Task TestAsync() { var loggerFactory = new LoggerFactory(); loggerFactory.AddDebug(LogLevel.Trace); var discoveryUrl = "opc.tcp://localhost:26543"; // Workstation.NodeServer //var discoveryUrl = "opc.tcp://localhost:48010"; // UaCppServer - see http://www.unified-automation.com/ //var discoveryUrl = "opc.tcp://localhost:16664"; // open62541 Console.WriteLine("Step 1 - Describe this app."); var appDescription = new ApplicationDescription() { ApplicationName = "MyHomework", ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:MyHomework", ApplicationType = ApplicationType.Client, }; Console.WriteLine("Step 2 - Create a certificate store."); var certificateStore = new DirectoryStore( Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Workstation.ConsoleApp", "pki")); Console.WriteLine("Step 3 - Create a session with your server."); var channel = new UaTcpSessionChannel( appDescription, certificateStore, ShowSignInDialog, discoveryUrl, loggerFactory: loggerFactory); try { await channel.OpenAsync(); Console.WriteLine($" Opened channel with endpoint '{channel.RemoteEndpoint.EndpointUrl}'."); Console.WriteLine($" SecurityPolicyUri: '{channel.RemoteEndpoint.SecurityPolicyUri}'."); Console.WriteLine($" SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'."); Console.WriteLine($" UserIdentity: '{channel.UserIdentity}'."); Console.WriteLine("Press any key to continue..."); Console.ReadKey(true); Console.WriteLine("Step 4 - Browse the server namespace."); Console.WriteLine("+ Root"); BrowseRequest browseRequest = new BrowseRequest { NodesToBrowse = new BrowseDescription[] { new BrowseDescription { NodeId = NodeId.Parse(ObjectIds.RootFolder), BrowseDirection = BrowseDirection.Forward, ReferenceTypeId = NodeId.Parse(ReferenceTypeIds.HierarchicalReferences), NodeClassMask = (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, IncludeSubtypes = true, ResultMask = (uint)BrowseResultMask.All } }, }; BrowseResponse browseResponse = await channel.BrowseAsync(browseRequest); foreach (var rd1 in browseResponse.Results[0].References ?? new ReferenceDescription[0]) { Console.WriteLine(" + {0}: {1}, {2}", rd1.DisplayName, rd1.BrowseName, rd1.NodeClass); browseRequest = new BrowseRequest { NodesToBrowse = new BrowseDescription[] { new BrowseDescription { NodeId = ExpandedNodeId.ToNodeId(rd1.NodeId, channel.NamespaceUris), BrowseDirection = BrowseDirection.Forward, ReferenceTypeId = NodeId.Parse(ReferenceTypeIds.HierarchicalReferences), NodeClassMask = (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, IncludeSubtypes = true, ResultMask = (uint)BrowseResultMask.All } }, }; browseResponse = await channel.BrowseAsync(browseRequest); foreach (var rd2 in browseResponse.Results[0].References ?? new ReferenceDescription[0]) { Console.WriteLine(" + {0}: {1}, {2}", rd2.DisplayName, rd2.BrowseName, rd2.NodeClass); browseRequest = new BrowseRequest { NodesToBrowse = new BrowseDescription[] { new BrowseDescription { NodeId = ExpandedNodeId.ToNodeId(rd2.NodeId, channel.NamespaceUris), BrowseDirection = BrowseDirection.Forward, ReferenceTypeId = NodeId.Parse(ReferenceTypeIds.HierarchicalReferences), NodeClassMask = (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, IncludeSubtypes = true, ResultMask = (uint)BrowseResultMask.All } }, }; browseResponse = await channel.BrowseAsync(browseRequest); foreach (var rd3 in browseResponse.Results[0].References ?? new ReferenceDescription[0]) { Console.WriteLine(" + {0}: {1}, {2}", rd3.DisplayName, rd3.BrowseName, rd3.NodeClass); } } } Console.WriteLine("Press any key to continue..."); Console.ReadKey(true); Console.WriteLine("Step 5 - Create a subscription."); var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = 1000, RequestedMaxKeepAliveCount = 10, RequestedLifetimeCount = 30, PublishingEnabled = true }; var subscriptionResponse = await channel.CreateSubscriptionAsync(subscriptionRequest); var id = subscriptionResponse.SubscriptionId; Console.WriteLine("Step 6 - Add items to the subscription."); var itemsToCreate = new MonitoredItemCreateRequest[] { new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("i=2258"), AttributeId = AttributeIds.Value }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 12345, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } } }; var itemsRequest = new CreateMonitoredItemsRequest { SubscriptionId = id, ItemsToCreate = itemsToCreate, }; var itemsResponse = await channel.CreateMonitoredItemsAsync(itemsRequest); Console.WriteLine("Step 7 - Subscribe to PublishResponse stream."); var token = channel.Where(pr => pr.SubscriptionId == id).Subscribe(pr => { // loop thru all the data change notifications var dcns = pr.NotificationMessage.NotificationData.OfType <DataChangeNotification>(); foreach (var dcn in dcns) { foreach (var min in dcn.MonitoredItems) { Console.WriteLine($"sub: {pr.SubscriptionId}; handle: {min.ClientHandle}; value: {min.Value}"); } } }); Console.WriteLine("Press any key to delete the subscription..."); while (!Console.KeyAvailable) { await Task.Delay(500); } Console.ReadKey(true); Console.WriteLine("Step 8 - Delete the subscription."); var request = new DeleteSubscriptionsRequest { SubscriptionIds = new uint[] { id } }; await channel.DeleteSubscriptionsAsync(request); token.Dispose(); Console.WriteLine("Press any key to close the session..."); Console.ReadKey(true); Console.WriteLine("Step 9 - Close the session."); await channel.CloseAsync(); } catch (ServiceResultException ex) { if ((uint)ex.HResult == StatusCodes.BadSecurityChecksFailed) { Console.WriteLine("Error connecting to endpoint. Did the server reject our certificate?"); } await channel.AbortAsync(); throw; } }
/// <summary> /// Deletes one or more Subscriptions. /// </summary> /// <param name="channel">A instance of <see cref="IRequestChannel"/>.</param> /// <param name="request">A <see cref="DeleteSubscriptionsRequest"/>.</param> /// <returns>A <see cref="Task"/> representing the asynchronous operation that returns a <see cref="DeleteSubscriptionsResponse"/>.</returns> public static async Task <DeleteSubscriptionsResponse> DeleteSubscriptionsAsync(this IRequestChannel channel, DeleteSubscriptionsRequest request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } return((DeleteSubscriptionsResponse)await channel.RequestAsync(request).ConfigureAwait(false)); }
/// <summary> /// Begins an asynchronous invocation of the DeleteSubscriptions service. /// </summary> public IAsyncResult BeginDeleteSubscriptions( RequestHeader requestHeader, UInt32Collection subscriptionIds, AsyncCallback callback, object asyncState) { DeleteSubscriptionsRequest request = new DeleteSubscriptionsRequest(); request.RequestHeader = requestHeader; request.SubscriptionIds = subscriptionIds; UpdateRequestHeader(request, requestHeader == null, "DeleteSubscriptions"); if (UseTransportChannel) { return TransportChannel.BeginSendRequest(request, callback, asyncState); } return InnerChannel.BeginDeleteSubscriptions(new DeleteSubscriptionsMessage(request), callback, asyncState); }
/// <summary> /// Invokes the DeleteSubscriptions service. /// </summary> public virtual ResponseHeader DeleteSubscriptions( RequestHeader requestHeader, UInt32Collection subscriptionIds, out StatusCodeCollection results, out DiagnosticInfoCollection diagnosticInfos) { DeleteSubscriptionsRequest request = new DeleteSubscriptionsRequest(); DeleteSubscriptionsResponse response = null; request.RequestHeader = requestHeader; request.SubscriptionIds = subscriptionIds; UpdateRequestHeader(request, requestHeader == null, "DeleteSubscriptions"); try { if (UseTransportChannel) { IServiceResponse genericResponse = TransportChannel.SendRequest(request); if (genericResponse == null) { throw new ServiceResultException(StatusCodes.BadUnknownResponse); } ValidateResponse(genericResponse.ResponseHeader); response = (DeleteSubscriptionsResponse)genericResponse; } else { DeleteSubscriptionsResponseMessage responseMessage = InnerChannel.DeleteSubscriptions(new DeleteSubscriptionsMessage(request)); if (responseMessage == null || responseMessage.DeleteSubscriptionsResponse == null) { throw new ServiceResultException(StatusCodes.BadUnknownResponse); } response = responseMessage.DeleteSubscriptionsResponse; ValidateResponse(response.ResponseHeader); } results = response.Results; diagnosticInfos = response.DiagnosticInfos; } finally { RequestCompleted(request, response, "DeleteSubscriptions"); } return response.ResponseHeader; }
private static async Task ConnectAndPublish(CancellationToken token = default) { var discoveryUrl = "opc.tcp://localhost:48010"; // UaCppServer - see http://www.unified-automation.com/ var appDescription = new ApplicationDescription() { ApplicationName = "MyHomework", ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:MyHomework", ApplicationType = ApplicationType.Client, }; var certificateStore = new DirectoryStore( Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Workstation.ConsoleApp", "pki")); while (!token.IsCancellationRequested) { var channel = new UaTcpSessionChannel( appDescription, certificateStore, new AnonymousIdentity(), discoveryUrl); try { await channel.OpenAsync(); var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = 1000, RequestedMaxKeepAliveCount = 10, RequestedLifetimeCount = 30, PublishingEnabled = true }; var subscriptionResponse = await channel.CreateSubscriptionAsync(subscriptionRequest); var id = subscriptionResponse.SubscriptionId; var itemsToCreate = new MonitoredItemCreateRequest[] { new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("i=2258"), AttributeId = AttributeIds.Value }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 12345, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } } }; var itemsRequest = new CreateMonitoredItemsRequest { SubscriptionId = id, ItemsToCreate = itemsToCreate, }; var itemsResponse = await channel.CreateMonitoredItemsAsync(itemsRequest); var subtoken = channel.Where(pr => pr.SubscriptionId == id).Subscribe( pr => { var dcns = pr.NotificationMessage.NotificationData.OfType <DataChangeNotification>(); foreach (var dcn in dcns) { foreach (var min in dcn.MonitoredItems) { Console.WriteLine($"sub: {pr.SubscriptionId}; handle: {min.ClientHandle}; value: {min.Value}"); } } }, // need to handle error when server closes ex => { }); try { Task.WaitAny(new Task[] { channel.Completion }, token); } catch (OperationCanceledException) { } var request = new DeleteSubscriptionsRequest { SubscriptionIds = new uint[] { id } }; await channel.DeleteSubscriptionsAsync(request); subtoken.Dispose(); await channel.CloseAsync(); } catch (Exception ex) { Console.WriteLine($"Error connecting and publishing. {ex.Message}"); await channel.AbortAsync(); try { await Task.Delay(5000, token); } catch (TaskCanceledException) { } } } }
private static async Task TestAsync() { var discoveryUrl = "opc.tcp://*****:*****@"%LOCALAPPDATA%\Workstation.ConsoleApp\pki")), userIdentity, remoteEndpoint)) { try { await session.OpenAsync(); } catch (ServiceResultException ex) { if ((uint)ex.HResult == StatusCodes.BadSecurityChecksFailed) { Console.WriteLine("Error connecting to endpoint. Did the server reject our certificate?"); } throw ex; } Console.WriteLine("Step 5 - Browse the server namespace."); Console.WriteLine("+ Root"); BrowseRequest browseRequest = new BrowseRequest { NodesToBrowse = new BrowseDescription[] { new BrowseDescription { NodeId = NodeId.Parse(ObjectIds.RootFolder), BrowseDirection = BrowseDirection.Forward, ReferenceTypeId = NodeId.Parse(ReferenceTypeIds.HierarchicalReferences), NodeClassMask = (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, IncludeSubtypes = true, ResultMask = (uint)BrowseResultMask.All } }, }; BrowseResponse browseResponse = await session.BrowseAsync(browseRequest); foreach (var rd1 in browseResponse.Results[0].References ?? new ReferenceDescription[0]) { Console.WriteLine(" + {0}: {1}, {2}", rd1.DisplayName, rd1.BrowseName, rd1.NodeClass); browseRequest = new BrowseRequest { NodesToBrowse = new BrowseDescription[] { new BrowseDescription { NodeId = ExpandedNodeId.ToNodeId(rd1.NodeId, session.NamespaceUris), BrowseDirection = BrowseDirection.Forward, ReferenceTypeId = NodeId.Parse(ReferenceTypeIds.HierarchicalReferences), NodeClassMask = (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, IncludeSubtypes = true, ResultMask = (uint)BrowseResultMask.All } }, }; browseResponse = await session.BrowseAsync(browseRequest); foreach (var rd2 in browseResponse.Results[0].References ?? new ReferenceDescription[0]) { Console.WriteLine(" + {0}: {1}, {2}", rd2.DisplayName, rd2.BrowseName, rd2.NodeClass); browseRequest = new BrowseRequest { NodesToBrowse = new BrowseDescription[] { new BrowseDescription { NodeId = ExpandedNodeId.ToNodeId(rd2.NodeId, session.NamespaceUris), BrowseDirection = BrowseDirection.Forward, ReferenceTypeId = NodeId.Parse(ReferenceTypeIds.HierarchicalReferences), NodeClassMask = (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, IncludeSubtypes = true, ResultMask = (uint)BrowseResultMask.All } }, }; browseResponse = await session.BrowseAsync(browseRequest); foreach (var rd3 in browseResponse.Results[0].References ?? new ReferenceDescription[0]) { Console.WriteLine(" + {0}: {1}, {2}", rd3.DisplayName, rd3.BrowseName, rd3.NodeClass); } } } Console.WriteLine("Press any key to continue..."); Console.ReadKey(true); Console.WriteLine("Step 6 - Create a subscription."); var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = 1000, RequestedMaxKeepAliveCount = 10, RequestedLifetimeCount = 30, PublishingEnabled = true }; var subscriptionResponse = await session.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false); var id = subscriptionResponse.SubscriptionId; Console.WriteLine("Step 7 - Add items to the subscription."); var itemsToCreate = new MonitoredItemCreateRequest[] { new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("i=2258"), AttributeId = AttributeIds.Value }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 12345, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } } }; var itemsRequest = new CreateMonitoredItemsRequest { SubscriptionId = id, ItemsToCreate = itemsToCreate, }; var itemsResponse = await session.CreateMonitoredItemsAsync(itemsRequest).ConfigureAwait(false); Console.WriteLine("Step 8 - Publish the subscription."); var publishRequest = new PublishRequest { SubscriptionAcknowledgements = new SubscriptionAcknowledgement[0] }; Console.WriteLine("Press any key to delete the subscription..."); while (!Console.KeyAvailable) { var publishResponse = await session.PublishAsync(publishRequest).ConfigureAwait(false); // loop thru all the data change notifications var dcns = publishResponse.NotificationMessage.NotificationData.OfType <DataChangeNotification>(); foreach (var dcn in dcns) { foreach (var min in dcn.MonitoredItems) { Console.WriteLine($"clientHandle: {min.ClientHandle}; value: {min.Value}"); } } publishRequest = new PublishRequest { SubscriptionAcknowledgements = new[] { new SubscriptionAcknowledgement { SequenceNumber = publishResponse.NotificationMessage.SequenceNumber, SubscriptionId = publishResponse.SubscriptionId } } }; } Console.ReadKey(true); Console.WriteLine("Step 9 - Delete the subscription."); var request = new DeleteSubscriptionsRequest { SubscriptionIds = new uint[] { id } }; await session.DeleteSubscriptionsAsync(request).ConfigureAwait(false); Console.WriteLine("Press any key to close the session..."); Console.ReadKey(true); Console.WriteLine("Step 10 - Close the session."); await session.CloseAsync(); } }
/// <summary> /// Initializes the message with the body. /// </summary> public DeleteSubscriptionsMessage(DeleteSubscriptionsRequest DeleteSubscriptionsRequest) { this.DeleteSubscriptionsRequest = DeleteSubscriptionsRequest; }