public async Task TransferSubscription() { var channel1 = new UaTcpSessionChannel( localDescription, certificateStore, new UserNameIdentity("root", "secret"), EndpointUrl, loggerFactory: loggerFactory); await channel1.OpenAsync(); logger.LogInformation($"Opened session with endpoint '{channel1.RemoteEndpoint.EndpointUrl}'."); logger.LogInformation($"SecurityPolicy: '{channel1.RemoteEndpoint.SecurityPolicyUri}'."); logger.LogInformation($"SecurityMode: '{channel1.RemoteEndpoint.SecurityMode}'."); logger.LogInformation($"Activated session '{channel1.SessionId}'."); // create the keep alive subscription. var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = 1000f, RequestedMaxKeepAliveCount = 30, RequestedLifetimeCount = 30 * 3, PublishingEnabled = true, }; var subscriptionResponse = await channel1.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false); var id = subscriptionResponse.SubscriptionId; void onPublish(PublishResponse pr) { // loop thru all the data change notifications and log them. var dcns = pr.NotificationMessage.NotificationData.OfType <DataChangeNotification>(); foreach (var dcn in dcns) { foreach (var min in dcn.MonitoredItems) { logger.LogInformation($"sub: {pr.SubscriptionId}; handle: {min.ClientHandle}; value: {min.Value}"); } } } void onPublishError(Exception ex) { logger.LogInformation("Exception in publish response handler: {0}", ex.GetBaseException().Message); } var token = channel1 .Where(pr => pr.SubscriptionId == id) .Subscribe(onPublish, onPublishError); var itemsRequest = new CreateMonitoredItemsRequest { SubscriptionId = id, 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 itemsResponse = await channel1.CreateMonitoredItemsAsync(itemsRequest); await Task.Delay(3000); var channel2 = new UaTcpSessionChannel( localDescription, certificateStore, new UserNameIdentity("root", "secret"), EndpointUrl); await channel2.OpenAsync(); var token2 = channel2 .Where(pr => pr.SubscriptionId == id) .Subscribe(onPublish, onPublishError); var transferRequest = new TransferSubscriptionsRequest { SubscriptionIds = new[] { id }, SendInitialValues = true }; var transferResult = await channel2.TransferSubscriptionsAsync(transferRequest); StatusCode.IsGood(transferResult.Results[0].StatusCode) .Should().BeTrue(); logger.LogInformation($"Transfered subscriptions to new client."); await Task.Delay(3000); logger.LogInformation($"Closing session '{channel1.SessionId}'."); await channel1.CloseAsync(); logger.LogInformation($"Closing session '{channel2.SessionId}'."); await channel2.CloseAsync(); }
public async Task TransferSubscriptions() { // get or add application certificate. var localCertificate = this.localDescription.GetCertificate(); if (localCertificate == null) { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Application certificate is missing."); } // discover available endpoints of server. var getEndpointsRequest = new GetEndpointsRequest { EndpointUrl = this.endpointUrl, ProfileUris = new[] { TransportProfileUris.UaTcpTransport } }; Console.WriteLine($"Discovering endpoints of '{getEndpointsRequest.EndpointUrl}'."); var getEndpointsResponse = await UaTcpDiscoveryClient.GetEndpointsAsync(getEndpointsRequest); var selectedEndpoint = getEndpointsResponse.Endpoints.OrderBy(e => e.SecurityLevel).Last(); IUserIdentity selectedUserIdentity = new UserNameIdentity("root", "secret"); var channel = new UaTcpSessionChannel( this.localDescription, localCertificate, selectedUserIdentity, selectedEndpoint); Console.WriteLine($"Creating session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'."); Console.WriteLine($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'."); Console.WriteLine($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'."); await channel.OpenAsync(); Console.WriteLine($"Activated session '{channel.SessionId}'."); var req = new CreateSubscriptionRequest { RequestedPublishingInterval = 1000, RequestedMaxKeepAliveCount = 20, PublishingEnabled = true }; var res = await channel.CreateSubscriptionAsync(req); Console.WriteLine($"Created subscription '{res.SubscriptionId}'."); Console.WriteLine($"Aborting session '{channel.SessionId}'."); await channel.AbortAsync(); var channel2 = new UaTcpSessionChannel( this.localDescription, localCertificate, selectedUserIdentity, selectedEndpoint); await channel2.OpenAsync(); Console.WriteLine($"Activated session '{channel2.SessionId}'."); var req2 = new TransferSubscriptionsRequest { SubscriptionIds = new[] { res.SubscriptionId } }; var res2 = await channel2.TransferSubscriptionsAsync(req2); Console.WriteLine($"Transferred subscription result '{res2.Results[0].StatusCode}'."); Console.WriteLine($"Closing session '{channel2.SessionId}'."); await channel2.CloseAsync(); Assert.IsTrue(StatusCode.IsGood(res2.Results[0].StatusCode)); }