public async Task TryConnectAsync() { await _mutex.WaitAsync(_cancellationToken).ConfigureAwait(false); try { if (Connected) { return; } try { var endpointDescription = await GetEndpointAsync(EndpointUrl, true).ConfigureAwait(false); ConfiguredEndpoint.Update(endpointDescription); ConfiguredEndpoint.Configuration.UseBinaryEncoding = endpointDescription.EncodingSupport == BinaryEncodingSupport.Optional || endpointDescription.EncodingSupport == BinaryEncodingSupport.Required; TransportChannel = SessionChannel.Create(Configuration, ConfiguredEndpoint.Description, ConfiguredEndpoint.Configuration, Configuration.SecurityConfiguration.ApplicationCertificate.Certificate, Configuration.CreateMessageContext()); Open(_sessionName, null); NotifyPropertyChanged("Connected"); Trace.TraceInformation("Success connecting to endpoint '{0}'. ", ConfiguredEndpoint); } catch (ServiceResultException ex) { Trace.TraceError("Error connecting to endpoint '{0}'. {1}", ConfiguredEndpoint, ex.Message); } } finally { _mutex.Release(); } }
private async Task <Session> GetSessionAsync(string serverUrl) { lock (_sessions) { if (_sessions.ContainsKey(serverUrl)) { return(_sessions[serverUrl]); } } await CheckAndLoadConfiguration(); EndpointDescription endpointDescription; try { endpointDescription = CoreClientUtils.SelectEndpoint(serverUrl, true, 15000); } catch (Exception) { throw new DataSetNotAvailableException(); } Console.WriteLine(" Selected endpoint uses: {0}", endpointDescription.SecurityPolicyUri.Substring(endpointDescription.SecurityPolicyUri.LastIndexOf('#') + 1)); var endpointConfiguration = EndpointConfiguration.Create(_appConfiguration); var endpoint = new ConfiguredEndpoint(endpointDescription.Server, endpointConfiguration); endpoint.Update(endpointDescription); var s = await Session.Create(_appConfiguration, endpoint, true, false, _appConfiguration.ApplicationName + "_session", (uint)_appConfiguration.ClientConfiguration.DefaultSessionTimeout, null, null); lock (_sessions) { if (_sessions.ContainsKey(serverUrl)) { s = _sessions[serverUrl]; } else { _sessions.Add(serverUrl, s); } } return(s); }
/// <summary> /// Creates a new session /// </summary> /// <param name="identity"></param> /// <returns></returns> private async Task <Session> CreateSessionAsync(IUserIdentity identity) { if (_connection.Endpoint.SecurityMode != SecurityMode.SignAndEncrypt) { _logger.Warning("Establishing unencrypted connection."); } if (_urlQueue.TryDequeue(out var next)) { if (_endpointUrl != null && _endpointUrl != next) { _urlQueue.Enqueue(_endpointUrl); } _endpointUrl = next; _logger.Information("Creating session via {endpoint}.", _endpointUrl); } var selectedEndpoint = await DiscoverEndpointsAsync(_config, _connection.Endpoint, new Uri(_endpointUrl), (server, endpoints, channel) => SelectServerEndpoint(server, endpoints, channel, true)); if (selectedEndpoint == null) { throw new ConnectionException( $"Unable to select secure endpoint on {_connection.Endpoint.Url} via {_endpointUrl}"); } var configuredEndpoint = new ConfiguredEndpoint(selectedEndpoint.Server, EndpointConfiguration.Create(_config)); configuredEndpoint.Update(selectedEndpoint); var session = await Session.Create(_config, configuredEndpoint, true, false, _sessionName, (uint)(_timeout.TotalMilliseconds * 1.2), identity, null); if (session == null) { throw new ExternalDependencyException( $"Cannot establish session to {_connection.Endpoint.Url} via {_endpointUrl}."); } session.KeepAlive += (_, e) => e.CancelKeepAlive = true; session.KeepAliveInterval = -1; // No keep alives - we handle those ourselves. session.RenewUserIdentity += (_, user) => identity; // Reset back to default. try { var complexTypeSystem = new ComplexTypeSystem(session); await complexTypeSystem.Load(); } catch (Exception ex) { _logger.Error(ex, "Failed to load complex type system"); } return(session); }
public async Task <ConnectionStatus> OpcClient(string endpointURL) { try { Uri endpointURI = new Uri(endpointURL); var selectedEndpoint = CoreClientUtils.SelectEndpoint(endpointURL, haveAppCertificate, 15000); info.LabelText = "Selected endpoint uses: " + selectedEndpoint.SecurityPolicyUri.Substring(selectedEndpoint.SecurityPolicyUri.LastIndexOf('#') + 1); var endpointConfiguration = EndpointConfiguration.Create(config); var endpoint = new ConfiguredEndpoint(selectedEndpoint.Server, endpointConfiguration); endpoint.Update(selectedEndpoint); var platform = Device.RuntimePlatform; var sessionName = ""; switch (Device.RuntimePlatform) { case "Android": sessionName = "OPC UA Xamarin Client Android"; break; case "UWP": sessionName = "OPC UA Xamarin Client UWP"; break; case "iOS": sessionName = "OPC UA Xamarin Client IOS"; break; } session = await Session.Create(config, endpoint, false, sessionName, 60000, new UserIdentity(new AnonymousIdentityToken()), null); if (session != null) { connectionStatus = ConnectionStatus.Connected; } else { connectionStatus = ConnectionStatus.NotConnected; } // register keep alive handler session.KeepAlive += Client_KeepAlive; } catch { connectionStatus = ConnectionStatus.Error; } return(connectionStatus); }
private static void securelyUpdateEndpointConfiguration(ConfiguredEndpoint ep, ApplicationConfiguration applicationConfiguration) { // ep.UpdateFromServer(...) looks for matching endpoints on the server. // If there is no match with the same securityMode and securityPolicy, it will simply // _replace_ ep by one of the server endpoints, possibly lowering the security settings. Therefore: // save old settings - update from server - verify security settings -- and throw update from server away if security settings have changed. // note that ConfiguredEndpoints need a collection to live in. Note also that some settings of the configured endpoint may be changed nonetheless behind the scenes. ConfiguredEndpointCollection cepc = new ConfiguredEndpointCollection(); EndpointDescription epd = (EndpointDescription)ep.Description.Clone(); ConfiguredEndpoint cep = new ConfiguredEndpoint(cepc, epd); Opc.Ua.BindingFactory bindingFactory = BindingFactory.Create(applicationConfiguration, applicationConfiguration.CreateMessageContext()); ep.UpdateFromServer(bindingFactory); if (ep.Description.SecurityMode != epd.SecurityMode || ep.Description.SecurityPolicyUri != epd.SecurityPolicyUri) { ep.Update(cep); throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "No endpoint with matching security configuration could be found during updated on connect."); } }
/// <summary> /// Connects to a single OPC UA Server's endpoint /// </summary> public static async Task EndpointConnect(Uri endpointUrl) { EndpointDescription selectedEndpoint = CoreClientUtils.SelectEndpoint(endpointUrl.AbsoluteUri, true); ConfiguredEndpoint configuredEndpoint = new ConfiguredEndpoint(selectedEndpoint.Server, EndpointConfiguration.Create(m_configuration)); configuredEndpoint.Update(selectedEndpoint); Session newSession = await Session.Create( m_configuration, configuredEndpoint, true, false, m_configuration.ApplicationName, 60000, new UserIdentity(new AnonymousIdentityToken()), null); if (newSession != null) { Trace("Created session with updated endpoint " + selectedEndpoint.EndpointUrl + " from server!"); newSession.KeepAlive += new KeepAliveEventHandler((sender, e) => StandardClient_KeepAlive(sender, e, newSession)); m_sessions.Add(newSession); } }
/// <summary> /// Connects to a single OPC UA Server's endpoint /// </summary> public static async Task EndpointConnect(Uri endpointUrl) { EndpointDescription selectedEndpoint = SelectUaTcpEndpoint(DiscoverEndpoints(m_configuration, endpointUrl, 10)); ConfiguredEndpoint configuredEndpoint = new ConfiguredEndpoint(selectedEndpoint.Server, EndpointConfiguration.Create(m_configuration)); configuredEndpoint.Update(selectedEndpoint); Session newSession = await Session.Create( m_configuration, configuredEndpoint, true, false, m_configuration.ApplicationName, 60000, new UserIdentity(new AnonymousIdentityToken()), null); if (newSession != null) { Trace("Opc.Ua.Publisher.Module: Created session with updated endpoint " + selectedEndpoint.EndpointUrl + " from server!"); newSession.KeepAlive += new KeepAliveEventHandler((sender, e) => StandardClient_KeepAlive(sender, e, newSession)); m_sessions.Add(newSession); } }
static async Task ConsoleSampleClient(string endpointURL, Op op, int count) { Console.WriteLine("1 - Create an Application Configuration."); var config = new ApplicationConfiguration { ApplicationName = "UA Core Sample Client", ApplicationType = ApplicationType.Client, ApplicationUri = "urn:" + Utils.GetHostName() + ":OPCFoundation:CoreSampleClient", SecurityConfiguration = new SecurityConfiguration { ApplicationCertificate = new CertificateIdentifier { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/MachineDefault", SubjectName = "UA Core Sample Client" }, TrustedPeerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Applications", }, TrustedIssuerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Certificate Authorities", }, RejectedCertificateStore = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/RejectedCertificates", }, NonceLength = 32, AutoAcceptUntrustedCertificates = true }, TransportConfigurations = new TransportConfigurationCollection(), TransportQuotas = new TransportQuotas { OperationTimeout = 120000 }, ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 120000 } }; await config.Validate(ApplicationType.Client); var haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (!haveAppCertificate) { Console.WriteLine(" INFO: Creating new application certificate: {0}", config.ApplicationName); var certificate = CertificateFactory.CreateCertificate( config.SecurityConfiguration.ApplicationCertificate.StoreType, config.SecurityConfiguration.ApplicationCertificate.StorePath, null, config.ApplicationUri, config.ApplicationName, config.SecurityConfiguration.ApplicationCertificate.SubjectName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, false, null, null ); config.SecurityConfiguration.ApplicationCertificate.Certificate = certificate; } haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (haveAppCertificate) { config.ApplicationUri = Utils.GetApplicationUriFromCertificate( config.SecurityConfiguration.ApplicationCertificate.Certificate); if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates) { config.CertificateValidator.CertificateValidation += CertificateValidator_CertificateValidation; } } else { Console.WriteLine(" WARN: missing application certificate, using unsecure connection."); } var reconnectLoops = op == Op.All ? 1 : count; for (var i = 1; i <= reconnectLoops; i++) { Console.WriteLine("2 - Discover endpoints of {0}.", endpointURL); var endpointURI = new Uri(endpointURL); var endpointCollection = DiscoverEndpoints(config, endpointURI, 10); var selectedEndpoint = SelectUaTcpEndpoint(endpointCollection, haveAppCertificate); Console.WriteLine(" Selected endpoint uses: {0}", selectedEndpoint.SecurityPolicyUri.Substring(selectedEndpoint.SecurityPolicyUri.LastIndexOf('#') + 1)); Console.WriteLine("3 - Create session with OPC UA server."); var endpointConfiguration = EndpointConfiguration.Create(config); var endpoint = new ConfiguredEndpoint(selectedEndpoint.Server, endpointConfiguration); endpoint.Update(selectedEndpoint); var session = await CreateSessionAsync(config, endpoint); if (op == Op.All || op == Op.Browse) { Console.WriteLine("4 - Browse the OPC UA server namespace."); var j = 0; while (true) { var w = Stopwatch.StartNew(); var stack = new Stack <Tuple <string, ReferenceDescription> >(); session.Browse( null, null, ObjectIds.ObjectsFolder, 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out var continuationPoint, out var references); Console.WriteLine(" DisplayName, BrowseName, NodeClass"); references.Reverse(); foreach (var rd in references) { stack.Push(Tuple.Create("", rd)); } while (stack.Count > 0) { var browsed = stack.Pop(); session.Browse( null, null, ExpandedNodeId.ToNodeId(browsed.Item2.NodeId, session.NamespaceUris), 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out continuationPoint, out references); references.Reverse(); foreach (var rd in references) { stack.Push(Tuple.Create(browsed.Item1 + " ", rd)); } Console.WriteLine($"{browsed.Item1}{(references.Count == 0 ? "-" : "+")} " + $"{browsed.Item2.DisplayName}, {browsed.Item2.BrowseName}, {browsed.Item2.NodeClass}"); } Console.WriteLine($" .... took {w.ElapsedMilliseconds} ms..."); if (++j <= count) { break; } // Reconnect session.Close(); session = await CreateSessionAsync(config, endpoint); } } if (op == Op.All || op == Op.Subscribe) { Console.WriteLine("5 - Create a subscription with publishing interval of 1 second."); var subscription = new Subscription(session.DefaultSubscription) { PublishingInterval = 1000 }; Console.WriteLine("6 - Add a list of items (server current time and status) to the subscription."); var list = new List <MonitoredItem> { new MonitoredItem(subscription.DefaultItem) { DisplayName = "ServerStatusCurrentTime", StartNodeId = "i=2258" } }; list.ForEach(m => m.Notification += OnNotification); subscription.AddItems(list); Console.WriteLine("7 - Add the subscription to the session."); session.AddSubscription(subscription); subscription.Create(); await Task.Delay(1000 *(count + 1)); subscription.Delete(false); subscription.Dispose(); } session.Close(); } }
/// <summary> /// Checks if there is an active OPC UA session for the provided browser session. If the persisted OPC UA session does not exist, /// a new OPC UA session to the given endpoint URL is established. /// </summary> public async Task <Session> GetSessionAsync(string sessionID, string endpointURL) { if (string.IsNullOrEmpty(sessionID) || string.IsNullOrEmpty(endpointURL)) { return(null); } OpcSessionCacheData entry; if (OpcSessionCache.TryGetValue(sessionID, out entry)) { if (entry.OPCSession != null) { if (entry.OPCSession.Connected) { return(entry.OPCSession); } try { entry.OPCSession.Close(500); } catch { } entry.OPCSession = null; } } else { // create a new entry OpcSessionCacheData newEntry = new OpcSessionCacheData { EndpointURL = endpointURL }; OpcSessionCache.TryAdd(sessionID, newEntry); } Uri endpointURI = new Uri(endpointURL); EndpointDescriptionCollection endpointCollection = DiscoverEndpoints(_configuration, endpointURI, 10); EndpointDescription selectedEndpoint = SelectUaTcpEndpoint(endpointCollection); EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create(_configuration); ConfiguredEndpoint endpoint = new ConfiguredEndpoint(selectedEndpoint.Server, endpointConfiguration); endpoint.Update(selectedEndpoint); // Check if we have a cached endpoint with the same URL and use that one instead foreach (ConfiguredEndpoint cachedEndpoint in OpcCachedEndpoints) { if (cachedEndpoint.EndpointUrl.AbsoluteUri.Equals(endpointURL, StringComparison.InvariantCultureIgnoreCase)) { endpoint = cachedEndpoint; break; } } Session session = await Session.Create( _configuration, endpoint, true, false, sessionID, 60000, new UserIdentity(new AnonymousIdentityToken()), null); if (session != null) { session.KeepAlive += new KeepAliveEventHandler(StandardClient_KeepAlive); // Update our cache data if (OpcSessionCache.TryGetValue(sessionID, out entry)) { if (string.Equals(entry.EndpointURL, endpointURL, StringComparison.InvariantCultureIgnoreCase)) { OpcSessionCacheData newValue = new OpcSessionCacheData { CertThumbprint = entry.CertThumbprint, EndpointURL = entry.EndpointURL, Trusted = entry.Trusted, OPCSession = session }; OpcSessionCache.TryUpdate(sessionID, newValue, entry); } } } return(session); }
/// <summary> /// Подключение к OPC-серверу по его адресу. Выполняется асинхронно. /// </summary> /// <param name="ep">Адрес OPC-сервера</param> /// <returns></returns> public async Task Connect(string endpointUrl) { _config = new ApplicationConfiguration() { ApplicationName = "Console OPC-Client", ApplicationType = ApplicationType.Client, ApplicationUri = "urn:localhost:OPCFoundation:SampleClient", SecurityConfiguration = new SecurityConfiguration { ApplicationCertificate = new CertificateIdentifier { StoreType = "Directory", StorePath = "./OPC Foundation/CertificateStores/MachineDefault", SubjectName = Utils.Format("CN={0}, DC={1}", "Console OPC-Client", Utils.GetHostName()) }, TrustedPeerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "./OPC Foundation/CertificateStores/UA Applications", }, TrustedIssuerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "./OPC Foundation/CertificateStores/UA Certificate Authorities", }, RejectedCertificateStore = new CertificateTrustList { StoreType = "Directory", StorePath = "./OPC Foundation/CertificateStores/RejectedCertificates", }, NonceLength = 32, AutoAcceptUntrustedCertificates = true }, TransportConfigurations = new TransportConfigurationCollection(), TransportQuotas = new TransportQuotas { OperationTimeout = 15000 }, ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 } }; await _config.Validate(ApplicationType.Client); _haveAppCertificate = _config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (_haveAppCertificate && _config.SecurityConfiguration.AutoAcceptUntrustedCertificates) { _config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); } Uri endpointURI = new Uri(endpointUrl); var endpointCollection = DiscoverEndpoints(_config, endpointURI, 10); var selectedEndpoint = SelectUaTcpEndpoint(endpointCollection, _haveAppCertificate); var endpointConfiguration = EndpointConfiguration.Create(_config); var endpoint = new ConfiguredEndpoint(selectedEndpoint.Server, endpointConfiguration); endpoint.Update(selectedEndpoint); _session = await Session.Create(_config, endpoint, true, "Console OPC Client", 60000, null, null); _subscription = new Subscription(_session.DefaultSubscription) { PublishingInterval = 1000 }; }
public async Task <ConnectionStatus> OpcClient(string endpointURL) { try { Uri endpointURI = new Uri(endpointURL); var selectedEndpoint = CoreClientUtils.SelectEndpoint(endpointURL, false, 15000); info.LabelText = "Selected endpoint uses: " + selectedEndpoint.SecurityPolicyUri.Substring(selectedEndpoint.SecurityPolicyUri.LastIndexOf('#') + 1); var endpointConfiguration = EndpointConfiguration.Create(config); var endpoint = new ConfiguredEndpoint(selectedEndpoint.Server, endpointConfiguration); endpoint.Update(selectedEndpoint); var platform = Device.RuntimePlatform; var sessionName = ""; switch (Device.RuntimePlatform) { case "Android": sessionName = "AIS Demonstrator Android Applikation"; break; // other cases are irrelevant for the Industrie 4.0 Demonstrator as of now case "UWP": sessionName = "OPC UA Xamarin Client UWP"; break; case "iOS": sessionName = "OPC UA Xamarin Client IOS"; break; } #region OPC UA User Authentication handling /* * Partially copied from https://github.com/OPCFoundation/UA-.NETStandard/issues/446 */ UserTokenPolicy utp = new UserTokenPolicy(); utp.TokenType = UserTokenType.UserName; UserTokenPolicyCollection utpCollection = new UserTokenPolicyCollection(); utpCollection.Add(utp); selectedEndpoint.UserIdentityTokens = utpCollection; selectedEndpoint.SecurityMode = MessageSecurityMode.SignAndEncrypt; UserIdentity SessionUserIdentity = new UserIdentity(MainActivity.UserName, MainActivity.UserPassword); #endregion session = await Session.Create(config, endpoint, false, sessionName, 30000, SessionUserIdentity, null); if (session != null) { connectionStatus = ConnectionStatus.Connected; #region Subscription + monitoredItems // Code for Monitored Items based on http://opcfoundation.github.io/UA-.NETStandard/help/index.htm#client_development.htm // Create Subscription Subscription subscription = new Subscription() // new Subscription(OpcClient.session.DefaultSubscription) { PublishingInterval = 1000, PublishingEnabled = true }; // CoffeeLevel MonitoredItem CoffeeLevel = new MonitoredItem(subscription.DefaultItem) { StartNodeId = "ns=1;s=CoffeeLevel", DisplayName = "MonitoredCoffeeLevel", AttributeId = Attributes.Value, MonitoringMode = MonitoringMode.Reporting, SamplingInterval = 1000, // check the CoffeeLevel every second QueueSize = 1, // only the most recent value for the CoffeeLevel is needed, thus we only need a queuesize of one DiscardOldest = true // we only need the most recent value for CoffeeLevel }; CoffeeLevel.Notification += (sender, e) => OnNotification(sender, e, ref valueCoffeeLevel); // WaterLevel MonitoredItem WaterLevel = new MonitoredItem(subscription.DefaultItem) { StartNodeId = "ns=1;s=WaterLevel", DisplayName = "MonitoredWaterLevel", AttributeId = Attributes.Value, MonitoringMode = MonitoringMode.Reporting, SamplingInterval = 1000, // check the CoffeeLevel every second QueueSize = 1, // only the most recent value for the CoffeeLevel is needed, thus we only need a queuesize of one DiscardOldest = true // we only need the most recent value for CoffeeLevel }; WaterLevel.Notification += (sender, e) => OnNotification(sender, e, ref valueWaterLevel); // CleanlinessLevel MonitoredItem CleanlinessLevel = new MonitoredItem(subscription.DefaultItem) { StartNodeId = "ns=1;s=Cleanliness", DisplayName = "MonitoredCleanlinessLevel", AttributeId = Attributes.Value, MonitoringMode = MonitoringMode.Reporting, SamplingInterval = 1000, // check the CoffeeLevel every second QueueSize = 1, // only the most recent value for the CoffeeLevel is needed, thus we only need a queuesize of one DiscardOldest = true // we only need the most recent value for CoffeeLevel }; CleanlinessLevel.Notification += (sender, e) => OnNotification(sender, e, ref valueCleanlinessLevel); // add MonitoredItems to Subscription subscription.AddItem(CoffeeLevel); subscription.AddItem(WaterLevel); subscription.AddItem(CleanlinessLevel); // add Subscription to Session session.AddSubscription(subscription); subscription.Create(); #endregion } else { connectionStatus = ConnectionStatus.NotConnected; } // register keep alive handler session.KeepAlive += Client_KeepAlive; } catch { connectionStatus = ConnectionStatus.Error; } return(connectionStatus); }
public async Task ConnectAndMonitor() { _opcSessionSemaphore.Wait(); Trace($"Connect and monitor session and nodes on endpoint '{EndpointUri.AbsoluteUri}'."); try { // if the session is disconnected, create it. if (State == SessionState.Disconnected) { EndpointDescription selectedEndpoint = CoreClientUtils.SelectEndpoint(EndpointUri.AbsoluteUri, true); ConfiguredEndpoint configuredEndpoint = new ConfiguredEndpoint(selectedEndpoint.Server, EndpointConfiguration.Create(OpcConfiguration)); configuredEndpoint.Update(selectedEndpoint); try { uint timeout = SessionTimeout * ((UnsuccessfulConnectionCount >= OpcSessionCreationBackoffMax) ? OpcSessionCreationBackoffMax : UnsuccessfulConnectionCount + 1); Trace($"Create session for endpoint URI '{EndpointUri.AbsoluteUri}' with timeout of {timeout} ms."); Session = await Session.Create( OpcConfiguration, configuredEndpoint, true, false, OpcConfiguration.ApplicationName, timeout, new UserIdentity(new AnonymousIdentityToken()), null); if (Session != null) { Trace($"Session successfully created with Id {Session.SessionId}."); if (!selectedEndpoint.EndpointUrl.Equals(configuredEndpoint.EndpointUrl)) { Trace($"the Server has updated the EndpointUrl to '{selectedEndpoint.EndpointUrl}'"); } // init object state and install keep alive UnsuccessfulConnectionCount = 0; State = SessionState.Connected; Session.KeepAliveInterval = OpcKeepAliveIntervalInSec * 1000; Session.KeepAlive += new KeepAliveEventHandler((sender, e) => StandardClient_KeepAlive(sender, e, Session)); // fetch the namespace array and cache it. it will not change as long the session exists. NodeId namespaceArrayNodeId = new NodeId(Variables.Server_NamespaceArray, 0); DataValue namespaceArrayNodeValue = Session.ReadValue(namespaceArrayNodeId); _namespaceTable.Update(namespaceArrayNodeValue.GetValue <string[]>(null)); // show the available namespaces Trace($"The session to endpoint '{selectedEndpoint.EndpointUrl}' has {_namespaceTable.Count} entries in its namespace array:"); int i = 0; foreach (var ns in _namespaceTable.ToArray()) { Trace($"Namespace index {i++}: {ns}"); } } } catch (Exception e) { Trace(e, $"Session creation to endpoint '{EndpointUri.AbsoluteUri}' failed {++UnsuccessfulConnectionCount} time(s). Please verify if server is up and Publisher configuration is correct."); State = SessionState.Disconnected; Session = null; return; } } // stop monitoring of nodes if requested and remove them from the monitored items list. var itemsToRemove = MonitoredItemsInfo.Where(i => i.State == MonitoredItemInfo.MonitoredItemState.StopMonitoring); if (itemsToRemove.GetEnumerator().MoveNext()) { itemsToRemove.GetEnumerator().Reset(); Trace($"Remove nodes on endpoint '{EndpointUri.AbsoluteUri}'"); Session.DefaultSubscription.RemoveItems(itemsToRemove.Select(i => i.MonitoredItem)); } // ensure all nodes on this session are monitored. Trace($"Start monitoring nodes on endpoint '{EndpointUri.AbsoluteUri}'"); var unmonitoredItems = MonitoredItemsInfo.Where(i => i.State == MonitoredItemInfo.MonitoredItemState.Unmonitored); foreach (var item in unmonitoredItems) { // if the session is disconnected, we stop trying and wait for the next cycle if (State == SessionState.Disconnected) { break; } NodeId currentNodeId; try { Subscription subscription = Session.DefaultSubscription; if (Session.AddSubscription(subscription)) { Trace("Create default subscription."); subscription.Create(); } // lookup namespace index if ExpandedNodeId format has been used and build NodeId identifier. if (!string.IsNullOrEmpty(item.StartNodeId.NamespaceUri)) { currentNodeId = NodeId.Create(item.StartNodeId.Identifier, item.StartNodeId.NamespaceUri, _namespaceTable); } else { currentNodeId = new NodeId((NodeId)item.StartNodeId); } // get the DisplayName for the node, otherwise use the nodeId Node node = Session.ReadNode(currentNodeId); item.DisplayName = node.DisplayName.Text ?? currentNodeId.ToString(); // add the new monitored item. MonitoredItem monitoredItem = new MonitoredItem(subscription.DefaultItem) { StartNodeId = currentNodeId, AttributeId = item.AttributeId, DisplayName = node.DisplayName.Text, MonitoringMode = item.MonitoringMode, SamplingInterval = item.SamplingInterval, QueueSize = item.QueueSize, DiscardOldest = item.DiscardOldest }; monitoredItem.Notification += item.Notification; subscription.AddItem(monitoredItem); subscription.ApplyChanges(); item.MonitoredItem = monitoredItem; item.State = MonitoredItemInfo.MonitoredItemState.Monitoreded; item.EndpointUri = EndpointUri; Trace($"Created monitored item for node '{currentNodeId}' on endpoint '{EndpointUri.AbsoluteUri}'"); } catch (Exception e) when(e.GetType() == typeof(ServiceResultException)) { ServiceResultException sre = (ServiceResultException)e; switch ((uint)sre.Result.StatusCode) { case StatusCodes.BadSessionIdInvalid: { Trace($"Session with Id {Session.SessionId} is no longer available on endpoint '{EndpointUri}'. Cleaning up."); // clean up the session _opcSessionSemaphore.Release(); Disconnect(); break; } case StatusCodes.BadNodeIdInvalid: case StatusCodes.BadNodeIdUnknown: { Trace($"Failed to monitor node '{item.StartNodeId.Identifier}' on endpoint '{EndpointUri}'."); Trace($"OPC UA ServiceResultException is '{sre.Result}'. Please check your publisher configuration for this node."); break; } default: { Trace($"Unhandled OPC UA ServiceResultException '{sre.Result}' when monitoring node '{item.StartNodeId.Identifier}' on endpoint '{EndpointUri}'. Continue."); break; } } } catch (Exception e) { Trace(e, $"Failed to monitor node '{item.StartNodeId.Identifier}' on endpoint '{EndpointUri}'"); } } // shutdown unused sessions. var unusedSessions = OpcSessions.Where(s => s.MonitoredItemsInfo.Count == 0); foreach (var unusedSession in unusedSessions) { await unusedSession.Shutdown(); OpcSessions.Remove(unusedSession); } } finally { _opcSessionSemaphore.Release(); } }
public async Task EndpointConnect() { var endpointCollection = DiscoverEndpoints(Module.Configuration, ServerUrl, 60); var selectedEndpoints = new List <EndpointDescription>(); // Select endpoints foreach (EndpointDescription endpoint in endpointCollection) { if (endpoint.TransportProfileUri == Profiles.UaTcpTransport && endpoint.SecurityLevel >= MinimumSecurityLevel && endpoint.SecurityMode >= MinimumSecurityMode) { // patch endpoint to set the original host name we want to connect to. var url = new UriBuilder(endpoint.EndpointUrl); url.Host = ServerUrl.Host; endpoint.EndpointUrl = url.ToString(); selectedEndpoints.Add(endpoint); } } // // Sort, but descending with highest level first i.e. return // < 0 if x is less than y // > 0 if x is greater than y // 0 if x and y are equal // selectedEndpoints.Sort((y, x) => x.SecurityLevel - y.SecurityLevel); // Do not emit all exceptions as they occur, only throw them all when no connection can be made. var exceptions = new List <Exception>(selectedEndpoints.Count); foreach (EndpointDescription endpoint in selectedEndpoints) { ConfiguredEndpoint configuredEndpoint = new ConfiguredEndpoint( endpoint.Server, EndpointConfiguration.Create(Module.Configuration)); configuredEndpoint.Update(endpoint); try { Console.WriteLine($"Opc.Ua.Client.SampleModule: Trying to create session with mode: {endpoint.SecurityMode}, level:{endpoint.SecurityLevel} to {configuredEndpoint.EndpointUrl}..."); _session = await Session.Create( Module.Configuration, configuredEndpoint, true, false, Module.Configuration.ApplicationName, 60000, // TODO: Make user identity configurable, plus add dedicated security policy new UserIdentity(new AnonymousIdentityToken()), null); if (_session != null) { var subscription = new Subscription(_session.DefaultSubscription); subscription.PublishingInterval = PublishingInterval; // TODO: Make other subscription settings configurable... subscription.AddItems(MonitoredItems); _session.AddSubscription(subscription); subscription.Create(); Console.WriteLine($"Opc.Ua.Client.SampleModule: Session with mode: {endpoint.SecurityMode}, level:{endpoint.SecurityLevel} to {configuredEndpoint.EndpointUrl} established!"); _session.KeepAlive += new KeepAliveEventHandler(StandardClient_KeepAlive); // Done return; } exceptions.Add(new Exception($"ERROR: Create session to endpoint {endpoint.ToString()} returned null.")); } catch (AggregateException ae) { exceptions.AddRange(ae.InnerExceptions); } catch (Exception ex) { exceptions.Add(ex); } // ... try another endpoint until we do not have any more... Console.WriteLine($"Opc.Ua.Client.SampleModule: WARNING Could not create session to endpoint {endpoint.ToString()}..."); } throw new AggregateException("Failed to find acceptable endpoint to connect to.", exceptions); }
public static async Task ConsoleSampleClient(string endpointURL) { Console.WriteLine("1 - Create an Application Configuration."); var config = new ApplicationConfiguration { ApplicationName = "UA Core Sample Client", ApplicationType = ApplicationType.Client, ApplicationUri = "urn:"+Utils.GetHostName()+":OPCFoundation:CoreSampleClient", SecurityConfiguration = new SecurityConfiguration { ApplicationCertificate = new CertificateIdentifier { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/MachineDefault", SubjectName = "UA Core Sample Client" }, TrustedPeerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Applications", }, TrustedIssuerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Certificate Authorities", }, RejectedCertificateStore = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/RejectedCertificates", }, NonceLength = 32, AutoAcceptUntrustedCertificates = true }, TransportConfigurations = new TransportConfigurationCollection(), TransportQuotas = new TransportQuotas { OperationTimeout = 120000 }, ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 120000 } }; await config.Validate(ApplicationType.Client); bool haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (!haveAppCertificate) { Console.WriteLine(" INFO: Creating new application certificate: {0}", config.ApplicationName); X509Certificate2 certificate = CertificateFactory.CreateCertificate( config.SecurityConfiguration.ApplicationCertificate.StoreType, config.SecurityConfiguration.ApplicationCertificate.StorePath, config.ApplicationUri, config.ApplicationName, config.SecurityConfiguration.ApplicationCertificate.SubjectName ); config.SecurityConfiguration.ApplicationCertificate.Certificate = certificate; } haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (haveAppCertificate) { config.ApplicationUri = Utils.GetApplicationUriFromCertificate(config.SecurityConfiguration.ApplicationCertificate.Certificate); if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates) { config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); } } else { Console.WriteLine(" WARN: missing application certificate, using unsecure connection."); } Console.WriteLine("2 - Discover endpoints of {0}.", endpointURL); Uri endpointURI = new Uri(endpointURL); var endpointCollection = DiscoverEndpoints(config, endpointURI, 10); var selectedEndpoint = SelectUaTcpEndpoint(endpointCollection, haveAppCertificate); Console.WriteLine(" Selected endpoint uses: {0}", selectedEndpoint.SecurityPolicyUri.Substring(selectedEndpoint.SecurityPolicyUri.LastIndexOf('#') + 1)); #if PERF for (int i = 1; ; i++) { #endif Console.WriteLine("3 - Create a session with OPC UA server."); var endpointConfiguration = EndpointConfiguration.Create(config); var endpoint = new ConfiguredEndpoint(selectedEndpoint.Server, endpointConfiguration); endpoint.Update(selectedEndpoint); var session = await Session.Create(config, endpoint, true, ".Net Core OPC UA Console Client", 60000, null, null); // Access underlying proxy socket var channel = session.TransportChannel as IMessageSocketChannel; var socket = channel.Socket as ProxyMessageSocket; var proxySocket = socket.ProxySocket; Console.WriteLine(" Connected through proxy {0}.", proxySocket.LocalEndPoint.ToString()); ReferenceDescriptionCollection references; Byte[] continuationPoint; references = session.FetchReferences(ObjectIds.ObjectsFolder); Stopwatch w = Stopwatch.StartNew(); Console.WriteLine($"4 - Browse the OPC UA server namespace."); session.Browse( null, null, ObjectIds.ObjectsFolder, 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint) NodeClass.Variable | (uint) NodeClass.Object | (uint) NodeClass.Method, out continuationPoint, out references); Console.WriteLine(" DisplayName, BrowseName, NodeClass"); BrowseChildren("", references, session); Console.WriteLine($" .... took {w.ElapsedMilliseconds} ms..."); #if PERF session.Close(); } #else Console.WriteLine("5 - Create a subscription with publishing interval of 1 second."); var subscription = new Subscription(session.DefaultSubscription) { PublishingInterval = 1000 }; Console.WriteLine("6 - Add a list of items (server current time and status) to the subscription."); var list = new List<MonitoredItem> { new MonitoredItem(subscription.DefaultItem) { DisplayName = "ServerStatusCurrentTime", StartNodeId = "i=2258" } }; list.ForEach(i => i.Notification += OnNotification); subscription.AddItems(list); Console.WriteLine("7 - Add the subscription to the session."); session.AddSubscription(subscription); subscription.Create(); Console.WriteLine("8 - Running...Press any key to exit..."); #endif }
public static async Task ConsoleSampleClient(string endpointURL) { Console.WriteLine("1 - Create an Application Configuration."); var config = new ApplicationConfiguration() { ApplicationName = "UA Core Sample Client", ApplicationType = ApplicationType.Client, ApplicationUri = "urn:" + Utils.GetHostName() + ":OPCFoundation:CoreSampleClient", SecurityConfiguration = new SecurityConfiguration { ApplicationCertificate = new CertificateIdentifier { StoreType = "X509Store", StorePath = "CurrentUser\\UA_MachineDefault", SubjectName = "UA Core Sample Client" }, TrustedPeerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Applications", }, TrustedIssuerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Certificate Authorities", }, RejectedCertificateStore = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/RejectedCertificates", }, NonceLength = 32, AutoAcceptUntrustedCertificates = true }, TransportConfigurations = new TransportConfigurationCollection(), TransportQuotas = new TransportQuotas { OperationTimeout = 15000 }, ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 } }; await config.Validate(ApplicationType.Client); bool haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (!haveAppCertificate) { Console.WriteLine(" INFO: Creating new application certificate: {0}", config.ApplicationName); X509Certificate2 certificate = CertificateFactory.CreateCertificate( config.SecurityConfiguration.ApplicationCertificate.StoreType, config.SecurityConfiguration.ApplicationCertificate.StorePath, config.ApplicationUri, config.ApplicationName, config.SecurityConfiguration.ApplicationCertificate.SubjectName ); config.SecurityConfiguration.ApplicationCertificate.Certificate = certificate; } haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (haveAppCertificate) { config.ApplicationUri = Utils.GetApplicationUriFromCertificate(config.SecurityConfiguration.ApplicationCertificate.Certificate); if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates) { config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); } } else { Console.WriteLine(" WARN: missing application certificate, using unsecure connection."); } Console.WriteLine("2 - Discover endpoints of {0}.", endpointURL); Uri endpointURI = new Uri(endpointURL); var endpointCollection = DiscoverEndpoints(config, endpointURI, 10); var selectedEndpoint = SelectUaTcpEndpoint(endpointCollection, haveAppCertificate); Console.WriteLine(" Selected endpoint uses: {0}", selectedEndpoint.SecurityPolicyUri.Substring(selectedEndpoint.SecurityPolicyUri.LastIndexOf('#') + 1)); Console.WriteLine("3 - Create a session with OPC UA server."); var endpointConfiguration = EndpointConfiguration.Create(config); var endpoint = new ConfiguredEndpoint(selectedEndpoint.Server, endpointConfiguration); endpoint.Update(selectedEndpoint); var session = await Session.Create(config, endpoint, true, ".Net Core OPC UA Console Client", 60000, new UserIdentity(new AnonymousIdentityToken()), null); Console.WriteLine("4 - Browse the OPC UA server namespace."); ReferenceDescriptionCollection references; Byte[] continuationPoint; references = session.FetchReferences(ObjectIds.ObjectsFolder); session.Browse( null, null, ObjectIds.ObjectsFolder, 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out continuationPoint, out references); Console.WriteLine(" DisplayName, BrowseName, NodeClass"); foreach (var rd in references) { Console.WriteLine(" {0}, {1}, {2}", rd.DisplayName, rd.BrowseName, rd.NodeClass); ReferenceDescriptionCollection nextRefs; byte[] nextCp; session.Browse( null, null, ExpandedNodeId.ToNodeId(rd.NodeId, session.NamespaceUris), 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out nextCp, out nextRefs); foreach (var nextRd in nextRefs) { Console.WriteLine(" + {0}, {1}, {2}", nextRd.DisplayName, nextRd.BrowseName, nextRd.NodeClass); } } Console.WriteLine("5 - Create a subscription with publishing interval of 1 second."); var subscription = new Subscription(session.DefaultSubscription) { PublishingInterval = 1000 }; Console.WriteLine("6 - Add a list of items (server current time and status) to the subscription."); var list = new List <MonitoredItem> { new MonitoredItem(subscription.DefaultItem) { DisplayName = "ServerStatusCurrentTime", StartNodeId = "i=2258" } }; list.ForEach(i => i.Notification += OnNotification); subscription.AddItems(list); Console.WriteLine("7 - Add the subscription to the session."); session.AddSubscription(subscription); subscription.Create(); Console.WriteLine("8 - Running...Press any key to exit..."); Console.ReadKey(true); }
private void OkBTN_Click(object sender, EventArgs e) { try { // check that discover has completed. if (!m_discoverySucceeded) { DialogResult result = MessageBox.Show( "Endpoint information may be out of date because the discovery process has not completed. Continue anyways?", this.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (result != DialogResult.Yes) { return; } } EndpointConfiguration configuration = m_endpointConfiguration; if (configuration == null) { configuration = EndpointConfiguration.Create(m_configuration); } if (m_currentDescription == null) { m_currentDescription = CreateDescriptionFromSelections(); } // the discovery endpoint should always be on the same machine as the server. // if there is a mismatch it is likely because the server has multiple addresses // and was not configured to return the current address to the client. // The code automatically updates the domain in the url. Uri endpointUrl = Utils.ParseUri(m_currentDescription.EndpointUrl); if (m_discoverySucceeded) { if (!Utils.AreDomainsEqual(endpointUrl, m_discoveryUrl)) { UriBuilder url = new UriBuilder(endpointUrl); url.Host = m_discoveryUrl.DnsSafeHost; if (url.Scheme == m_discoveryUrl.Scheme) { url.Port = m_discoveryUrl.Port; } endpointUrl = url.Uri; m_currentDescription.EndpointUrl = endpointUrl.ToString(); } } // set the encoding. Encoding encoding = (Encoding)EncodingCB.SelectedItem; configuration.UseBinaryEncoding = encoding != Encoding.Xml; if (m_endpoint == null) { m_endpoint = new ConfiguredEndpoint(null, m_currentDescription, configuration); } else { m_endpoint.Update(m_currentDescription); m_endpoint.Update(configuration); } // set the user token policy. m_endpoint.SelectedUserTokenPolicyIndex = FindBestUserTokenPolicy(m_currentDescription); // update the user identity. UserTokenType userTokenType = (UserTokenType)UserTokenTypeCB.SelectedItem; UserIdentityToken userIdentity = null; if (!m_userIdentities.TryGetValue(userTokenType, out userIdentity)) { userIdentity = null; } m_endpoint.UserIdentity = userIdentity; DialogResult = DialogResult.OK; } catch (Exception exception) { GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception); } }
public static async Task ConsoleSampleClient(string endpointURL) { Console.WriteLine("1 - Create an Application Configuration."); var config = new ApplicationConfiguration() { ApplicationName = "UA Core Sample Client", ApplicationType = ApplicationType.Client, ApplicationUri = "urn:"+Utils.GetHostName()+":OPCFoundation:CoreSampleClient", SecurityConfiguration = new SecurityConfiguration { ApplicationCertificate = new CertificateIdentifier { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/MachineDefault", SubjectName = "UA Core Sample Client" }, TrustedPeerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Applications", }, TrustedIssuerCertificates = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/UA Certificate Authorities", }, RejectedCertificateStore = new CertificateTrustList { StoreType = "Directory", StorePath = "OPC Foundation/CertificateStores/RejectedCertificates", }, NonceLength = 32, AutoAcceptUntrustedCertificates = true }, TransportConfigurations = new TransportConfigurationCollection(), TransportQuotas = new TransportQuotas { OperationTimeout = 15000 }, ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 } }; await config.Validate(ApplicationType.Client); bool haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (!haveAppCertificate) { Console.WriteLine(" INFO: Creating new application certificate: {0}", config.ApplicationName); X509Certificate2 certificate = CertificateFactory.CreateCertificate( config.SecurityConfiguration.ApplicationCertificate.StoreType, config.SecurityConfiguration.ApplicationCertificate.StorePath, config.ApplicationUri, config.ApplicationName ); config.SecurityConfiguration.ApplicationCertificate.Certificate = certificate; } haveAppCertificate = config.SecurityConfiguration.ApplicationCertificate.Certificate != null; if (haveAppCertificate) { config.ApplicationUri = Utils.GetApplicationUriFromCertificate(config.SecurityConfiguration.ApplicationCertificate.Certificate); if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates) { config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); } } else { Console.WriteLine(" WARN: missing application certificate, using unsecure connection."); } Console.WriteLine("2 - Discover endpoints of {0}.", endpointURL); Uri endpointURI = new Uri(endpointURL); var endpointCollection = DiscoverEndpoints(config, endpointURI, 10); var selectedEndpoint = SelectUaTcpEndpoint(endpointCollection, haveAppCertificate); Console.WriteLine(" Selected endpoint uses: {0}", selectedEndpoint.SecurityPolicyUri.Substring(selectedEndpoint.SecurityPolicyUri.LastIndexOf('#') + 1)); Console.WriteLine("3 - Create a session with OPC UA server."); var endpointConfiguration = EndpointConfiguration.Create(config); var endpoint = new ConfiguredEndpoint(selectedEndpoint.Server, endpointConfiguration); endpoint.Update(selectedEndpoint); var session = await Session.Create(config, endpoint, true, ".Net Core OPC UA Console Client", 60000, null, null); Console.WriteLine("4 - Browse the OPC UA server namespace."); ReferenceDescriptionCollection references; Byte[] continuationPoint; references = session.FetchReferences(ObjectIds.ObjectsFolder); session.Browse( null, null, ObjectIds.ObjectsFolder, 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out continuationPoint, out references); Console.WriteLine(" DisplayName, BrowseName, NodeClass"); foreach (var rd in references) { Console.WriteLine(" {0}, {1}, {2}", rd.DisplayName, rd.BrowseName, rd.NodeClass); ReferenceDescriptionCollection nextRefs; byte[] nextCp; session.Browse( null, null, ExpandedNodeId.ToNodeId(rd.NodeId, session.NamespaceUris), 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out nextCp, out nextRefs); foreach (var nextRd in nextRefs) { Console.WriteLine(" + {0}, {1}, {2}", nextRd.DisplayName, nextRd.BrowseName, nextRd.NodeClass); } } Console.WriteLine("5 - Create a subscription with publishing interval of 1 second."); var subscription = new Subscription(session.DefaultSubscription) { PublishingInterval = 1000 }; Console.WriteLine("6 - Add a list of items (server current time and status) to the subscription."); var list = new List<MonitoredItem> { new MonitoredItem(subscription.DefaultItem) { DisplayName = "ServerStatusCurrentTime", StartNodeId = "i=2258" } }; list.ForEach(i => i.Notification += OnNotification); subscription.AddItems(list); Console.WriteLine("7 - Add the subscription to the session."); session.AddSubscription(subscription); subscription.Create(); Console.WriteLine("8 - Running...Press any key to exit..."); Console.ReadKey(true); }