Exemplo n.º 1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SubscriptionBase"/> class.
        /// </summary>
        public SubscriptionBase()
        {
            this.application = UaApplication.Current;
            this.application?.Completion.ContinueWith(t => this.stateMachineCts?.Cancel());
            this.logger           = this.application?.LoggerFactory?.CreateLogger(this.GetType());
            this.errors           = new ErrorsContainer <string>(p => this.ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(p)));
            this.progress         = new Progress <CommunicationState>(s => this.State = s);
            this.propertyChanged += this.OnPropertyChanged;
            this.whenSubscribed   = new TaskCompletionSource <bool>();
            this.whenUnsubscribed = new TaskCompletionSource <bool>();
            this.whenUnsubscribed.TrySetResult(true);

            // register the action to be run on the ui thread, if there is one.
            if (SynchronizationContext.Current != null)
            {
                this.actionBlock = new ActionBlock <PublishResponse>(pr => this.OnPublishResponse(pr), new ExecutionDataflowBlockOptions {
                    SingleProducerConstrained = true, TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
                });
            }
            else
            {
                this.actionBlock = new ActionBlock <PublishResponse>(pr => this.OnPublishResponse(pr), new ExecutionDataflowBlockOptions {
                    SingleProducerConstrained = true
                });
            }

            // read [Subscription] attribute.
            var typeInfo = this.GetType().GetTypeInfo();
            var sa       = typeInfo.GetCustomAttribute <SubscriptionAttribute>();

            if (sa != null)
            {
                this.endpointUrl        = sa.EndpointUrl;
                this.publishingInterval = sa.PublishingInterval;
                this.keepAliveCount     = sa.KeepAliveCount;
                this.lifetimeCount      = sa.LifetimeCount;
            }

            // read [MonitoredItem] attributes.
            foreach (var propertyInfo in typeInfo.DeclaredProperties)
            {
                var mia = propertyInfo.GetCustomAttribute <MonitoredItemAttribute>();
                if (mia == null || string.IsNullOrEmpty(mia.NodeId))
                {
                    continue;
                }

                MonitoringFilter filter = null;
                if (mia.AttributeId == AttributeIds.Value && (mia.DataChangeTrigger != DataChangeTrigger.StatusValue || mia.DeadbandType != DeadbandType.None))
                {
                    filter = new DataChangeFilter()
                    {
                        Trigger = mia.DataChangeTrigger, DeadbandType = (uint)mia.DeadbandType, DeadbandValue = mia.DeadbandValue
                    };
                }

                var propType = propertyInfo.PropertyType;
                if (propType == typeof(DataValue))
                {
                    this.monitoredItems.Add(new DataValueMonitoredItem(
                                                target: this,
                                                property: propertyInfo,
                                                nodeId: NodeId.Parse(mia.NodeId),
                                                indexRange: mia.IndexRange,
                                                attributeId: mia.AttributeId,
                                                samplingInterval: mia.SamplingInterval,
                                                filter: filter,
                                                queueSize: mia.QueueSize,
                                                discardOldest: mia.DiscardOldest));
                    continue;
                }

                if (propType == typeof(BaseEvent) || propType.GetTypeInfo().IsSubclassOf(typeof(BaseEvent)))
                {
                    this.monitoredItems.Add(new EventMonitoredItem(
                                                target: this,
                                                property: propertyInfo,
                                                nodeId: NodeId.Parse(mia.NodeId),
                                                indexRange: mia.IndexRange,
                                                attributeId: mia.AttributeId,
                                                samplingInterval: mia.SamplingInterval,
                                                filter: new EventFilter()
                    {
                        SelectClauses = EventHelper.GetSelectClauses(propType)
                    },
                                                queueSize: mia.QueueSize,
                                                discardOldest: mia.DiscardOldest));
                    continue;
                }

                if (propType == typeof(ObservableQueue <DataValue>))
                {
                    this.monitoredItems.Add(new DataValueQueueMonitoredItem(
                                                target: this,
                                                property: propertyInfo,
                                                nodeId: NodeId.Parse(mia.NodeId),
                                                indexRange: mia.IndexRange,
                                                attributeId: mia.AttributeId,
                                                samplingInterval: mia.SamplingInterval,
                                                filter: filter,
                                                queueSize: mia.QueueSize,
                                                discardOldest: mia.DiscardOldest));
                    continue;
                }

                if (propType.IsConstructedGenericType && propType.GetGenericTypeDefinition() == typeof(ObservableQueue <>))
                {
                    var elemType = propType.GenericTypeArguments[0];
                    if (elemType == typeof(BaseEvent) || elemType.GetTypeInfo().IsSubclassOf(typeof(BaseEvent)))
                    {
                        this.monitoredItems.Add((MonitoredItemBase)Activator.CreateInstance(
                                                    typeof(EventQueueMonitoredItem <>).MakeGenericType(elemType),
                                                    this,
                                                    propertyInfo,
                                                    NodeId.Parse(mia.NodeId),
                                                    mia.AttributeId,
                                                    mia.IndexRange,
                                                    MonitoringMode.Reporting,
                                                    mia.SamplingInterval,
                                                    new EventFilter()
                        {
                            SelectClauses = EventHelper.GetSelectClauses(elemType)
                        },
                                                    mia.QueueSize,
                                                    mia.DiscardOldest));
                        continue;
                    }
                }

                this.monitoredItems.Add(new ValueMonitoredItem(
                                            target: this,
                                            property: propertyInfo,
                                            nodeId: NodeId.Parse(mia.NodeId),
                                            indexRange: mia.IndexRange,
                                            attributeId: mia.AttributeId,
                                            samplingInterval: mia.SamplingInterval,
                                            filter: filter,
                                            queueSize: mia.QueueSize,
                                            discardOldest: mia.DiscardOldest));
            }

            this.stateMachineCts  = new CancellationTokenSource();
            this.stateMachineTask = Task.Run(() => this.StateMachineAsync(this.stateMachineCts.Token));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MonitoredItemCollection"/> class.
        /// Attributes found in the given subscription are added to the collection.
        /// </summary>
        /// <param name="subscription">the instance that will be inspected for [MonitoredItem] attributes.</param>
        public MonitoredItemCollection(ISubscription subscription)
        {
            var typeInfo = subscription.GetType().GetTypeInfo();

            foreach (var propertyInfo in typeInfo.DeclaredProperties)
            {
                var itemAttribute = propertyInfo.GetCustomAttribute <MonitoredItemAttribute>();
                if (itemAttribute == null || string.IsNullOrEmpty(itemAttribute.NodeId))
                {
                    continue;
                }

                MonitoringFilter filter = null;
                if (itemAttribute.AttributeId == AttributeIds.Value && (itemAttribute.DataChangeTrigger != DataChangeTrigger.StatusValue || itemAttribute.DeadbandType != DeadbandType.None))
                {
                    filter = new DataChangeFilter()
                    {
                        Trigger = itemAttribute.DataChangeTrigger, DeadbandType = (uint)itemAttribute.DeadbandType, DeadbandValue = itemAttribute.DeadbandValue
                    };
                }

                var propType = propertyInfo.PropertyType;
                if (propType == typeof(DataValue))
                {
                    this.Add(new DataValueMonitoredItem(
                                 target: subscription,
                                 property: propertyInfo,
                                 nodeId: NodeId.Parse(itemAttribute.NodeId),
                                 indexRange: itemAttribute.IndexRange,
                                 attributeId: itemAttribute.AttributeId,
                                 samplingInterval: itemAttribute.SamplingInterval,
                                 filter: filter,
                                 queueSize: itemAttribute.QueueSize,
                                 discardOldest: itemAttribute.DiscardOldest));
                    continue;
                }

                if (propType == typeof(ObservableQueue <DataValue>))
                {
                    this.Add(new DataValueQueueMonitoredItem(
                                 target: subscription,
                                 property: propertyInfo,
                                 nodeId: NodeId.Parse(itemAttribute.NodeId),
                                 indexRange: itemAttribute.IndexRange,
                                 attributeId: itemAttribute.AttributeId,
                                 samplingInterval: itemAttribute.SamplingInterval,
                                 filter: filter,
                                 queueSize: itemAttribute.QueueSize,
                                 discardOldest: itemAttribute.DiscardOldest));
                    continue;
                }

                if (propType == typeof(BaseEvent) || propType.GetTypeInfo().IsSubclassOf(typeof(BaseEvent)))
                {
                    this.Add(new EventMonitoredItem(
                                 target: subscription,
                                 property: propertyInfo,
                                 nodeId: NodeId.Parse(itemAttribute.NodeId),
                                 indexRange: itemAttribute.IndexRange,
                                 attributeId: itemAttribute.AttributeId,
                                 samplingInterval: itemAttribute.SamplingInterval,
                                 filter: new EventFilter()
                    {
                        SelectClauses = EventHelper.GetSelectClauses(propType)
                    },
                                 queueSize: itemAttribute.QueueSize,
                                 discardOldest: itemAttribute.DiscardOldest));
                    continue;
                }

                if (propType.IsConstructedGenericType && propType.GetGenericTypeDefinition() == typeof(ObservableQueue <>))
                {
                    var elemType = propType.GenericTypeArguments[0];
                    if (elemType == typeof(BaseEvent) || elemType.GetTypeInfo().IsSubclassOf(typeof(BaseEvent)))
                    {
                        this.Add((MonitoredItemBase)Activator.CreateInstance(
                                     typeof(EventQueueMonitoredItem <>).MakeGenericType(elemType),
                                     subscription,
                                     propertyInfo,
                                     NodeId.Parse(itemAttribute.NodeId),
                                     itemAttribute.AttributeId,
                                     itemAttribute.IndexRange,
                                     MonitoringMode.Reporting,
                                     itemAttribute.SamplingInterval,
                                     new EventFilter()
                        {
                            SelectClauses = EventHelper.GetSelectClauses(elemType)
                        },
                                     itemAttribute.QueueSize,
                                     itemAttribute.DiscardOldest));
                        continue;
                    }
                }

                this.Add(new ValueMonitoredItem(
                             target: subscription,
                             property: propertyInfo,
                             nodeId: NodeId.Parse(itemAttribute.NodeId),
                             indexRange: itemAttribute.IndexRange,
                             attributeId: itemAttribute.AttributeId,
                             samplingInterval: itemAttribute.SamplingInterval,
                             filter: filter,
                             queueSize: itemAttribute.QueueSize,
                             discardOldest: itemAttribute.DiscardOldest));
            }
        }