/// <summary> /// Does any processing after a monitored item is created. /// </summary> protected override void OnCreateMonitoredItem( ISystemContext systemContext, MonitoredItemCreateRequest itemToCreate, MonitoredNode monitoredNode, DataChangeMonitoredItem monitoredItem) { // TBD }
/// <summary> /// Creates a set of monitored items. /// </summary> public MonitoredItem CreateMonitoredItem( OperationContext context, INodeManager nodeManager, object handle, uint subscriptionId, uint monitoredItemId, TimestampsToReturn timestampsToReturn, double publishingInterval, MonitoredItemCreateRequest itemToCreate, EventFilter filter) { lock (m_lock) { // calculate sampling interval. double samplingInterval = itemToCreate.RequestedParameters.SamplingInterval; if (samplingInterval < 0) { samplingInterval = publishingInterval; } // limit the queue size. uint queueSize = itemToCreate.RequestedParameters.QueueSize; if (queueSize > m_maxEventQueueSize) { queueSize = m_maxEventQueueSize; } // create the monitored item. MonitoredItem monitoredItem = new MonitoredItem( m_server, nodeManager, handle, subscriptionId, monitoredItemId, context.Session, itemToCreate.ItemToMonitor, context.DiagnosticsMask, timestampsToReturn, itemToCreate.MonitoringMode, itemToCreate.RequestedParameters.ClientHandle, filter, filter, null, samplingInterval, queueSize, itemToCreate.RequestedParameters.DiscardOldest, MinimumSamplingIntervals.Continuous); // save the monitored item. m_monitoredItems.Add(monitoredItemId, monitoredItem); return(monitoredItem); } }
/// <summary> /// Updates the object with the results of a create monitored item request. /// </summary> public void SetCreateResult( MonitoredItemCreateRequest request, MonitoredItemCreateResult result, int index, DiagnosticInfoCollection diagnosticInfos, ResponseHeader responseHeader) { ServiceResult error = null; if (StatusCode.IsBad(result.StatusCode)) { error = ClientBase.GetResult(result.StatusCode, index, diagnosticInfos, responseHeader); } m_status.SetCreateResult(request, result, error); m_attributesModified = false; }
/// <summary> /// Creates a monitored item. /// </summary> public void CreateMonitoredItem( TimestampsToReturn timestampsToReturn, MonitoredItemCreateRequest request, MonitoredItemCreateResult result, DiagnosticInfo diagnosticInfo) { lock (m_lock) { // initialize the monitored item. MonitoredItem monitoredItem = new MonitoredItem(); monitoredItem.Id = (uint)Interlocked.Increment(ref m_monitoredItemCounter); monitoredItem.ItemToMonitor = request.ItemToMonitor; monitoredItem.MonitoringMode = request.MonitoringMode; monitoredItem.Parameters = request.RequestedParameters; monitoredItem.NextScanTime = 0; // use the publishing interval as the default. if (monitoredItem.Parameters.SamplingInterval < 0) { monitoredItem.Parameters.SamplingInterval = m_publishingInterval; } // ensure the queue is at least one. if (monitoredItem.Parameters.QueueSize == 0) { monitoredItem.Parameters.QueueSize = 1; } result.MonitoredItemId = monitoredItem.Id; result.RevisedQueueSize = monitoredItem.Parameters.QueueSize; result.RevisedSamplingInterval = monitoredItem.Parameters.SamplingInterval; result.FilterResult = new ExtensionObject(); m_monitoredItems.Add(monitoredItem.Id, monitoredItem); // start a background thread that scans the items. if (m_monitoredItems.Count == 1) { ThreadPool.QueueUserWorkItem(OnScanItems); } } }
public MonitoredItem CreateMonitoredItem( OperationContext context, INodeManager nodeManager, object handle, uint subscriptionId, uint monitoredItemId, TimestampsToReturn timestampsToReturn, MonitoredItemCreateRequest itemToCreate, EventFilter filter) { return(CreateMonitoredItem( context, nodeManager, handle, subscriptionId, monitoredItemId, timestampsToReturn, 0, itemToCreate, filter)); }
/// <summary> /// Updates the object with the results of a create monitored item request. /// </summary> internal void SetCreateResult( MonitoredItemCreateRequest request, MonitoredItemCreateResult result, ServiceResult error) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (result == null) { throw new ArgumentNullException(nameof(result)); } m_nodeId = request.ItemToMonitor.NodeId; m_attributeId = request.ItemToMonitor.AttributeId; m_indexRange = request.ItemToMonitor.IndexRange; m_encoding = request.ItemToMonitor.DataEncoding; m_monitoringMode = request.MonitoringMode; m_clientHandle = request.RequestedParameters.ClientHandle; m_samplingInterval = request.RequestedParameters.SamplingInterval; m_queueSize = request.RequestedParameters.QueueSize; m_discardOldest = request.RequestedParameters.DiscardOldest; m_filter = null; m_error = error; if (request.RequestedParameters.Filter != null) { m_filter = Utils.Clone(request.RequestedParameters.Filter.Body) as MonitoringFilter; } if (ServiceResult.IsGood(error)) { m_id = result.MonitoredItemId; m_samplingInterval = result.RevisedSamplingInterval; m_queueSize = result.RevisedQueueSize; } }
/// <summary> /// Creates a new set of monitored items for a set of variables. /// </summary> /// <remarks> /// This method only handles data change subscriptions. Event subscriptions are created by the SDK. /// </remarks> protected override ServiceResult CreateMonitoredItem(ServerSystemContext context, NodeHandle handle, uint subscriptionId, double publishingInterval, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoredItemCreateRequest itemToCreate, ref long globalIdCounter, out MonitoringFilterResult filterResult, out IMonitoredItem monitoredItem) { filterResult = null; monitoredItem = null; // validate parameters. MonitoringParameters parameters = itemToCreate.RequestedParameters; // validate attribute. if (!Attributes.IsValid(handle.Node.NodeClass, itemToCreate.ItemToMonitor.AttributeId)) { return(StatusCodes.BadAttributeIdInvalid); } NodeState cachedNode = AddNodeToComponentCache(context, handle, handle.Node); // check if the node is already being monitored. MonitoredNode2 monitoredNode = null; if (!MonitoredNodes.TryGetValue(handle.Node.NodeId, out monitoredNode)) { MonitoredNodes[handle.Node.NodeId] = monitoredNode = new MonitoredNode2(this, cachedNode); } handle.Node = monitoredNode.Node; handle.MonitoredNode = monitoredNode; // create a globally unique identifier. uint monitoredItemId = Utils.IncrementIdentifier(ref globalIdCounter); // determine the sampling interval. double samplingInterval = itemToCreate.RequestedParameters.SamplingInterval; if (samplingInterval < 0) { samplingInterval = publishingInterval; } // ensure minimum sampling interval is not exceeded. if (itemToCreate.ItemToMonitor.AttributeId == Attributes.Value) { BaseVariableState variable = handle.Node as BaseVariableState; if (variable != null && samplingInterval < variable.MinimumSamplingInterval) { samplingInterval = variable.MinimumSamplingInterval; } } // put a large upper limit on sampling. if (samplingInterval == Double.MaxValue) { samplingInterval = 365 * 24 * 3600 * 1000.0; } // put an upper limit on queue size. uint queueSize = itemToCreate.RequestedParameters.QueueSize; if (queueSize > MaxQueueSize) { queueSize = MaxQueueSize; } // validate the monitoring filter. Range euRange = null; MonitoringFilter filterToUse = null; ServiceResult error = ValidateMonitoringFilter( context, handle, itemToCreate.ItemToMonitor.AttributeId, samplingInterval, queueSize, parameters.Filter, out filterToUse, out euRange, out filterResult); if (ServiceResult.IsBad(error)) { return(error); } // create the item. MonitoredItem datachangeItem = new ComMonitoredItem( Server, this, handle, subscriptionId, monitoredItemId, context.OperationContext.Session, itemToCreate.ItemToMonitor, diagnosticsMasks, timestampsToReturn, itemToCreate.MonitoringMode, itemToCreate.RequestedParameters.ClientHandle, filterToUse, filterToUse, euRange, samplingInterval, queueSize, itemToCreate.RequestedParameters.DiscardOldest, 0); // report the initial value. ReadInitialValue(context, handle, datachangeItem); // update monitored item list. monitoredItem = datachangeItem; // save the monitored item. MonitoredItems.Add(monitoredItemId, datachangeItem); monitoredNode.Add(datachangeItem); // report change. OnMonitoredItemCreated(context, handle, datachangeItem); return(error); }
/// <summary> /// Creates a new monitored item and calls StartMonitoring(). /// </summary> public virtual MonitoredItem CreateMonitoredItem( OperationContext context, uint subscriptionId, double publishingInterval, TimestampsToReturn timestampsToReturn, uint monitoredItemId, object managerHandle, MonitoredItemCreateRequest itemToCreate, Range range, double minimumSamplingInterval) { // use publishing interval as sampling interval. double samplingInterval = itemToCreate.RequestedParameters.SamplingInterval; if (samplingInterval < 0) { samplingInterval = publishingInterval; } // limit the sampling interval. if (minimumSamplingInterval > 0 && samplingInterval < minimumSamplingInterval) { samplingInterval = minimumSamplingInterval; } // calculate queue size. uint queueSize = itemToCreate.RequestedParameters.QueueSize; if (queueSize > m_maxQueueSize) { queueSize = m_maxQueueSize; } // get filter. MonitoringFilter filter = null; if (!ExtensionObject.IsNull(itemToCreate.RequestedParameters.Filter)) { filter = itemToCreate.RequestedParameters.Filter.Body as MonitoringFilter; } // update limits for event filters. if (filter is EventFilter) { if (queueSize == 0) { queueSize = Int32.MaxValue; } samplingInterval = 0; } // check if the queue size was not specified. if (queueSize == 0) { queueSize = 1; } // create monitored item. MonitoredItem monitoredItem = CreateMonitoredItem( m_server, m_nodeManager, managerHandle, subscriptionId, monitoredItemId, context.Session, itemToCreate.ItemToMonitor, context.DiagnosticsMask, timestampsToReturn, itemToCreate.MonitoringMode, itemToCreate.RequestedParameters.ClientHandle, filter, filter, range, samplingInterval, queueSize, itemToCreate.RequestedParameters.DiscardOldest, samplingInterval); // start sampling. StartMonitoring(context, monitoredItem); // return item. return monitoredItem; }
/// <summary> /// Creates a new set of monitored items for a set of variables. /// </summary> /// <remarks> /// This method only handles data change subscriptions. Event subscriptions are created by the SDK. /// </remarks> public override void CreateMonitoredItems( OperationContext context, uint subscriptionId, double publishingInterval, TimestampsToReturn timestampsToReturn, IList <MonitoredItemCreateRequest> itemsToCreate, IList <ServiceResult> errors, IList <MonitoringFilterResult> filterResults, IList <IMonitoredItem> monitoredItems, ref long globalIdCounter) { ServerSystemContext systemContext = _defaultSystemContext.Copy(context); IDictionary <NodeId, NodeState> operationCache = new NodeIdDictionary <NodeState>(); List <NodeHandle> nodesToValidate = new List <NodeHandle>(); List <IMonitoredItem> createdItems = new List <IMonitoredItem>(); lock (Lock) { for (int ii = 0; ii < itemsToCreate.Count; ii++) { MonitoredItemCreateRequest monitoredItemCreateRequest = itemsToCreate[ii]; // skip items that have already been processed. if (monitoredItemCreateRequest.Processed) { continue; } ReadValueId itemToMonitor = monitoredItemCreateRequest.ItemToMonitor; // check for valid handle. NodeHandle handle = GetManagerHandle(systemContext, itemToMonitor.NodeId, operationCache); if (handle == null) { continue; } // owned by this node manager. monitoredItemCreateRequest.Processed = true; // must validate node in a seperate operation. errors[ii] = StatusCodes.BadNodeIdUnknown; handle.Index = ii; nodesToValidate.Add(handle); } // check for nothing to do. if (nodesToValidate.Count == 0) { return; } } // validates the nodes (reads values from the underlying data source if required). for (int ii = 0; ii < nodesToValidate.Count; ii++) { NodeHandle handle = nodesToValidate[ii]; MonitoringFilterResult filterResult = null; IMonitoredItem monitoredItem = null; lock (Lock) { // validate node. NodeState source = ValidateNode(systemContext, handle, operationCache); if (source == null) { continue; } MonitoredItemCreateRequest itemToCreate = itemsToCreate[handle.Index]; // create monitored item. errors[handle.Index] = CreateMonitoredItem( systemContext, handle, subscriptionId, publishingInterval, context.DiagnosticsMask, timestampsToReturn, itemToCreate, ref globalIdCounter, out filterResult, out monitoredItem); } // save any filter error details. filterResults[handle.Index] = filterResult; if (ServiceResult.IsBad(errors[handle.Index])) { continue; } // save the monitored item. monitoredItems[handle.Index] = monitoredItem; createdItems.Add(monitoredItem); } // do any post processing. OnCreateMonitoredItemsComplete(systemContext, createdItems); }
/// <summary> /// Updates the object with the results of a create monitored item request. /// </summary> internal void SetCreateResult( MonitoredItemCreateRequest request, MonitoredItemCreateResult result, ServiceResult error) { if (request == null) throw new ArgumentNullException("request"); if (result == null) throw new ArgumentNullException("result"); m_nodeId = request.ItemToMonitor.NodeId; m_attributeId = request.ItemToMonitor.AttributeId; m_indexRange = request.ItemToMonitor.IndexRange; m_encoding = request.ItemToMonitor.DataEncoding; m_monitoringMode = request.MonitoringMode; m_clientHandle = request.RequestedParameters.ClientHandle; m_samplingInterval = request.RequestedParameters.SamplingInterval; m_queueSize = request.RequestedParameters.QueueSize; m_discardOldest = request.RequestedParameters.DiscardOldest; m_filter = null; m_error = error; if (request.RequestedParameters.Filter != null) { m_filter = Utils.Clone(request.RequestedParameters.Filter.Body) as MonitoringFilter; } if (ServiceResult.IsGood(error)) { m_id = result.MonitoredItemId; m_samplingInterval = result.RevisedSamplingInterval; m_queueSize = result.RevisedQueueSize; } }
/// <summary> /// Does any processing after a monitored item is created. /// </summary> protected virtual void OnCreateMonitoredItem( ISystemContext systemContext, MonitoredItemCreateRequest itemToCreate, MonitoredNode monitoredNode, DataChangeMonitoredItem monitoredItem) { // does nothing. }
/// <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) { while (!token.IsCancellationRequested) { await this.whenSubscribed.Task; this.progress.Report(CommunicationState.Opening); try { if (this.endpointUrl is null) { throw new InvalidOperationException("The endpointUrl field must not be null. Please, use the Subscription attribute properly."); } // 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(false); // 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 = ExpandedNodeId.ToNodeId(m.NodeId, this.InnerChannel.NamespaceUris), 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(); //split requests array to MaxMonitoredItemsPerCall chunks int maxmonitoreditemspercall = 100; MonitoredItemCreateRequest[] requests_chunk; int chunk_size; for (int i_chunk = 0; i_chunk < requests.Length; i_chunk += maxmonitoreditemspercall) { chunk_size = Math.Min(maxmonitoreditemspercall, requests.Length - i_chunk); requests_chunk = new MonitoredItemCreateRequest[chunk_size]; Array.Copy(requests, i_chunk, requests_chunk, 0, chunk_size); var itemsRequest = new CreateMonitoredItemsRequest { SubscriptionId = id, ItemsToCreate = requests_chunk, }; var itemsResponse = await this.innerChannel.CreateMonitoredItemsAsync(itemsRequest); if (itemsResponse.Results is { } results) { for (int i = 0; i < results.Length; i++) { var item = items[i]; var result = results[i]; if (result is null) { this.logger?.LogError($"Error creating MonitoredItem for {item.NodeId}. The result is null."); continue; } 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); } } }
/// <summary> /// Adds the MonitoredItems to the request collection. /// </summary> private void AddMonitoredItems( Node node, MonitoredItemCreateRequestCollection itemsToCreate, params uint[] attributeIds) { if (attributeIds != null) { for (int ii = 0; ii < attributeIds.Length; ii++) { MonitoredItemCreateRequest request = new MonitoredItemCreateRequest(); request.ItemToMonitor.NodeId = node.NodeId; request.ItemToMonitor.AttributeId = attributeIds[ii]; request.MonitoringMode = MonitoringMode.Reporting; request.RequestedParameters.ClientHandle = ++m_lastClientHandle; request.RequestedParameters.SamplingInterval = 6000000; request.RequestedParameters.QueueSize = 0; request.RequestedParameters.DiscardOldest = true; request.RequestedParameters.Filter = null; request.Handle = node; itemsToCreate.Add(request); } } }
/// <summary> /// Validates a monitored item create request parameter. /// </summary> protected static ServiceResult ValidateMonitoredItemCreateRequest(MonitoredItemCreateRequest item) { // check for null structure. if (item == null) { return new ServiceResult(StatusCodes.BadStructureMissing); } // validate read value id component. ServiceResult error = ReadValueId.Validate(item.ItemToMonitor); if (ServiceResult.IsBad(error)) { return error; } // check for valid monitoring mode. if ((int)item.MonitoringMode < 0 || (int)item.MonitoringMode > (int)MonitoringMode.Reporting) { return new ServiceResult(StatusCodes.BadMonitoringModeInvalid); } // check for null structure. MonitoringParameters attributes = item.RequestedParameters; error = ValidateMonitoringAttributes(attributes); if (ServiceResult.IsBad(error)) { return error; } // check that no filter is specified for non-value attributes. if (item.ItemToMonitor.AttributeId != Attributes.Value && item.ItemToMonitor.AttributeId != Attributes.EventNotifier) { if (!ExtensionObject.IsNull(attributes.Filter)) { return new ServiceResult(StatusCodes.BadFilterNotAllowed); } } else { error = ValidateMonitoringFilter(attributes.Filter); if (ServiceResult.IsBad(error)) { return error; } } // passed basic validation. return null; }
public static async Task ReadSubscribed(CancellationToken token = default(CancellationToken)) { { // setup logger var loggerFactory = new LoggerFactory(); loggerFactory.AddConsole(LogLevel.Information); //var logger = loggerFactory?.CreateLogger<Program>(); // Describe this app. var appDescription = new ApplicationDescription() { ApplicationName = "DataLoggingConsole", ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:DataLoggingConsole", ApplicationType = ApplicationType.Client, }; // Create a certificate store on disk. // Create array of NodeIds to log. while (!token.IsCancellationRequested) { try { // Discover endpoints. var getEndpointsRequest = new GetEndpointsRequest { EndpointUrl = discoveryUrl, ProfileUris = new[] { TransportProfileUris.UaTcpTransport } }; var getEndpointsResponse = await UaTcpDiscoveryService.GetEndpointsAsync(getEndpointsRequest) .ConfigureAwait(false); if (getEndpointsResponse.Endpoints == null || getEndpointsResponse.Endpoints.Length == 0) { throw new InvalidOperationException($"'{discoveryUrl}' returned no endpoints."); } // Choose the endpoint with highest security level. var remoteEndpoint = getEndpointsResponse.Endpoints.OrderBy(e => e.SecurityLevel).Last(); // Create a session with the server. var channel = new UaTcpSessionChannel(appDescription, certificateStore, async e => GetIUserIdentity(remoteEndpoint).GetAwaiter().GetResult(), remoteEndpoint, loggerFactory); try { await channel.OpenAsync(); var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = 1000, RequestedMaxKeepAliveCount = 10, RequestedLifetimeCount = 30, PublishingEnabled = true }; var subscriptionResponse = await channel.CreateSubscriptionAsync(subscriptionRequest); var id = subscriptionResponse.SubscriptionId; var itemsToCreate = new MonitoredItemCreateRequest[] { #region MonitoredItems new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Admin.ProdProcessedCount"), AttributeId = AttributeIds.Value }, //ProdProcessedCount MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 1, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Command.Parameter[0].Value"), AttributeId = AttributeIds.Value }, //Next batch ID MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 2, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Command.Parameter[1].Value"), AttributeId = AttributeIds.Value }, //Next product ID MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 3, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Command.Parameter[2].Value"), AttributeId = AttributeIds.Value }, //Amount of product in next batch MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 4, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Status.Parameter[2].Value"), AttributeId = AttributeIds.Value }, //Humidity MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 5, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Status.Parameter[3].Value"), AttributeId = AttributeIds.Value }, //Temperature MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 6, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Status.Parameter[4].Value"), AttributeId = AttributeIds.Value }, //Vibration MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 7, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Status.MachSpeed"), AttributeId = AttributeIds.Value }, //MachineSpeed MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 8, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Status.StateCurrent"), AttributeId = AttributeIds.Value }, //state MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 9, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } }, new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("ns=6;s=::Program:Cube.Status.StateCurrent"), AttributeId = AttributeIds.Value }, //cmdCtrln MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 10, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } } #endregion }; var itemsRequest = new CreateMonitoredItemsRequest { SubscriptionId = id, ItemsToCreate = itemsToCreate, }; var itemsResponse = await channel.CreateMonitoredItemsAsync(itemsRequest); var subToken = channel.Where(pr => pr.SubscriptionId == id).Subscribe(pr => { // loop through all the data change notifications var dcns = pr.NotificationMessage.NotificationData.OfType <DataChangeNotification>(); foreach (var dcn in dcns) { foreach (var min in dcn.MonitoredItems) { switch (min.ClientHandle) { case 1: prodProc = (int)min.Value.Value; time = (DateTime)min.Value.ServerTimestamp; break; case 2: time = (DateTime)min.Value.ServerTimestamp; nextBatchID = (float)min.Value.Value; break; case 3: time = (DateTime)min.Value.ServerTimestamp; nextProductID = (float)min.Value.Value; break; case 4: time = (DateTime)min.Value.ServerTimestamp; nextProductAmount = (float)min.Value.Value; break; case 5: time = (DateTime)min.Value.ServerTimestamp; humidity = (float)min.Value.Value; break; case 6: time = (DateTime)min.Value.ServerTimestamp; temperature = (float)min.Value.Value; break; case 7: time = (DateTime)min.Value.ServerTimestamp; vibration = (float)min.Value.Value; break; case 8: time = (DateTime)min.Value.ServerTimestamp; machinespeed = (float)min.Value.Value; break; case 9: time = (DateTime)min.Value.ServerTimestamp; State = (int)min.Value.Value; break; case 10: cmdctrl = (int)min.Value.Value; time = (DateTime)min.Value.ServerTimestamp; break; } } } }); while (!token.IsCancellationRequested) { await Task.Delay(500); } } catch { } } catch (Exception ex) { } //try //{ // await Task.Delay(cycleTime, token); //} //catch //{ //} } } }
/// <summary> /// Starts monitoring the value of the currently selected item. /// </summary> public void CreateMonitoredItem(ReferenceDescription node) { ListOfMonitoredItemCreateRequest itemsToCreate = new ListOfMonitoredItemCreateRequest(); MonitoredItemCreateRequest itemToCreate = new MonitoredItemCreateRequest(); itemToCreate.ItemToMonitor = new ReadValueId(); itemToCreate.ItemToMonitor.NodeId = new NodeId(node.NodeId); itemToCreate.ItemToMonitor.AttributeId = Attributes.Value; itemToCreate.MonitoringMode = MonitoringMode.Reporting_2; itemToCreate.RequestedParameters = new MonitoringParameters(); itemToCreate.RequestedParameters.ClientHandle = ++m_monitoredItemCount; itemToCreate.RequestedParameters.SamplingInterval = 1000; itemToCreate.RequestedParameters.QueueSize = 0; itemToCreate.RequestedParameters.DiscardOldest = true; itemToCreate.RequestedParameters.Filter = new ExtensionObject(); itemsToCreate.Add(itemToCreate); ListOfMonitoredItemCreateResult results; ListOfDiagnosticInfo diagnosticInfos; m_client.CreateMonitoredItems( m_client.CreateRequestHeader(), m_subscriptionId, TimestampsToReturn.Both_2, itemsToCreate, out results, out diagnosticInfos); if (results != null) { // update the list view. MonitoredItemCreateResult result = results[0]; ListViewItem item = new ListViewItem(itemToCreate.RequestedParameters.ClientHandle.ToString()); item.SubItems.Add(new ListViewItem.ListViewSubItem()); item.SubItems[1].Text = node.DisplayName.Text; item.SubItems.Add(new ListViewItem.ListViewSubItem()); item.SubItems[2].Text = "<Unknown>"; item.SubItems.Add(new ListViewItem.ListViewSubItem()); item.SubItems[3].Text = String.Format("{0}", result.StatusCode); item.SubItems.Add(new ListViewItem.ListViewSubItem()); item.SubItems[4].Text = String.Format("{0:HH:mm:ss}", DateTime.Now); UpdatesLV.Items.Add(item); // save the monitored item. MonitoredItem monitoredItem = new MonitoredItem(); monitoredItem.MonitoredItemId = result.MonitoredItemId; monitoredItem.ItemToMonitor = itemToCreate.ItemToMonitor; monitoredItem.MonitoringMode = itemToCreate.MonitoringMode; monitoredItem.Parameters = itemToCreate.RequestedParameters; monitoredItem.Parameters.SamplingInterval = result.RevisedSamplingInterval; monitoredItem.Parameters.QueueSize = result.RevisedQueueSize; m_monitoredItems.Add(itemToCreate.RequestedParameters.ClientHandle, monitoredItem); item.Tag = monitoredItem; } }
/// <summary> /// Creates a set of monitored items. /// </summary> public MonitoredItem CreateMonitoredItem( OperationContext context, INodeManager nodeManager, object handle, uint subscriptionId, uint monitoredItemId, TimestampsToReturn timestampsToReturn, double publishingInterval, MonitoredItemCreateRequest itemToCreate, EventFilter filter) { lock (m_lock) { // calculate sampling interval. double samplingInterval = itemToCreate.RequestedParameters.SamplingInterval; if (samplingInterval < 0) { samplingInterval = publishingInterval; } // limit the queue size. uint queueSize = itemToCreate.RequestedParameters.QueueSize; if (queueSize > m_maxEventQueueSize) { queueSize = m_maxEventQueueSize; } // create the monitored item. MonitoredItem monitoredItem = new MonitoredItem( m_server, nodeManager, handle, subscriptionId, monitoredItemId, context.Session, itemToCreate.ItemToMonitor, context.DiagnosticsMask, timestampsToReturn, itemToCreate.MonitoringMode, itemToCreate.RequestedParameters.ClientHandle, filter, filter, null, samplingInterval, queueSize, itemToCreate.RequestedParameters.DiscardOldest, MinimumSamplingIntervals.Continuous); // save the monitored item. m_monitoredItems.Add(monitoredItemId, monitoredItem); return monitoredItem; } }
public MonitoredItem CreateMonitoredItem( OperationContext context, INodeManager nodeManager, object handle, uint subscriptionId, uint monitoredItemId, TimestampsToReturn timestampsToReturn, MonitoredItemCreateRequest itemToCreate, EventFilter filter) { return CreateMonitoredItem( context, nodeManager, handle, subscriptionId, monitoredItemId, timestampsToReturn, 0, itemToCreate, filter); }
/// <summary> /// Creates a new set of monitored items for a set of variables. /// </summary> /// <remarks> /// This method only handles data change subscriptions. Event subscriptions are created by the SDK. /// </remarks> protected override ServiceResult CreateMonitoredItem( ISystemContext context, NodeState source, uint subscriptionId, double publishingInterval, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoredItemCreateRequest itemToCreate, ref long globalIdCounter, out MonitoringFilterResult filterError, out IMonitoredItem monitoredItem) { filterError = null; monitoredItem = null; // use default behavoir for non-tag sources. if (!(source is MemoryTagState tag)) { return(base.CreateMonitoredItem( context, source, subscriptionId, publishingInterval, diagnosticsMasks, timestampsToReturn, itemToCreate, ref globalIdCounter, out filterError, out monitoredItem)); } // validate parameters. var parameters = itemToCreate.RequestedParameters; // no filters supported at this time. var filter = (MonitoringFilter)ExtensionObject.ToEncodeable(parameters.Filter); if (filter != null) { return(StatusCodes.BadFilterNotAllowed); } // index range not supported. if (itemToCreate.ItemToMonitor.ParsedIndexRange != NumericRange.Empty) { return(StatusCodes.BadIndexRangeInvalid); } // data encoding not supported. if (!QualifiedName.IsNull(itemToCreate.ItemToMonitor.DataEncoding)) { return(StatusCodes.BadDataEncodingInvalid); } // read initial value. var initialValue = new DataValue { Value = null, ServerTimestamp = DateTime.UtcNow, SourceTimestamp = DateTime.MinValue, StatusCode = StatusCodes.Good }; var error = source.ReadAttribute( context, itemToCreate.ItemToMonitor.AttributeId, itemToCreate.ItemToMonitor.ParsedIndexRange, itemToCreate.ItemToMonitor.DataEncoding, initialValue); if (ServiceResult.IsBad(error)) { return(error); } // get the monitored node for the containing buffer. if (!(tag.Parent is MemoryBufferState buffer)) { return(StatusCodes.BadInternalError); } // create a globally unique identifier. var monitoredItemId = Utils.IncrementIdentifier(ref globalIdCounter); // determine the sampling interval. var samplingInterval = itemToCreate.RequestedParameters.SamplingInterval; if (samplingInterval < 0) { samplingInterval = publishingInterval; } // create the item. var datachangeItem = buffer.CreateDataChangeItem( context as ServerSystemContext, tag, monitoredItemId, itemToCreate.ItemToMonitor, diagnosticsMasks, timestampsToReturn, itemToCreate.MonitoringMode, itemToCreate.RequestedParameters.ClientHandle, samplingInterval); /* * // create the item. * MemoryBufferMonitoredItem datachangeItem = buffer.CreateDataChangeItem( * context, * tag, * monitoredItemId, * itemToCreate.ItemToMonitor.AttributeId, * diagnosticsMasks, * timestampsToReturn, * itemToCreate.MonitoringMode, * itemToCreate.RequestedParameters.ClientHandle, * samplingInterval); */ // report the initial value. datachangeItem.QueueValue(initialValue, null); // update monitored item list. monitoredItem = datachangeItem; return(ServiceResult.Good); }
/// <summary> /// Creates a new set of monitored items for a set of variables. /// </summary> /// <remarks> /// This method only handles data change subscriptions. Event subscriptions are created by the SDK. /// </remarks> protected virtual ServiceResult CreateMonitoredItem( ISystemContext context, NodeState source, uint subscriptionId, double publishingInterval, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoredItemCreateRequest itemToCreate, ref long globalIdCounter, out MonitoringFilterResult filterError, out IMonitoredItem monitoredItem) { filterError = null; monitoredItem = null; ServiceResult error = null; // read initial value. DataValue initialValue = new DataValue(); initialValue.Value = null; initialValue.ServerTimestamp = DateTime.UtcNow; initialValue.SourceTimestamp = DateTime.MinValue; initialValue.StatusCode = StatusCodes.Good; error = source.ReadAttribute( context, itemToCreate.ItemToMonitor.AttributeId, itemToCreate.ItemToMonitor.ParsedIndexRange, itemToCreate.ItemToMonitor.DataEncoding, initialValue); if (ServiceResult.IsBad(error)) { return error; } // validate parameters. MonitoringParameters parameters = itemToCreate.RequestedParameters; // validate the data change filter. DataChangeFilter filter = null; Range range = null; if (!ExtensionObject.IsNull(parameters.Filter)) { error = ValidateDataChangeFilter( context, source, itemToCreate.ItemToMonitor.AttributeId, parameters.Filter, out filter, out range); if (ServiceResult.IsBad(error)) { return error; } } // create monitored node. MonitoredNode monitoredNode = source.Handle as MonitoredNode; if (monitoredNode == null) { source.Handle = monitoredNode = new MonitoredNode(m_server, this, source); } // create a globally unique identifier. uint monitoredItemId = Utils.IncrementIdentifier(ref globalIdCounter); // determine the sampling interval. double samplingInterval = itemToCreate.RequestedParameters.SamplingInterval; if (samplingInterval < 0) { samplingInterval = publishingInterval; } // check if the variable needs to be sampled. bool samplingRequired = false; if (itemToCreate.ItemToMonitor.AttributeId == Attributes.Value) { BaseVariableState variable = source as BaseVariableState; if (variable.MinimumSamplingInterval > 0) { samplingInterval = CalculateSamplingInterval(variable, samplingInterval); samplingRequired = true; } } // create the item. DataChangeMonitoredItem datachangeItem = monitoredNode.CreateDataChangeItem( context, monitoredItemId, itemToCreate.ItemToMonitor.AttributeId, itemToCreate.ItemToMonitor.ParsedIndexRange, itemToCreate.ItemToMonitor.DataEncoding, diagnosticsMasks, timestampsToReturn, itemToCreate.MonitoringMode, itemToCreate.RequestedParameters.ClientHandle, samplingInterval, itemToCreate.RequestedParameters.QueueSize, itemToCreate.RequestedParameters.DiscardOldest, filter, range, false); if (samplingRequired) { CreateSampledItem(samplingInterval, datachangeItem); } // report the initial value. datachangeItem.QueueValue(initialValue, null); // do any post processing. OnCreateMonitoredItem(context, itemToCreate, monitoredNode, datachangeItem); // update monitored item list. monitoredItem = datachangeItem; return ServiceResult.Good; }
private static async Task TestAsync() { var discoveryUrl = "opc.tcp://*****:*****@"%LOCALAPPDATA%\Workstation.ConsoleApp\pki")), userIdentity, remoteEndpoint)) { try { await session.OpenAsync(); } catch (ServiceResultException ex) { if ((uint)ex.HResult == StatusCodes.BadSecurityChecksFailed) { Console.WriteLine("Error connecting to endpoint. Did the server reject our certificate?"); } throw ex; } Console.WriteLine("Step 5 - 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 session.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, session.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 session.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, session.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 session.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 6 - Create a subscription."); var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = 1000, RequestedMaxKeepAliveCount = 10, RequestedLifetimeCount = 30, PublishingEnabled = true }; var subscriptionResponse = await session.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false); var id = subscriptionResponse.SubscriptionId; Console.WriteLine("Step 7 - 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 session.CreateMonitoredItemsAsync(itemsRequest).ConfigureAwait(false); Console.WriteLine("Step 8 - Publish the subscription."); var publishRequest = new PublishRequest { SubscriptionAcknowledgements = new SubscriptionAcknowledgement[0] }; Console.WriteLine("Press any key to delete the subscription..."); while (!Console.KeyAvailable) { var publishResponse = await session.PublishAsync(publishRequest).ConfigureAwait(false); // loop thru all the data change notifications var dcns = publishResponse.NotificationMessage.NotificationData.OfType <DataChangeNotification>(); foreach (var dcn in dcns) { foreach (var min in dcn.MonitoredItems) { Console.WriteLine($"clientHandle: {min.ClientHandle}; value: {min.Value}"); } } publishRequest = new PublishRequest { SubscriptionAcknowledgements = new[] { new SubscriptionAcknowledgement { SequenceNumber = publishResponse.NotificationMessage.SequenceNumber, SubscriptionId = publishResponse.SubscriptionId } } }; } Console.ReadKey(true); Console.WriteLine("Step 9 - Delete the subscription."); var request = new DeleteSubscriptionsRequest { SubscriptionIds = new uint[] { id } }; await session.DeleteSubscriptionsAsync(request).ConfigureAwait(false); Console.WriteLine("Press any key to close the session..."); Console.ReadKey(true); Console.WriteLine("Step 10 - Close the session."); await session.CloseAsync(); } }
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> /// Creates a new monitored item and calls StartMonitoring(). /// </summary> public virtual MonitoredItem CreateMonitoredItem( OperationContext context, uint subscriptionId, double publishingInterval, TimestampsToReturn timestampsToReturn, uint monitoredItemId, object managerHandle, MonitoredItemCreateRequest itemToCreate, Range range, double minimumSamplingInterval) { // use publishing interval as sampling interval. double samplingInterval = itemToCreate.RequestedParameters.SamplingInterval; if (samplingInterval < 0) { samplingInterval = publishingInterval; } // limit the sampling interval. if (minimumSamplingInterval > 0 && samplingInterval < minimumSamplingInterval) { samplingInterval = minimumSamplingInterval; } // calculate queue size. uint queueSize = itemToCreate.RequestedParameters.QueueSize; if (queueSize > m_maxQueueSize) { queueSize = m_maxQueueSize; } // get filter. MonitoringFilter filter = null; if (!ExtensionObject.IsNull(itemToCreate.RequestedParameters.Filter)) { filter = itemToCreate.RequestedParameters.Filter.Body as MonitoringFilter; } // update limits for event filters. if (filter is EventFilter) { if (queueSize == 0) { queueSize = Int32.MaxValue; } samplingInterval = 0; } // check if the queue size was not specified. if (queueSize == 0) { queueSize = 1; } // create monitored item. MonitoredItem monitoredItem = CreateMonitoredItem( m_server, m_nodeManager, managerHandle, subscriptionId, monitoredItemId, context.Session, itemToCreate.ItemToMonitor, context.DiagnosticsMask, timestampsToReturn, itemToCreate.MonitoringMode, itemToCreate.RequestedParameters.ClientHandle, filter, filter, range, samplingInterval, queueSize, itemToCreate.RequestedParameters.DiscardOldest, samplingInterval); // start sampling. StartMonitoring(context, monitoredItem); // return item. return(monitoredItem); }
private static async Task ConnectAndPublish(CancellationToken token = default) { var discoveryUrl = "opc.tcp://localhost:48010"; // UaCppServer - see http://www.unified-automation.com/ var appDescription = new ApplicationDescription() { ApplicationName = "MyHomework", ApplicationUri = $"urn:{System.Net.Dns.GetHostName()}:MyHomework", ApplicationType = ApplicationType.Client, }; var certificateStore = new DirectoryStore( Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Workstation.ConsoleApp", "pki")); while (!token.IsCancellationRequested) { var channel = new UaTcpSessionChannel( appDescription, certificateStore, new AnonymousIdentity(), discoveryUrl); try { await channel.OpenAsync(); var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = 1000, RequestedMaxKeepAliveCount = 10, RequestedLifetimeCount = 30, PublishingEnabled = true }; var subscriptionResponse = await channel.CreateSubscriptionAsync(subscriptionRequest); var id = subscriptionResponse.SubscriptionId; var itemsToCreate = new MonitoredItemCreateRequest[] { new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("i=2258"), AttributeId = AttributeIds.Value }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 12345, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } } }; var itemsRequest = new CreateMonitoredItemsRequest { SubscriptionId = id, ItemsToCreate = itemsToCreate, }; var itemsResponse = await channel.CreateMonitoredItemsAsync(itemsRequest); var subtoken = channel.Where(pr => pr.SubscriptionId == id).Subscribe( pr => { var dcns = pr.NotificationMessage.NotificationData.OfType <DataChangeNotification>(); foreach (var dcn in dcns) { foreach (var min in dcn.MonitoredItems) { Console.WriteLine($"sub: {pr.SubscriptionId}; handle: {min.ClientHandle}; value: {min.Value}"); } } }, // need to handle error when server closes ex => { }); try { Task.WaitAny(new Task[] { channel.Completion }, token); } catch (OperationCanceledException) { } var request = new DeleteSubscriptionsRequest { SubscriptionIds = new uint[] { id } }; await channel.DeleteSubscriptionsAsync(request); subtoken.Dispose(); await channel.CloseAsync(); } catch (Exception ex) { Console.WriteLine($"Error connecting and publishing. {ex.Message}"); await channel.AbortAsync(); try { await Task.Delay(5000, token); } catch (TaskCanceledException) { } } } }