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); } }
public async Task ReadHistorical() { var channel = new UaTcpSessionChannel( localDescription, certificateStore, new AnonymousIdentity(), "opc.tcp://localhost:48010", 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 historyReadRequest = new HistoryReadRequest { HistoryReadDetails = new ReadRawModifiedDetails { StartTime = DateTime.UtcNow - TimeSpan.FromMinutes(10), EndTime = DateTime.UtcNow, ReturnBounds = true, IsReadModified = false }, NodesToRead = new[] { new HistoryReadValueId { NodeId = NodeId.Parse("ns=2;s=Demo.History.DoubleWithHistory") } }, }; var historyReadResponse = await channel.HistoryReadAsync(historyReadRequest); var result = historyReadResponse.Results[0]; StatusCode.IsGood(result.StatusCode) .Should().BeTrue(); logger.LogInformation($"HistoryRead response status code: {result.StatusCode}, HistoryData count: {((HistoryData)result.HistoryData).DataValues.Length}."); if (false) // UaCPPserver does not appear to store event history. { var historyReadRequest2 = new HistoryReadRequest { HistoryReadDetails = new ReadEventDetails { StartTime = DateTime.UtcNow - TimeSpan.FromMinutes(10), EndTime = DateTime.UtcNow, Filter = new EventFilter // Use EventHelper to select all the fields of AlarmCondition. { SelectClauses = EventHelper.GetSelectClauses <AlarmCondition>() } }, NodesToRead = new[] { new HistoryReadValueId { NodeId = NodeId.Parse("ns=2;s=Demo.History.DoubleWithHistory") } }, }; var historyReadResponse2 = await channel.HistoryReadAsync(historyReadRequest2); var result2 = historyReadResponse2.Results[0]; StatusCode.IsGood(result2.StatusCode) .Should().BeTrue(); logger.LogInformation($"HistoryRead response status code: {result2.StatusCode}, HistoryEvent count: {((HistoryEvent)result2.HistoryData).Events.Length}."); // Use EventHelper to create AlarmConditions from the HistoryEventFieldList var alarms = ((HistoryEvent)result2.HistoryData).Events.Select(e => EventHelper.Deserialize <AlarmCondition>(e.EventFields)); } logger.LogInformation($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); }
public async Task ReadHistorical() { var channel = new UaTcpSessionChannel( this.localDescription, this.certificateStore, null, EndpointUrl); 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($"Activated session '{channel.SessionId}'."); var historyReadRequest = new HistoryReadRequest { HistoryReadDetails = new ReadRawModifiedDetails { StartTime = DateTime.UtcNow - TimeSpan.FromMinutes(10), EndTime = DateTime.UtcNow, ReturnBounds = true, IsReadModified = false }, NodesToRead = new[] { new HistoryReadValueId { NodeId = NodeId.Parse("ns=2;s=MyLevel") } }, }; var historyReadResponse = await channel.HistoryReadAsync(historyReadRequest); var result = historyReadResponse.Results[0]; Assert.IsTrue(StatusCode.IsGood(result.StatusCode)); Console.WriteLine($"HistoryRead response status code: {result.StatusCode}, HistoryData count: {((HistoryData)result.HistoryData.Body).DataValues.Length}."); var historyReadRequest2 = new HistoryReadRequest { HistoryReadDetails = new ReadEventDetails { StartTime = DateTime.UtcNow - TimeSpan.FromMinutes(10), EndTime = DateTime.UtcNow, Filter = new EventFilter // Use EventHelper to select all the fields of AlarmCondition. { SelectClauses = EventHelper.GetSelectClauses <AlarmCondition>() } }, NodesToRead = new[] { new HistoryReadValueId { NodeId = NodeId.Parse("ns=2;s=MyDevice") } }, }; var historyReadResponse2 = await channel.HistoryReadAsync(historyReadRequest2); var result2 = historyReadResponse2.Results[0]; Assert.IsTrue(StatusCode.IsGood(result2.StatusCode)); Console.WriteLine($"HistoryRead response status code: {result2.StatusCode}, HistoryEvent count: {((HistoryEvent)result2.HistoryData.Body).Events.Length}."); // Use EventHelper to create AlarmConditions from the HistoryEventFieldList var alarms = ((HistoryEvent)result2.HistoryData.Body).Events.Select(e => EventHelper.Deserialize <AlarmCondition>(e.EventFields)); Console.WriteLine($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); }