public async Task DatapoolReadOpcWriteAsync(OpcDatapoolModel dataModel, UaTcpSessionChannel channel) { // Read the Thermo tag value and write to the OPC Server DataValue value; switch (dataModel.TagInfo.Type) { case Thermo.Datapool.Datapool.dpTypes.FLOAT: value = new DataValue(new Variant(dataModel.TagInfo.AsDouble), sourceTimestamp: DateTime.Now, serverTimestamp: DateTime.Now); break; case Thermo.Datapool.Datapool.dpTypes.INT: value = new DataValue(new Variant(dataModel.TagInfo.AsInt), sourceTimestamp: DateTime.Now); break; case Thermo.Datapool.Datapool.dpTypes.STRING: value = new DataValue(new Variant(dataModel.TagInfo.AsString), sourceTimestamp: DateTime.Now); break; case Thermo.Datapool.Datapool.dpTypes.BOOL: value = new DataValue(new Variant(dataModel.TagInfo.AsBoolean), sourceTimestamp: DateTime.Now); break; default: throw new InvalidCastException($"Cannot write {dataModel.TagInfo.Type} data type to OPC."); } var writeRequest = new WriteRequest { NodesToWrite = new WriteValue[] { new WriteValue { NodeId = dataModel.NodeId, Value = value, AttributeId = AttributeIds.Value } } }; var response = await channel.WriteAsync(writeRequest); }
public async Task Polling() { 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 readRequest = new ReadRequest { NodesToRead = new[] { new ReadValueId { NodeId = NodeId.Parse(VariableIds.Server_ServerStatus_CurrentTime), AttributeId = AttributeIds.Value } } }; for (int i = 0; i < 10; i++) { var readResult = await channel.ReadAsync(readRequest); logger.LogInformation("Read {0}", readResult.Results[0].GetValueOrDefault <DateTime>()); await Task.Delay(1000); } logger.LogInformation($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); }
public async Task Read() { 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 readRequest = new ReadRequest { NodesToRead = new[] { new ReadValueId { NodeId = NodeId.Parse(VariableIds.Server_ServerStatus), AttributeId = AttributeIds.Value } } }; var readResult = await channel.ReadAsync(readRequest); var serverStatus = readResult.Results[0].GetValueOrDefault <ServerStatusDataType>(); logger.LogInformation("Server status:"); logger.LogInformation(" ProductName: {0}", serverStatus.BuildInfo.ProductName); logger.LogInformation(" SoftwareVersion: {0}", serverStatus.BuildInfo.SoftwareVersion); logger.LogInformation(" ManufacturerName: {0}", serverStatus.BuildInfo.ManufacturerName); logger.LogInformation(" State: {0}", serverStatus.State); logger.LogInformation(" CurrentTime: {0}", serverStatus.CurrentTime); logger.LogInformation($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); }
/// <summary> /// Reads first/next level of tag tree. /// </summary> async Task <Tag> ReadTag(ReferenceDescription[] rds, UaTcpSessionChannel channel, Tag tag) { ReadValueId[] items = new ReadValueId[1]; items[0] = new ReadValueId { NodeId = NodeId.Parse(rds.Last().NodeId.ToString()), AttributeId = AttributeIds.DataType }; ReadRequest readRequest = new ReadRequest { NodesToRead = items }; ReadResponse readResponse = await channel.ReadAsync(readRequest); if (string.IsNullOrEmpty(tag.Name)) { tag = new Tag(rds.Take(rds.Length - 1).ToList()); } tag.NestedName(rds.Last().DisplayName); if (rds.Length > 2) { tag.Group4 = rds[1].DisplayName.ToString(); } if (rds.Length > 1) { tag.Group3 = rds[0].DisplayName.ToString(); } if (readResponse.Results[0].Value != null) { tag.ConversionFunction = Typ(readResponse.Results[0].Value.ToString()); } return(tag); }
public async Task SessionTimeoutCausesFault() { // discover available endpoints of server. var getEndpointsRequest = new GetEndpointsRequest { EndpointUrl = EndpointUrl, ProfileUris = new[] { TransportProfileUris.UaTcpTransport } }; Console.WriteLine($"Discovering endpoints of '{getEndpointsRequest.EndpointUrl}'."); var getEndpointsResponse = await UaTcpDiscoveryService.GetEndpointsAsync(getEndpointsRequest); var selectedEndpoint = getEndpointsResponse.Endpoints.OrderBy(e => e.SecurityLevel).Last(); var selectedTokenType = selectedEndpoint.UserIdentityTokens[0].TokenType; IUserIdentity selectedUserIdentity; switch (selectedTokenType) { case UserTokenType.UserName: selectedUserIdentity = new UserNameIdentity("root", "secret"); break; default: selectedUserIdentity = new AnonymousIdentity(); break; } var channel = new UaTcpSessionChannel( this.localDescription, this.certificateStore, selectedUserIdentity, selectedEndpoint, loggerFactory: this.loggerFactory, options: new UaTcpSessionChannelOptions { SessionTimeout = 10000 }); 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}'."); // server should close session due to inactivity await Task.Delay(20000); // should throw exception var readRequest = new ReadRequest { NodesToRead = new[] { new ReadValueId { NodeId = NodeId.Parse(VariableIds.Server_ServerStatus_CurrentTime), AttributeId = AttributeIds.Value } } }; await channel.ReadAsync(readRequest); Console.WriteLine($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); }
private async Task <UaTcpSessionChannel> CreateChannelAsync(string endpointUrl, CancellationToken token = default) { try { this.logger?.LogTrace($"Begin creating UaTcpSessionChannel for {endpointUrl}"); await this.CheckSuspension(token).ConfigureAwait(false); EndpointDescription endpoint; var mappedEndpoint = this.MappedEndpoints?.LastOrDefault(m => m.RequestedUrl == endpointUrl); if (mappedEndpoint != null) { endpoint = mappedEndpoint.Endpoint; } else { endpoint = new EndpointDescription { EndpointUrl = endpointUrl }; } var channel = new UaTcpSessionChannel( this.LocalDescription, this.CertificateStore, this.UserIdentityProvider, endpoint, this.LoggerFactory, this.Options, this.AdditionalTypes); channel.Faulted += (s, e) => { this.logger?.LogTrace($"Error creating UaTcpSessionChannel for {endpointUrl}. OnFaulted"); var ch = (UaTcpSessionChannel)s; try { ch.AbortAsync().Wait(); } catch { } }; channel.Closing += (s, e) => { this.logger?.LogTrace($"Removing UaTcpSessionChannel for {endpointUrl} from channelMap."); this.channelMap.TryRemove(endpointUrl, out Lazy <Task <UaTcpSessionChannel> > value); }; await channel.OpenAsync(token).ConfigureAwait(false); this.logger?.LogTrace($"Success creating UaTcpSessionChannel for {endpointUrl}."); return(channel); } catch (Exception ex) { this.logger?.LogTrace($"Error creating UaTcpSessionChannel for {endpointUrl}. {ex.Message}"); throw; } }
public async Task ConnnectToAllEndpoints() { // discover available endpoints of server. var getEndpointsRequest = new GetEndpointsRequest { EndpointUrl = EndpointUrl, ProfileUris = new[] { TransportProfileUris.UaTcpTransport } }; Console.WriteLine($"Discovering endpoints of '{getEndpointsRequest.EndpointUrl}'."); var getEndpointsResponse = await UaTcpDiscoveryService.GetEndpointsAsync(getEndpointsRequest); // for each endpoint and user identity type, try creating a session and reading a few nodes. foreach (var selectedEndpoint in getEndpointsResponse.Endpoints.OrderBy(e => e.SecurityLevel)) { foreach (var selectedTokenPolicy in selectedEndpoint.UserIdentityTokens) { IUserIdentity selectedUserIdentity; switch (selectedTokenPolicy.TokenType) { case UserTokenType.UserName: selectedUserIdentity = new UserNameIdentity("root", "secret"); break; //case UserTokenType.Certificate: // selectedUserIdentity = new X509Identity(localCertificate); // break; case UserTokenType.Anonymous: selectedUserIdentity = new AnonymousIdentity(); break; default: continue; } var channel = new UaTcpSessionChannel( this.localDescription, this.certificateStore, async e => selectedUserIdentity, selectedEndpoint, loggerFactory: this.loggerFactory, options: new UaTcpSessionChannelOptions { TimeoutHint = 60000 }); 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}'."); Console.WriteLine($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); } } }
private static async Task ConnectAsync() { channel = new UaTcpSessionChannel( localDescription, certificateStore, null, EndpointUrl); await channel.OpenAsync(); }
public async Task StructureTest() { var channel = new UaTcpSessionChannel( localDescription, certificateStore, new AnonymousIdentity(), EndpointUrl, loggerFactory: loggerFactory); await channel.OpenAsync(); var readRequest = new ReadRequest { NodesToRead = new[] { new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Structure") }, }, }; var readResponse = await channel.ReadAsync(readRequest); foreach (var result in readResponse.Results) { StatusCode.IsGood(result.StatusCode) .Should().BeTrue(); } // reading this node returns an array of ExtensionObjects var obj = readResponse.Results[0].Value; // create new DataValue for writing. Most servers reject writing values with timestamps. var newValue = new DataValue(obj); var writeRequest = new WriteRequest { NodesToWrite = new[] { new WriteValue { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Structure"), Value = newValue }, }, }; var writeResponse = await channel.WriteAsync(writeRequest); foreach (var result in writeResponse.Results) { StatusCode.IsGood(result) .Should().BeTrue(); } logger.LogInformation($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); }
public async Task ConnnectToEndpointsWithNoSecurityAndWithNoCertificate() { // 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); // for each endpoint and user identity type, try creating a session and reading a few nodes. foreach (var selectedEndpoint in getEndpointsResponse.Endpoints.Where(e => e.SecurityMode == MessageSecurityMode.None)) { foreach (var selectedTokenPolicy in selectedEndpoint.UserIdentityTokens) { IUserIdentity selectedUserIdentity; switch (selectedTokenPolicy.TokenType) { case UserTokenType.UserName: selectedUserIdentity = new UserNameIdentity("root", "secret"); break; //case UserTokenType.Certificate: // selectedUserIdentity = new X509Identity(localCertificate); // break; case UserTokenType.Anonymous: selectedUserIdentity = new AnonymousIdentity(); break; default: continue; } var channel = new UaTcpSessionChannel( this.localDescription, null, selectedUserIdentity, selectedEndpoint, loggerFactory: this.loggerFactory); Console.WriteLine($"Creating session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'."); Console.WriteLine($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'."); Console.WriteLine($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'."); Console.WriteLine($"UserIdentityToken: '{channel.UserIdentity}'."); await channel.OpenAsync(); Console.WriteLine($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); } } }
public BrowseTagsViewModel(ReferenceDescription node, UaTcpSessionChannel currentChannel, ITagBrower _parent, bool loadChildren = false) { parent = _parent; TreeViewItemViewModelHelpers.InitializeChildren(this, loadChildren); //TreeViewItemViewModelHelpers.CheckForEndTag(this, node); Node = new OpcTagModel() { Node = node }; channel = currentChannel; }
private async Task CloseChannel() { if (connection == null) { return; } try { await connection.CloseAsync(); } catch (Exception) { } connection = null; }
/// <summary> /// Reads tag unit. /// </summary> async Task ReadUnit(ReferenceDescription[] rds, UaTcpSessionChannel channel, Tag tag) { ReadValueId[] unit = new ReadValueId[1]; unit[0] = new ReadValueId { NodeId = NodeId.Parse(rds.Last().NodeId.ToString()), AttributeId = AttributeIds.Value }; ReadRequest unitRequest = new ReadRequest { NodesToRead = unit }; ReadResponse unitResponse = await channel.ReadAsync(unitRequest); ExtensionObject EO = (ExtensionObject)unitResponse.Results[0].Value; EUInformation EU = (EUInformation)EO.Body; tag.Unit = EU.DisplayName; //zapis jednostki }
public async Task BrowseObjects() { var channel = new UaTcpSessionChannel( localDescription, certificateStore, new AnonymousIdentity(), EndpointUrl, SecurityPolicyUris.None, loggerFactory: loggerFactory); await channel.OpenAsync(); var rds = new List <ReferenceDescription>(); var browseRequest = new BrowseRequest { NodesToBrowse = new[] { new BrowseDescription { NodeId = ExpandedNodeId.ToNodeId(ExpandedNodeId.Parse(ObjectIds.ObjectsFolder), channel.NamespaceUris), ReferenceTypeId = NodeId.Parse(ReferenceTypeIds.HierarchicalReferences), ResultMask = (uint)BrowseResultMask.TargetInfo, NodeClassMask = (uint)NodeClass.Unspecified, BrowseDirection = BrowseDirection.Forward, IncludeSubtypes = true } }, RequestedMaxReferencesPerNode = 1000 }; var browseResponse = await channel.BrowseAsync(browseRequest).ConfigureAwait(false); rds.AddRange(browseResponse.Results.Where(result => result.References != null).SelectMany(result => result.References)); var continuationPoints = browseResponse.Results.Select(br => br.ContinuationPoint).Where(cp => cp != null).ToArray(); while (continuationPoints.Length > 0) { var browseNextRequest = new BrowseNextRequest { ContinuationPoints = continuationPoints, ReleaseContinuationPoints = false }; var browseNextResponse = await channel.BrowseNextAsync(browseNextRequest); rds.AddRange(browseNextResponse.Results.Where(result => result.References != null).SelectMany(result => result.References)); continuationPoints = browseNextResponse.Results.Select(br => br.ContinuationPoint).Where(cp => cp != null).ToArray(); } rds .Should().NotBeEmpty(); logger.LogInformation("+ Objects, 0:Objects, Object"); foreach (var rd in rds) { logger.LogInformation(" + {0}, {1}, {2}", rd.DisplayName, rd.BrowseName, rd.NodeClass); } logger.LogInformation($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); }
public async Task VectorAdd() { var channel = new UaTcpSessionChannel( this.localDescription, this.certificateStore, new AnonymousIdentity(), "opc.tcp://*****:*****@" ------------------"); Console.WriteLine($" {result}"); Console.WriteLine($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); result.Z .Should().Be(6.0); }
public void ConfigureClient() { clientDescription = new ApplicationDescription { ApplicationName = _clientOptions.ApplicationName, ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:{_clientOptions.ApplicationName}", ApplicationType = ApplicationType.Client }; certificateStore = new DirectoryStore("./pki"); channel = new UaTcpSessionChannel( clientDescription, null, new AnonymousIdentity(), _clientOptions.Endpoint, //server endpoint SecurityPolicyUris.None, _loggerFactory ); }
public static async Task <bool> StartOPC() { var clientDescription = new ApplicationDescription { ApplicationName = "Workstation.UaClient.FeatureTests", ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:Workstation.UaClient.FeatureTests", ApplicationType = ApplicationType.Client }; try { if (channel != null) { channel.CloseAsync(); } } catch { } // create a 'UaTcpSessionChannel', a client-side channel that opens a 'session' with the server. channel = new UaTcpSessionChannel( clientDescription, null, // no x509 certificates new AnonymousIdentity(), // no user identity //IP serwera path, // the public endpoint of a server at opcua.rocks. SecurityPolicyUris.None); // no encryption try { // try opening a session and reading a few nodes. await channel.OpenAsync(); //HMI_SuctionCup1 return(true); } catch (Exception ex) { await channel.AbortAsync(); Console.WriteLine(ex.Message); return(true); } }
public async Task ConnectWithSecurity() { // 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(); // success! client session opened with these settings. 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}'."); Console.WriteLine($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); } catch (Exception ex) { await channel.AbortAsync(); Console.WriteLine(ex.Message); } }
public async Task BrowseRoot() { var channel = new UaTcpSessionChannel( this.localDescription, this.certificateStore, new AnonymousIdentity(), EndpointUrl, SecurityPolicyUris.None, loggerFactory: this.loggerFactory); await channel.OpenAsync(); var rds = new List <ReferenceDescription>(); var browseRequest = new BrowseRequest { NodesToBrowse = new[] { new BrowseDescription { NodeId = ExpandedNodeId.ToNodeId(ExpandedNodeId.Parse(ObjectIds.RootFolder), channel.NamespaceUris), ReferenceTypeId = NodeId.Parse(ReferenceTypeIds.HierarchicalReferences), ResultMask = (uint)BrowseResultMask.TargetInfo, NodeClassMask = (uint)NodeClass.Unspecified, BrowseDirection = BrowseDirection.Forward, IncludeSubtypes = true } }, RequestedMaxReferencesPerNode = 1000 }; var browseResponse = await channel.BrowseAsync(browseRequest).ConfigureAwait(false); rds.AddRange(browseResponse.Results.Where(result => result.References != null).SelectMany(result => result.References)); var continuationPoints = browseResponse.Results.Select(br => br.ContinuationPoint).Where(cp => cp != null).ToArray(); while (continuationPoints.Length > 0) { var browseNextRequest = new BrowseNextRequest { ContinuationPoints = continuationPoints, ReleaseContinuationPoints = false }; var browseNextResponse = await channel.BrowseNextAsync(browseNextRequest); rds.AddRange(browseNextResponse.Results.Where(result => result.References != null).SelectMany(result => result.References)); continuationPoints = browseNextResponse.Results.Select(br => br.ContinuationPoint).Where(cp => cp != null).ToArray(); } Assert.IsTrue(rds.Count == 3); Console.WriteLine($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); }
/// <summary> /// Signals the channel state is Closing. /// </summary> /// <param name="channel">The session channel. </param> /// <param name="token">A cancellation token. </param> /// <returns>A task.</returns> private async Task WhenChannelClosingAsync(UaTcpSessionChannel channel, CancellationToken token = default(CancellationToken)) { var tcs = new TaskCompletionSource <bool>(); EventHandler handler = (o, e) => { tcs.TrySetResult(true); }; using (token.Register(state => ((TaskCompletionSource <bool>)state).TrySetCanceled(), tcs, false)) { try { channel.Closing += handler; if (channel.State == CommunicationState.Opened) { await tcs.Task; } } finally { channel.Closing -= handler; } } }
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); } }
/// <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); } } }
public async Task SetChanel() { var clientDescription = new ApplicationDescription { ApplicationName = "Workstation.UaClient.FeatureTests", ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:Workstation.UaClient.FeatureTests", ApplicationType = Workstation.ServiceModel.Ua.ApplicationType.Client }; channel = new UaTcpSessionChannel( clientDescription, null, // no x509 certificates new AnonymousIdentity(), url, SecurityPolicyUris.None); try { await channel.OpenAsync(); var readRequestGetName = new Workstation.ServiceModel.Ua.ReadRequest { NodesToRead = new[] { new Workstation.ServiceModel.Ua.ReadValueId { NodeId = Workstation.ServiceModel.Ua.NodeId.Parse(Workstation.ServiceModel.Ua.VariableIds.Server_ServerStatus), AttributeId = AttributeIds.Value } } }; var readResultName = await channel.ReadAsync(readRequestGetName); var serverStatusGetName = readResultName.Results[0].GetValueOrDefault <Workstation.ServiceModel.Ua.ServerStatusDataType>(); serverName = serverStatusGetName.BuildInfo.ProductName; ReadValueId[] reads = new ReadValueId[itemsNames.Count]; int index = 0; names = new String[itemsNames.Count]; foreach (string name in itemsNames) { reads[index] = new Workstation.ServiceModel.Ua.ReadValueId { NodeId = Workstation.ServiceModel.Ua.NodeId.Parse("ns=4;s=|var|" + serverName + "." + name), AttributeId = AttributeIds.Value }; //MessageBox.Show(itemsNames.Count.ToString()); names[index] = name; index++; } readRequest = new Workstation.ServiceModel.Ua.ReadRequest { NodesToRead = reads }; } catch (Exception ex) { await channel.AbortAsync(); MessageBox.Show(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 StackTest() { 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 readRequest = new ReadRequest { NodesToRead = new[] { new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Boolean") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.SByte") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Int16") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Int32") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Int64") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Byte") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.UInt16") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.UInt32") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.UInt64") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Float") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Double") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.String") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.DateTime") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Guid") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.ByteString") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.XmlElement") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.LocalizedText") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.QualifiedName") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Boolean") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.SByte") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Int16") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Int32") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Int64") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Byte") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.UInt16") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.UInt32") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.UInt64") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Float") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Double") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.String") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.DateTime") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Guid") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.ByteString") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.XmlElement") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.LocalizedText") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.QualifiedName") }, }, }; var sw = new Stopwatch(); sw.Restart(); for (int i = 0; i < 1; i++) { var readResponse = await channel.ReadAsync(readRequest); foreach (var result in readResponse.Results) { StatusCode.IsGood(result.StatusCode) .Should().BeTrue(); var obj = result.GetValue(); } } sw.Stop(); logger.LogInformation($"{sw.ElapsedMilliseconds} ms"); logger.LogInformation($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); }
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 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); }
public async Task ReadHistoryRawValues() { // 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}'."); Console.WriteLine("\nCheck if DataLogger active."); // check if DataLoggerActive is true. If not, then call method StartLogging. var req = new ReadRequest { NodesToRead = new[] { new ReadValueId { NodeId = NodeId.Parse("ns=2;s=Demo.History.DataLoggerActive"), AttributeId = AttributeIds.Value } }, }; var res = await channel.ReadAsync(req); if (StatusCode.IsBad(res.Results[0].StatusCode)) { throw new InvalidOperationException("Error reading 'Demo.History.DataLoggerActive'. "); } var isActive = res.Results[0].GetValueOrDefault <bool>(); if (!isActive) { Console.WriteLine("Activating DataLogger."); var req1 = new CallRequest { MethodsToCall = new[] { new CallMethodRequest { ObjectId = NodeId.Parse("ns=2;s=Demo.History"), // parent node MethodId = NodeId.Parse("ns=2;s=Demo.History.StartLogging") }, }, }; var res1 = await channel.CallAsync(req1); if (StatusCode.IsBad(res1.Results[0].StatusCode)) { throw new InvalidOperationException("Error calling method 'Demo.History.StartLogging'."); } Console.WriteLine("Note: Datalogger has just been activated, so there will be little or no history data to read."); Console.WriteLine(" Try again in 1 minute."); } Console.WriteLine("\nReading history for last 1 minute(s)."); // A continuation point is returned if there are more values to return than the // limit set by parameter NumValuesPerNode. A client should continue calling HistoryRead // until the continuation point returns null. byte[] cp = null; do { var req2 = new HistoryReadRequest { HistoryReadDetails = new ReadRawModifiedDetails { StartTime = DateTime.UtcNow.Add(TimeSpan.FromSeconds(-60)), // set start time to 1 minute ago EndTime = DateTime.UtcNow, NumValuesPerNode = 100, // sets limit. if there are more values to return then a continuation point is returned. ReturnBounds = false, // set true to return interpolated values for the start and end times }, TimestampsToReturn = TimestampsToReturn.Both, ReleaseContinuationPoints = false, // set true to abandon returning any remaining values from this interval NodesToRead = new[] { new HistoryReadValueId { NodeId = NodeId.Parse("ns=2;s=Demo.History.DoubleWithHistory"), ContinuationPoint = cp }, }, }; var res2 = await channel.HistoryReadAsync(req2); if (StatusCode.IsGood(res2.Results[0].StatusCode)) { var historyData = res2.Results[0].HistoryData as HistoryData; Console.WriteLine($"Found {historyData.DataValues.Length} value(s) for node '{req2.NodesToRead[0].NodeId}':"); foreach (var dv in historyData.DataValues) { Console.WriteLine($"Read {dv.Value}, q: {dv.StatusCode}, ts: {dv.SourceTimestamp}"); } cp = res2.Results[0].ContinuationPoint; // if ContinuationPoint is null, then there is no more data to return. if (cp == null) { break; } } else { Console.WriteLine($"HistoryRead return statuscode: {res2.Results[0].StatusCode}"); break; } } while (cp != null); // loop while ContinuationPoint is not null. Console.WriteLine($"\nClosing session '{channel.SessionId}'."); await channel.CloseAsync(); } catch (Exception ex) { await channel.AbortAsync(); Console.WriteLine(ex.Message); } }
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> /// Opens a session with the remote endpoint. /// </summary> /// <param name="token">A cancellation token.</param> /// <returns>A task.</returns> private async Task OpenAsync(CancellationToken token = default(CancellationToken)) { await this.semaphore.WaitAsync(token).ConfigureAwait(false); try { if (this.RemoteEndpoint == null) { // If specific endpoint is not provided, use discovery to select endpoint with highest // security level. try { this.Logger?.LogInformation($"Discovering endpoints of '{this.discoveryUrl}'."); var getEndpointsRequest = new GetEndpointsRequest { EndpointUrl = this.discoveryUrl, ProfileUris = new[] { TransportProfileUris.UaTcpTransport } }; var getEndpointsResponse = await UaTcpDiscoveryClient.GetEndpointsAsync(getEndpointsRequest).ConfigureAwait(false); if (getEndpointsResponse.Endpoints == null || getEndpointsResponse.Endpoints.Length == 0) { throw new InvalidOperationException($"'{this.discoveryUrl}' returned no endpoints."); } this.RemoteEndpoint = getEndpointsResponse.Endpoints.OrderBy(e => e.SecurityLevel).Last(); this.Logger?.LogTrace($"Success discovering endpoints of '{this.discoveryUrl}'."); } catch (Exception ex) { this.Logger?.LogError($"Error discovering endpoints of '{this.discoveryUrl}'. {ex.Message}"); throw; } } // throw here to exit state machine. token.ThrowIfCancellationRequested(); // evaluate the user identity provider (may show a dialog). var userIdentity = await this.UserIdentityProvider(this.RemoteEndpoint); try { this.linkToken?.Dispose(); if (this.innerChannel != null && this.innerChannel.State != CommunicationState.Closed) { await this.innerChannel.AbortAsync(); } this.innerChannel = new UaTcpSessionChannel( this.LocalDescription, this.CertificateStore, userIdentity, this.RemoteEndpoint, this.loggerFactory, this.SessionTimeout, this.TimeoutHint, this.DiagnosticsHint, this.LocalReceiveBufferSize, this.LocalSendBufferSize, this.LocalMaxMessageSize, this.LocalMaxChunkCount); await this.innerChannel.OpenAsync(token).ConfigureAwait(false); this.linkToken = this.pendingRequests.LinkTo(this.innerChannel); //// create an internal subscription. //var subscriptionRequest = new CreateSubscriptionRequest //{ // RequestedPublishingInterval = DefaultPublishingInterval, // RequestedMaxKeepAliveCount = DefaultKeepaliveCount, // RequestedLifetimeCount = (uint)(this.SessionTimeout / DefaultPublishingInterval), // PublishingEnabled = true, // Priority = 0 //}; //var subscriptionResponse = await this.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false); //this.subscriptionId = subscriptionResponse.SubscriptionId; } catch (Exception ex) { this.Logger?.LogError($"Error opening channel with endpoint '{this.RemoteEndpoint.EndpointUrl}'. {ex.Message}"); throw; } } finally { this.semaphore.Release(); } }