public async Task AddMonitoredItem() { var createItemsRequest = new CreateMonitoredItemsRequest { SubscriptionId = subscriptions[0], // Subscription to add to. May need to choose the subscription to add to if multiple subs per client TimestampsToReturn = TimestampsToReturn.Both, ItemsToCreate = new MonitoredItemCreateRequest[] { new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse(_clientOptions.Tag) }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 42, QueueSize = 2, DiscardOldest = true, SamplingInterval = 1000 }, }, }, }; var createItemResponse = await channel.CreateMonitoredItemsAsync(createItemsRequest); monitoredItems.Add(createItemResponse.Results[0].MonitoredItemId); _logger.LogInformation($"Monitored Item added: {monitoredItems[0]}"); tokens.Add(channel .Where(pr => pr.SubscriptionId == subscriptions[0]) // Subscription to add to. May need to choose the subscription to add to if multiple subs per client .Subscribe( pr => { 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}"); } } }, ex => _logger.LogError($"Exception in publish response handler: {ex.GetBaseException().Message}") )); }
public static async Task Run(CancellationToken cancelToken, Action onValueChanged) { var clientDescription = new ApplicationDescription { ApplicationName = "Workstation.UaClient.FeatureTests", ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:Workstation.UaClient.FeatureTests", ApplicationType = ApplicationType.Client }; var channel = new UaTcpSessionChannel( clientDescription, null, new AnonymousIdentity(), "opc.tcp://localhost:4840", SecurityPolicyUris.None ); try { await channel.OpenAsync(); // -------------------------------- var res = await channel.CreateSubscriptionAsync( new CreateSubscriptionRequest { RequestedPublishingInterval = 1000.0, // ms RequestedMaxKeepAliveCount = 30, RequestedLifetimeCount = 30 * 3, PublishingEnabled = true, }, cancelToken ); var id = res.SubscriptionId; var btnBrowseHandle = (uint)42; var rq = new CreateMonitoredItemsRequest { SubscriptionId = id, TimestampsToReturn = TimestampsToReturn.Both, ItemsToCreate = new MonitoredItemCreateRequest[] { new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::AsGlobalPV:dbgBtnBrowsePrograms"), AttributeId = AttributeIds.Value }, MonitoringMode = MonitoringMode.Reporting, // Specify a unique ClientHandle, // which will be returned in the PublishResponse. RequestedParameters = new MonitoringParameters { ClientHandle = btnBrowseHandle, QueueSize = 2, DiscardOldest = true, SamplingInterval = 1000.0 }, }, }, }; var res2 = await channel.CreateMonitoredItemsAsync(rq); var isInError = false; var token = channel // While session is open, the client sends a stream of PublishRequests to the server. // You can subscribe to all the PublishResponses. .Where(response => response.SubscriptionId == id) .Subscribe( onNext: response => { var notifications = response.NotificationMessage.NotificationData.OfType <DataChangeNotification>(); foreach (var notification in notifications) { foreach (var item in notification.MonitoredItems) { if (item.ClientHandle == btnBrowseHandle) { if ((bool)item.Value.Value) { onValueChanged(); } } } } }, onError: ex => { isInError = true; } ); while (!cancelToken.IsCancellationRequested && !isInError) { await Task.Delay(500); } await channel.CloseAsync(); } catch (Exception ex) { await channel.AbortAsync(); Console.WriteLine(ex.Message); } }
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 TestSubscription() { var channel = new UaTcpSessionChannel( localDescription, certificateStore, new AnonymousIdentity(), EndpointUrl, loggerFactory: loggerFactory); await channel.OpenAsync(); logger.LogInformation($"Opened session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'."); logger.LogInformation($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'."); logger.LogInformation($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'."); logger.LogInformation($"Activated session '{channel.SessionId}'."); var req = new CreateSubscriptionRequest { RequestedPublishingInterval = 1000.0, RequestedMaxKeepAliveCount = 30, RequestedLifetimeCount = 30 * 3, PublishingEnabled = true, }; var res = await channel.CreateSubscriptionAsync(req); var id = res.SubscriptionId; logger.LogInformation($"Created subscription '{id}'."); var req2 = new CreateMonitoredItemsRequest { SubscriptionId = id, TimestampsToReturn = TimestampsToReturn.Both, ItemsToCreate = new MonitoredItemCreateRequest[] { new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse(VariableIds.Server_ServerStatus_CurrentTime) }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 42, QueueSize = 2, DiscardOldest = true, SamplingInterval = 500.0 }, }, }, }; var res2 = await channel.CreateMonitoredItemsAsync(req2); logger.LogInformation("Subscribe to PublishResponse stream."); var numOfResponses = 0; void onPublish(PublishResponse pr) { numOfResponses++; // 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 = channel .Where(pr => pr.SubscriptionId == id) .Subscribe(onPublish, onPublishError); await Task.Delay(5000); logger.LogInformation($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); numOfResponses .Should().BeGreaterThan(0); }
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; } }
public static async Task ReadSubscribed(CancellationToken token = default(CancellationToken)) { { // setup logger var loggerFactory = new LoggerFactory(); loggerFactory.AddConsole(LogLevel.Information); //var logger = loggerFactory?.CreateLogger<Program>(); // Describe this app. var appDescription = new ApplicationDescription() { ApplicationName = "DataLoggingConsole", ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:DataLoggingConsole", ApplicationType = ApplicationType.Client, }; // Create a certificate store on disk. // Create array of NodeIds to log. while (!token.IsCancellationRequested) { try { // Discover endpoints. var getEndpointsRequest = new GetEndpointsRequest { EndpointUrl = discoveryUrl, ProfileUris = new[] { TransportProfileUris.UaTcpTransport } }; var getEndpointsResponse = await UaTcpDiscoveryService.GetEndpointsAsync(getEndpointsRequest) .ConfigureAwait(false); if (getEndpointsResponse.Endpoints == null || getEndpointsResponse.Endpoints.Length == 0) { throw new InvalidOperationException($"'{discoveryUrl}' returned no endpoints."); } // Choose the endpoint with highest security level. var remoteEndpoint = getEndpointsResponse.Endpoints.OrderBy(e => e.SecurityLevel).Last(); // Create a session with the server. var channel = new UaTcpSessionChannel(appDescription, certificateStore, async e => GetIUserIdentity(remoteEndpoint).GetAwaiter().GetResult(), remoteEndpoint, loggerFactory); 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[] { #region MonitoredItems new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Admin.ProdProcessedCount"), AttributeId = AttributeIds.Value }, //ProdProcessedCount MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 1, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Command.Parameter[0].Value"), AttributeId = AttributeIds.Value }, //Next batch ID MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 2, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Command.Parameter[1].Value"), AttributeId = AttributeIds.Value }, //Next product ID MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 3, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Command.Parameter[2].Value"), AttributeId = AttributeIds.Value }, //Amount of product in next batch MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 4, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Status.Parameter[2].Value"), AttributeId = AttributeIds.Value }, //Humidity MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 5, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Status.Parameter[3].Value"), AttributeId = AttributeIds.Value }, //Temperature MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 6, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Status.Parameter[4].Value"), AttributeId = AttributeIds.Value }, //Vibration MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 7, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Status.MachSpeed"), AttributeId = AttributeIds.Value }, //MachineSpeed MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 8, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Status.StateCurrent"), AttributeId = AttributeIds.Value }, //state MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 9, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Status.StateCurrent"), AttributeId = AttributeIds.Value }, //cmdCtrln MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 10, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } } #endregion }; var itemsRequest = new CreateMonitoredItemsRequest { SubscriptionId = id, ItemsToCreate = itemsToCreate, }; var itemsResponse = await channel.CreateMonitoredItemsAsync(itemsRequest); var subToken = channel.Where(pr => pr.SubscriptionId == id).Subscribe(pr => { // loop through all the data change notifications var dcns = pr.NotificationMessage.NotificationData.OfType <DataChangeNotification>(); foreach (var dcn in dcns) { foreach (var min in dcn.MonitoredItems) { switch (min.ClientHandle) { case 1: prodProc = (int)min.Value.Value; time = (DateTime)min.Value.ServerTimestamp; break; case 2: time = (DateTime)min.Value.ServerTimestamp; nextBatchID = (float)min.Value.Value; break; case 3: time = (DateTime)min.Value.ServerTimestamp; nextProductID = (float)min.Value.Value; break; case 4: time = (DateTime)min.Value.ServerTimestamp; nextProductAmount = (float)min.Value.Value; break; case 5: time = (DateTime)min.Value.ServerTimestamp; humidity = (float)min.Value.Value; break; case 6: time = (DateTime)min.Value.ServerTimestamp; temperature = (float)min.Value.Value; break; case 7: time = (DateTime)min.Value.ServerTimestamp; vibration = (float)min.Value.Value; break; case 8: time = (DateTime)min.Value.ServerTimestamp; machinespeed = (float)min.Value.Value; break; case 9: time = (DateTime)min.Value.ServerTimestamp; State = (int)min.Value.Value; break; case 10: cmdctrl = (int)min.Value.Value; time = (DateTime)min.Value.ServerTimestamp; break; } } } }); while (!token.IsCancellationRequested) { await Task.Delay(500); } } catch { } } catch (Exception ex) { } //try //{ // await Task.Delay(cycleTime, token); //} //catch //{ //} } } }
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) { } } } }
public async Task CreateDataSubscription() { // describe this client application. var clientDescription = new ApplicationDescription { ApplicationName = "Workstation.UaClient.FeatureTests", ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:Workstation.UaClient.FeatureTests", ApplicationType = ApplicationType.Client }; // place to store certificates var certificateStore = new DirectoryStore("./pki"); // create a 'UaTcpSessionChannel', a client-side channel that opens a 'session' with the server. var channel = new UaTcpSessionChannel( clientDescription, certificateStore, new AnonymousIdentity(), // the anonymous identity "opc.tcp://localhost:48010"); // the endpoint of Unified Automation's UaCPPServer. try { // try opening a session and reading a few nodes. await channel.OpenAsync(); Console.WriteLine($"Opened session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'."); Console.WriteLine($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'."); Console.WriteLine($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'."); Console.WriteLine($"UserIdentityToken: '{channel.UserIdentity}'."); // build a CreateSubscriptionRequest. See 'OPC UA Spec Part 4' paragraph 5.13.2 var req = new CreateSubscriptionRequest { RequestedPublishingInterval = 1000.0, // intervals are in milliseconds RequestedMaxKeepAliveCount = 30, RequestedLifetimeCount = 30 * 3, PublishingEnabled = true, }; var res = await channel.CreateSubscriptionAsync(req); // the result will return the server's subscription id. You will needs this to // add monitored items. var id = res.SubscriptionId; Console.WriteLine($"Created subscription '{id}'."); // build a CreateMonitoredItemsRequest. See 'OPC UA Spec Part 4' paragraph 5.12.2 var req2 = new CreateMonitoredItemsRequest { SubscriptionId = id, TimestampsToReturn = TimestampsToReturn.Both, ItemsToCreate = new MonitoredItemCreateRequest[] { new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse(VariableIds.Server_ServerStatus_CurrentTime) }, MonitoringMode = MonitoringMode.Reporting, // specify a unique ClientHandle. The ClientHandle is returned in the PublishResponse RequestedParameters = new MonitoringParameters { ClientHandle = 42, QueueSize = 2, DiscardOldest = true, SamplingInterval = 1000.0 }, }, }, }; var res2 = await channel.CreateMonitoredItemsAsync(req2); Console.WriteLine("\nSubscribe to PublishResponse stream."); // when the session is open, the client sends a stream of PublishRequests to the server. // You can subscribe to all the PublishResponses -or- subscribe to the responses from // a single subscription. var token = channel // receive just the subscription we just created .Where(pr => pr.SubscriptionId == id) // subscribe with an 'OnNext' function, and an 'OnError' function .Subscribe( pr => { // loop thru all the data change notifications and write them out. 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}"); } } }, ex => Console.WriteLine("Exception in publish response handler: {0}", ex.GetBaseException().Message) ); // publish for 5 seconds and then close. await Task.Delay(5000); Console.WriteLine($"\nClosing session '{channel.SessionId}'."); await channel.CloseAsync(); } catch (Exception ex) { await channel.AbortAsync(); Console.WriteLine(ex.Message); } }
public async Task CreateEventSubscription() { // describe this client application. var clientDescription = new ApplicationDescription { ApplicationName = "Workstation.UaClient.FeatureTests", ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:Workstation.UaClient.FeatureTests", ApplicationType = ApplicationType.Client }; // place to store certificates var certificateStore = new DirectoryStore("./pki"); // create a 'UaTcpSessionChannel', a client-side channel that opens a 'session' with the server. var channel = new UaTcpSessionChannel( clientDescription, certificateStore, new AnonymousIdentity(), // the anonymous identity "opc.tcp://localhost:48010"); // the endpoint of Unified Automation's UaCPPServer. try { // try opening a session and reading a few nodes. await channel.OpenAsync(); Console.WriteLine($"Opened session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'."); Console.WriteLine($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'."); Console.WriteLine($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'."); Console.WriteLine($"UserIdentityToken: '{channel.UserIdentity}'."); // build a CreateSubscriptionRequest. See 'OPC UA Spec Part 4' paragraph 5.13.2 var req = new CreateSubscriptionRequest { RequestedPublishingInterval = 500.0, // intervals are in milliseconds RequestedMaxKeepAliveCount = 30, RequestedLifetimeCount = 30 * 3, PublishingEnabled = true, }; var res = await channel.CreateSubscriptionAsync(req); // the result will return the server's subscription id. You will needs this to // add monitored items. var id = res.SubscriptionId; Console.WriteLine($"Created subscription '{id}'."); // build a CreateMonitoredItemsRequest. See 'OPC UA Spec Part 4' paragraph 5.12.2 var req2 = new CreateMonitoredItemsRequest { SubscriptionId = id, TimestampsToReturn = TimestampsToReturn.Both, ItemsToCreate = new MonitoredItemCreateRequest[] { new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { AttributeId = AttributeIds.EventNotifier, NodeId = NodeId.Parse(ObjectIds.Server) }, MonitoringMode = MonitoringMode.Reporting, // specify a unique ClientHandle. The ClientHandle is returned in the PublishResponse RequestedParameters = new MonitoringParameters { ClientHandle = 42, SamplingInterval = -1.0, QueueSize = 1000, DiscardOldest = true, // events require an EventFilter with a SelectClause (a list of fields to receive) Filter = new EventFilter { SelectClauses = EventHelper.GetSelectClauses <BaseEvent>() } }, }, }, }; var res2 = await channel.CreateMonitoredItemsAsync(req2); Console.WriteLine("\nSubscribe to PublishResponse stream."); // when the session is open, the client sends a stream of PublishRequests to the server. // You can subscribe to all the PublishResponses -or- subscribe to the responses from // a single subscription. var token = channel // receive responses for the subscription we just created .Where(pr => pr.SubscriptionId == id) // subscribe with an 'OnNext' function, and an 'OnError' function .Subscribe( pr => { // loop thru all the event notifications and write them out. var enls = pr.NotificationMessage.NotificationData.OfType <EventNotificationList>(); foreach (var enl in enls) { foreach (var efl in enl.Events) { var ev = EventHelper.Deserialize <BaseEvent>(efl.EventFields); Console.WriteLine($"time: {ev.Time}, src: {ev.SourceName}, msg: {ev.Message}, sev: {ev.Severity}"); } } }, ex => Console.WriteLine("Exception in publish response handler: {0}", ex.GetBaseException().Message) ); // publish for 5 seconds and then close. for (int i = 0; i < 10; i++) { // trigger an event on the Unified Automation server. var writeResult = await channel.WriteAsync( new WriteRequest { // Write true, false, true, false, ... NodesToWrite = new[] { new WriteValue { NodeId = NodeId.Parse("ns=2;s=Demo.Events.Trigger_BaseEvent"), AttributeId = AttributeIds.Value, Value = new DataValue(i % 2 == 0) } } } ); await Task.Delay(500); } Console.WriteLine($"\nClosing session '{channel.SessionId}'."); await channel.CloseAsync(); } catch (Exception ex) { await channel.AbortAsync(); Console.WriteLine(ex.Message); } }