Ejemplo n.º 1
0
        /// <summary>
        /// Converts the value to a human readable string.
        /// </summary>
        /// <returns>A string.</returns>
        public override string ToString()
        {
            StringBuilder buffer = new StringBuilder();

            buffer.Append(StatusCodes.GetDefaultMessage(StatusCode));

            if (!string.IsNullOrEmpty(SymbolicId))
            {
                if (!string.IsNullOrEmpty(NamespaceUri))
                {
                    buffer.AppendFormat(" ({0}:{1})", NamespaceUri, SymbolicId);
                }
                else if (SymbolicId != buffer.ToString())
                {
                    buffer.AppendFormat(" ({0})", SymbolicId);
                }
            }

            if (!string.IsNullOrEmpty(LocalizedText))
            {
                buffer.AppendFormat(" '{0}'", LocalizedText);
            }

            if ((0x0000FFFF & StatusCode) != 0)
            {
                buffer.AppendFormat(" [{0:X4}]", 0x0000FFFF & StatusCode);
            }

            return(buffer.ToString());
        }
Ejemplo n.º 2
0
 public virtual void OnWriteResult(StatusCode result)
 {
     this.StatusCode = result;
     if (StatusCode.IsBad(result))
     {
         Trace.TraceError($"Error writing value for {this.NodeId}. {StatusCodes.GetDefaultMessage(result)}");
     }
 }
Ejemplo n.º 3
0
 public virtual void OnCreateResult(MonitoredItemCreateResult result)
 {
     this.ServerId   = result.MonitoredItemId;
     this.StatusCode = result.StatusCode;
     if (StatusCode.IsBad(result.StatusCode))
     {
         Trace.TraceError($"Error creating MonitoredItem for {this.NodeId}. {StatusCodes.GetDefaultMessage(result.StatusCode)}");
     }
 }
Ejemplo n.º 4
0
        private async void OpcTag_ValueChanged(object sender, PropertyChangedEventArgs e)
        {
            if (isPublishing || string.IsNullOrEmpty(e.PropertyName))
            {
                return;
            }
            if (monitoredItems.TryGetValueByName(e.PropertyName, out MonitoredItemBase item))
            {
                if (item.TryGetValue(out DataValue value))
                {
                    StatusCode statusCode;
                    var        writeRequest = new WriteRequest
                    {
                        NodesToWrite = new[] { new WriteValue {
                                                   NodeId = item.NodeId, AttributeId = item.AttributeId, IndexRange = item.IndexRange, Value = value
                                               } }
                    };
                    try
                    {
                        var writeResponse = await opcConnection.Channel.WriteAsync(writeRequest).ConfigureAwait(false);

                        statusCode = writeResponse.Results[0];
                    }
                    catch (ServiceResultException ex)
                    {
                        statusCode = ex.StatusCode;
                    }
                    catch (Exception)
                    {
                        statusCode = StatusCodes.BadServerNotConnected;
                    }

                    item.OnWriteResult(statusCode);
                    if (StatusCode.IsBad(statusCode))
                    {
                        logger?.LogError($"Error writing value for {item.NodeId}.  {StatusCodes.GetDefaultMessage(statusCode)}");
                    }
                }
            }
        }
        private void SetDataErrorInfo(StatusCode statusCode)
        {
            if (this.statusCode == statusCode)
            {
                return;
            }

            this.statusCode = statusCode;
            var targetAsDataErrorInfo = Target as ISetDataErrorInfo;

            if (targetAsDataErrorInfo != null)
            {
                if (!StatusCode.IsGood(statusCode))
                {
                    targetAsDataErrorInfo.SetErrors(Property.Name, new string[] { StatusCodes.GetDefaultMessage(statusCode) });
                }
                else
                {
                    targetAsDataErrorInfo.SetErrors(Property.Name, null);
                }
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// The state machine manages the state of the subscription.
        /// </summary>
        /// <param name="token">A cancellation token.</param>
        /// <returns>A task.</returns>
        private async Task StateMachineAsync(CancellationToken token = default(CancellationToken))
        {
            while (!token.IsCancellationRequested)
            {
                await this.whenSubscribed.Task;

                this.progress.Report(CommunicationState.Opening);

                try
                {
                    // get a channel.
                    this.innerChannel = await this.application.GetChannelAsync(this.endpointUrl, token);

                    try
                    {
                        // create the subscription.
                        var subscriptionRequest = new CreateSubscriptionRequest
                        {
                            RequestedPublishingInterval = this.publishingInterval,
                            RequestedMaxKeepAliveCount  = this.keepAliveCount,
                            RequestedLifetimeCount      = Math.Max(this.lifetimeCount, 3 * this.keepAliveCount),
                            PublishingEnabled           = true
                        };
                        var subscriptionResponse = await this.innerChannel.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(true);

                        // link up the dataflow blocks
                        var id        = this.subscriptionId = subscriptionResponse.SubscriptionId;
                        var linkToken = this.innerChannel.LinkTo(this.actionBlock, pr => pr.SubscriptionId == id);

                        try
                        {
                            // create the monitored items.
                            var items = this.monitoredItems.ToList();
                            if (items.Count > 0)
                            {
                                var requests = items.Select(m => new MonitoredItemCreateRequest {
                                    ItemToMonitor = new ReadValueId {
                                        NodeId = m.NodeId, AttributeId = m.AttributeId, IndexRange = m.IndexRange
                                    }, MonitoringMode = m.MonitoringMode, RequestedParameters = new MonitoringParameters {
                                        ClientHandle = m.ClientId, DiscardOldest = m.DiscardOldest, QueueSize = m.QueueSize, SamplingInterval = m.SamplingInterval, Filter = m.Filter
                                    }
                                }).ToArray();
                                var itemsRequest = new CreateMonitoredItemsRequest
                                {
                                    SubscriptionId = id,
                                    ItemsToCreate  = requests,
                                };
                                var itemsResponse = await this.innerChannel.CreateMonitoredItemsAsync(itemsRequest);

                                for (int i = 0; i < itemsResponse.Results.Length; i++)
                                {
                                    var item   = items[i];
                                    var result = itemsResponse.Results[i];
                                    item.OnCreateResult(result);
                                    if (StatusCode.IsBad(result.StatusCode))
                                    {
                                        this.logger?.LogError($"Error creating MonitoredItem for {item.NodeId}. {StatusCodes.GetDefaultMessage(result.StatusCode)}");
                                    }
                                }
                            }

                            this.progress.Report(CommunicationState.Opened);

                            // wait here until channel is closing, unsubscribed or token cancelled.
                            try
                            {
                                await Task.WhenAny(
                                    this.WhenChannelClosingAsync(this.innerChannel, token),
                                    this.whenUnsubscribed.Task);
                            }
                            catch
                            {
                            }
                            finally
                            {
                                this.progress.Report(CommunicationState.Closing);
                            }
                        }
                        catch (Exception ex)
                        {
                            this.logger?.LogError($"Error creating MonitoredItems. {ex.Message}");
                            this.progress.Report(CommunicationState.Faulted);
                        }
                        finally
                        {
                            linkToken.Dispose();
                        }

                        if (this.innerChannel.State == CommunicationState.Opened)
                        {
                            try
                            {
                                // delete the subscription.
                                var deleteRequest = new DeleteSubscriptionsRequest
                                {
                                    SubscriptionIds = new uint[] { id }
                                };
                                await this.innerChannel.DeleteSubscriptionsAsync(deleteRequest);
                            }
                            catch (Exception ex)
                            {
                                this.logger?.LogError($"Error deleting subscription. {ex.Message}");
                                await Task.Delay(2000);
                            }
                        }

                        this.progress.Report(CommunicationState.Closed);
                    }
                    catch (Exception ex)
                    {
                        this.logger?.LogError($"Error creating subscription. {ex.Message}");
                        this.progress.Report(CommunicationState.Faulted);
                        await Task.Delay(2000);
                    }
                }
                catch (Exception ex)
                {
                    this.logger?.LogTrace($"Error getting channel. {ex.Message}");
                    this.progress.Report(CommunicationState.Faulted);
                    await Task.Delay(2000);
                }
            }
        }
 public ServiceResultException(StatusCode statusCode)
     : base(StatusCodes.GetDefaultMessage(statusCode))
 {
     this.HResult = unchecked ((int)(uint)statusCode);
 }
Ejemplo n.º 8
0
        /// <summary>
        /// Handles PropertyChanged event. If the property is associated with a MonitoredItem, writes the property value to the node of the server.
        /// </summary>
        /// <param name="sender">the sender.</param>
        /// <param name="e">the event.</param>
        private async void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (this.isPublishing || string.IsNullOrEmpty(e.PropertyName))
            {
                return;
            }

            if (this.monitoredItems.TryGetValueByName(e.PropertyName, out var item))
            {
                if (item.TryGetValue(out var value))
                {
                    StatusCode statusCode;
                    try
                    {
                        var writeRequest = new WriteRequest
                        {
                            NodesToWrite = new[] { new WriteValue {
                                                       NodeId = ExpandedNodeId.ToNodeId(item.NodeId, this.InnerChannel.NamespaceUris), AttributeId = item.AttributeId, IndexRange = item.IndexRange, Value = value
                                                   } }
                        };
                        var writeResponse = await this.InnerChannel.WriteAsync(writeRequest).ConfigureAwait(false);

                        statusCode = writeResponse?.Results?[0] ?? StatusCodes.BadDataEncodingInvalid;
                    }
                    catch (ServiceResultException ex)
                    {
                        statusCode = ex.StatusCode;
                    }
                    catch (Exception)
                    {
                        statusCode = StatusCodes.BadServerNotConnected;
                    }

                    item.OnWriteResult(statusCode);
                    if (StatusCode.IsBad(statusCode))
                    {
                        this.logger?.LogError($"Error writing value for {item.NodeId}. {StatusCodes.GetDefaultMessage(statusCode)}");
                    }
                }
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Creates the subscriptions on the server.
        /// </summary>
        /// <param name="token">A cancellation token. </param>
        /// <returns>A task.</returns>
        private async Task AutoCreateSubscriptionsAsync(CancellationToken token = default(CancellationToken))
        {
            var tcs = new TaskCompletionSource <bool>();
            NotifyCollectionChangedEventHandler handler = async(o, e) =>
            {
                if (e.Action == NotifyCollectionChangedAction.Add)
                {
                    foreach (var subscription in e.NewItems.OfType <Subscription>())
                    {
                        var target = subscription.Target;
                        if (target == null)
                        {
                            continue;
                        }

                        try
                        {
                            // create the subscription.
                            var subscriptionRequest = new CreateSubscriptionRequest
                            {
                                RequestedPublishingInterval = subscription.PublishingInterval,
                                RequestedMaxKeepAliveCount  = subscription.KeepAliveCount,
                                RequestedLifetimeCount      = Math.Max(subscription.LifetimeCount, 3 * subscription.KeepAliveCount),
                                PublishingEnabled           = subscription.PublishingEnabled
                            };
                            var subscriptionResponse = await this.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false);

                            var id = subscription.SubscriptionId = subscriptionResponse.SubscriptionId;

                            // add the items.
                            if (subscription.MonitoredItems.Count > 0)
                            {
                                var items    = subscription.MonitoredItems.ToList();
                                var requests = items.Select(m => new MonitoredItemCreateRequest {
                                    ItemToMonitor = new ReadValueId {
                                        NodeId = m.NodeId, AttributeId = m.AttributeId, IndexRange = m.IndexRange
                                    }, MonitoringMode = m.MonitoringMode, RequestedParameters = new MonitoringParameters {
                                        ClientHandle = m.ClientId, DiscardOldest = m.DiscardOldest, QueueSize = m.QueueSize, SamplingInterval = m.SamplingInterval, Filter = m.Filter
                                    }
                                }).ToArray();
                                var itemsRequest = new CreateMonitoredItemsRequest
                                {
                                    SubscriptionId = id,
                                    ItemsToCreate  = requests,
                                };
                                var itemsResponse = await this.CreateMonitoredItemsAsync(itemsRequest).ConfigureAwait(false);

                                for (int i = 0; i < itemsResponse.Results.Length; i++)
                                {
                                    var item   = items[i];
                                    var result = itemsResponse.Results[i];
                                    item.OnCreateResult(target, result);
                                    if (StatusCode.IsBad(result.StatusCode))
                                    {
                                        this.Logger?.LogError($"Error creating MonitoredItem for {item.NodeId}. {StatusCodes.GetDefaultMessage(result.StatusCode)}");
                                    }
                                }
                            }
                        }
                        catch (ServiceResultException ex)
                        {
                            this.Logger?.LogError($"Error creating subscription. {ex.Message}");
                            this.innerChannel.Fault(ex);
                        }
                    }
                }
                else if (e.Action == NotifyCollectionChangedAction.Remove)
                {
                    try
                    {
                        // delete the subscriptions.
                        var request = new DeleteSubscriptionsRequest
                        {
                            SubscriptionIds = e.OldItems.OfType <Subscription>().Select(s => s.SubscriptionId).ToArray()
                        };
                        await this.DeleteSubscriptionsAsync(request).ConfigureAwait(false);
                    }
                    catch (ServiceResultException ex)
                    {
                        this.Logger?.LogError($"Error deleting subscriptions. {ex.Message}");
                    }
                }
            };

            using (token.Register(state => ((TaskCompletionSource <bool>)state).TrySetResult(true), tcs, false))
            {
                try
                {
                    handler.Invoke(this.subscriptions, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, this.subscriptions.ToList()));
                    this.subscriptions.CollectionChanged += handler;
                    await tcs.Task;
                }
                finally
                {
                    this.subscriptions.CollectionChanged -= handler;
                    foreach (var subscription in this.subscriptions)
                    {
                        subscription.SubscriptionId = 0;
                    }
                }
            }
        }
    private async Task <bool> TryWriteAsync(WriteRequest request)
    {
        try
        {
            var response = await this.Session.WriteAsync(request);

            for (int i = 0; i < response.Results.Length; i++)
            {
                if (StatusCode.IsBad(response.Results[i]))
                {
                    Debug.WriteLine($"Error writing output '{request.NodesToWrite[i].NodeId}' {request.NodesToWrite[i].Value.GetValue()}: {StatusCodes.GetDefaultMessage(response.Results[i])}");
                    return(false);
                }
            }
            return(true);
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"Error writing outputs : {ex.Message}");
            return(false);
        }
    }
Ejemplo n.º 11
0
        /// <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);
                }
            }
        }
Ejemplo n.º 12
0
        private void SetDataErrorInfo(object target, StatusCode statusCode)
        {
            var targetAsDataErrorInfo = target as ISetDataErrorInfo;

            if (targetAsDataErrorInfo != null)
            {
                if (!StatusCode.IsGood(statusCode))
                {
                    targetAsDataErrorInfo.SetErrors(this.Property.Name, new string[] { StatusCodes.GetDefaultMessage(statusCode) });
                }
                else
                {
                    targetAsDataErrorInfo.SetErrors(this.Property.Name, null);
                }
            }
        }