/// <summary>
 /// Initializes a new instance of the <see cref="MonitoredItemAttribute"/> class.
 /// </summary>
 /// <param name="nodeId">the NodeId to monitor.</param>
 /// <param name="attributeId">the attribute to monitor.</param>
 /// <param name="indexRange">the range of array indexes to monitor.</param>
 /// <param name="samplingInterval">the sampling interval.</param>
 /// <param name="queueSize">the length of the queue used by the server to buffer values.</param>
 /// <param name="discardOldest">a value indicating whether to discard the oldest entries in the queue when it is full.</param>
 /// <param name="dataChangeTrigger">the properties that trigger a data change.</param>
 /// <param name="deadbandType">the type of deadband calculation.</param>
 /// <param name="deadbandValue">the deadband value.</param>
 public MonitoredItemAttribute(string nodeId = null, uint attributeId = AttributeIds.Value, string indexRange = null, int samplingInterval = -1, uint queueSize = 0, bool discardOldest = true, DataChangeTrigger dataChangeTrigger = DataChangeTrigger.StatusValue, DeadbandType deadbandType = DeadbandType.None, double deadbandValue = 0.0)
 {
     this.NodeId = nodeId;
     this.AttributeId = attributeId;
     this.IndexRange = indexRange;
     this.SamplingInterval = samplingInterval;
     this.QueueSize = queueSize;
     this.DiscardOldest = discardOldest;
     this.DataChangeTrigger = dataChangeTrigger;
     this.DeadbandType = deadbandType;
     this.DeadbandValue = deadbandValue;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="MonitoredItemAttribute"/> class.
 /// </summary>
 /// <param name="nodeId">the NodeId to monitor.</param>
 /// <param name="attributeId">the attribute to monitor.</param>
 /// <param name="indexRange">the range of array indexes to monitor.</param>
 /// <param name="samplingInterval">the sampling interval.</param>
 /// <param name="queueSize">the length of the queue used by the server to buffer values.</param>
 /// <param name="discardOldest">a value indicating whether to discard the oldest entries in the queue when it is full.</param>
 /// <param name="dataChangeTrigger">the properties that trigger a data change.</param>
 /// <param name="deadbandType">the type of deadband calculation.</param>
 /// <param name="deadbandValue">the deadband value.</param>
 public MonitoredItemAttribute(string nodeId, uint attributeId = AttributeIds.Value, string?indexRange = null, int samplingInterval = -1, uint queueSize = 0, bool discardOldest = true, DataChangeTrigger dataChangeTrigger = DataChangeTrigger.StatusValue, DeadbandType deadbandType = DeadbandType.None, double deadbandValue = 0.0)
 {
     NodeId            = nodeId;
     AttributeId       = attributeId;
     IndexRange        = indexRange;
     SamplingInterval  = samplingInterval;
     QueueSize         = queueSize;
     DiscardOldest     = discardOldest;
     DataChangeTrigger = dataChangeTrigger;
     DeadbandType      = deadbandType;
     DeadbandValue     = deadbandValue;
 }
Exemplo n.º 3
0
        private void DeadbandTypeCB_SelectedIndexChanged(object sender, EventArgs e)
        {
            DeadbandType deadbandType = (DeadbandType)DeadbandTypeCB.SelectedItem;

            DeadbandNC.Enabled = deadbandType != DeadbandType.None;

            if (deadbandType == DeadbandType.Percent)
            {
                DeadbandNC.Minimum = 0;
                DeadbandNC.Maximum = 100;
            }
            else
            {
                DeadbandNC.Minimum = Decimal.MinValue;
                DeadbandNC.Maximum = Decimal.MaxValue;
            }
        }
        /// <summary>
        /// Returns true if the deadband was exceeded.
        /// </summary>
        private static bool ExceedsDeadband(double value1, double value2, DeadbandType deadbandType, double deadband, double range)
        {
            double baseline = 1;

            if (deadbandType == DeadbandType.Percent)
            {
                baseline = range / 100;
            }

            if (baseline > 0)
            {
                if (Math.Abs((value1 - value2)/baseline) <= (double)deadband)
                {
                    return false;
                }
            }

            return true;
        }        
        /// <summary>
        /// Returns true if the deadband was exceeded.
        /// </summary>
        protected static bool ExceedsDeadband(object value1, object value2, DeadbandType deadbandType, double deadband, double range)
        {
            // cannot convert doubles safely to decimals.
            if (value1 is double)
            {
                return ExceedsDeadband((double)value1, (double)value2, deadbandType, deadband, range);
            }

            try
            {
                decimal decimal1 = Convert.ToDecimal(value1, CultureInfo.InvariantCulture);
                decimal decimal2 = Convert.ToDecimal(value2, CultureInfo.InvariantCulture);
                decimal baseline = 1;

                if (deadbandType == DeadbandType.Percent)
                {
                    baseline = ((decimal)range) / 100;
                }

                if (baseline > 0)
                {
                    if (Math.Abs((decimal1 - decimal2)/baseline) <= (decimal)deadband)
                    {
                        return false;
                    }
                }
            }
            catch
            {
                // treat all conversion errors as evidence that the deadband was exceeded.
            }
                
            return true;
        }
        /// <summary>
        /// Checks if the two values are equal.
        /// </summary>
        protected static bool Equals(object value1, object value2, DeadbandType deadbandType, double deadband, double range)
        {
            // check if reference to same object.
            if (Object.ReferenceEquals(value1, value2))
            {
                return true;
            }
            
            // check for invalid values.
            if (value1 == null || value2 == null)
            {
			    return value1 == value2;
            }
            
            // check for type change.
            if (value1.GetType() != value2.GetType())
            {
			    return false;
            }

            // check if values are equal.
            if (value1.Equals(value2))
            {
                return true;
            }

            // check for arrays.
            Array array1 = value1 as Array;
            Array array2 = value2 as Array;

            if (array1 == null || array2 == null)
            {

                XmlElement xmlElement1 = value1 as XmlElement;
                XmlElement xmlElement2 = value2 as XmlElement;

                if (xmlElement1 != null && xmlElement2 != null)
                {
                    return xmlElement1.OuterXml.Equals(xmlElement2.OuterXml);
                }

                // nothing more to do if no deadband.
                if (deadbandType == DeadbandType.None)
                {
			        return false;
                }

                // check deadband.
                return !ExceedsDeadband(value1, value2, deadbandType, deadband, range);
            }
            
            // compare lengths.
            if (array1.Length != array2.Length)
            {
			    return false;
            }

            // compare each element.
            bool isVariant = array1.GetType().GetElementType() == typeof(Variant);

            for (int ii = 0; ii < array1.Length; ii++)
            {
                object element1 = array1.GetValue(ii);
                object element2 = array2.GetValue(ii);

                if (isVariant)
                {
                    element1 = ((Variant)element1).Value;
                    element2 = ((Variant)element2).Value;
                }

                if (!Equals(element1, element2, deadbandType, deadband, range))
                {
                    return false;
                }
            }

            // must be equal.
            return true;
        }
        /// <summary>
        /// Prompts the user to edit the monitored item.
        /// </summary>
        public bool ShowDialog(Session session, MonitoredItem monitoredItem, bool isEvent)
        {
            if (!monitoredItem.Created)
            {
                NodeBTN.Session      = session;
                NodeBTN.SelectedNode = monitoredItem.StartNodeId;
            }

            // hide fields not used for events.
            NodeLB.Visible             = !monitoredItem.Created;
            NodeTB.Visible             = !monitoredItem.Created;
            NodeBTN.Visible            = !monitoredItem.Created;
            AttributeLB.Visible        = !isEvent && !monitoredItem.Created;
            AttributeCB.Visible        = !isEvent && !monitoredItem.Created;
            IndexRangeLB.Visible       = !isEvent && !monitoredItem.Created;
            IndexRangeTB.Visible       = !isEvent && !monitoredItem.Created;
            DataEncodingLB.Visible     = !isEvent && !monitoredItem.Created;
            DataEncodingCB.Visible     = !isEvent && !monitoredItem.Created;
            MonitoringModeLB.Visible   = !monitoredItem.Created;
            MonitoringModeCB.Visible   = !monitoredItem.Created;
            SamplingIntervalLB.Visible = true;
            SamplingIntervalUP.Visible = true;
            QueueSizeLB.Visible        = !isEvent;
            QueueSizeUP.Visible        = !isEvent;
            DiscardOldestLB.Visible    = true;
            DiscardOldestCK.Visible    = true;
            DeadbandTypeLB.Visible     = !isEvent;
            DeadbandTypeCB.Visible     = !isEvent;
            DeadbandValueLB.Visible    = !isEvent;
            DeadbandValueUP.Visible    = !isEvent;
            TriggerTypeLB.Visible      = !isEvent;
            TriggerTypeCB.Visible      = !isEvent;

            // fill in values.
            SamplingIntervalUP.Value = monitoredItem.SamplingInterval;
            DiscardOldestCK.Checked  = monitoredItem.DiscardOldest;

            if (!isEvent)
            {
                AttributeCB.SelectedIndex     = (int)(monitoredItem.AttributeId - 1);
                IndexRangeTB.Text             = monitoredItem.IndexRange;
                MonitoringModeCB.SelectedItem = monitoredItem.MonitoringMode;
                QueueSizeUP.Value             = monitoredItem.QueueSize;

                DataChangeFilter filter = monitoredItem.Filter as DataChangeFilter;

                if (filter != null)
                {
                    DeadbandTypeCB.SelectedItem = (DeadbandType)filter.DeadbandType;
                    DeadbandValueUP.Value       = (decimal)filter.DeadbandValue;
                    TriggerTypeCB.SelectedItem  = filter.Trigger;
                }

                if (!monitoredItem.Created)
                {
                    // fetch the available encodings for the first node in the list from the server.
                    IVariableBase variable = session.NodeCache.Find(monitoredItem.StartNodeId) as IVariableBase;

                    DataEncodingCB.Items.Add(new EncodingInfo());
                    DataEncodingCB.SelectedIndex = 0;

                    if (variable != null)
                    {
                        if (session.NodeCache.IsTypeOf(variable.DataType, Opc.Ua.DataTypeIds.Structure))
                        {
                            foreach (INode encoding in session.NodeCache.Find(variable.DataType, Opc.Ua.ReferenceTypeIds.HasEncoding, false, true))
                            {
                                DataEncodingCB.Items.Add(new EncodingInfo()
                                {
                                    EncodingName = encoding.BrowseName
                                });

                                if (monitoredItem.Encoding == encoding.BrowseName)
                                {
                                    DataEncodingCB.SelectedIndex = DataEncodingCB.Items.Count - 1;
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                AttributeCB.SelectedIndex = ((int)Attributes.EventNotifier - 1);
            }

            if (base.ShowDialog() != DialogResult.OK)
            {
                return(false);
            }

            // update monitored item.
            if (!monitoredItem.Created)
            {
                monitoredItem.StartNodeId    = NodeBTN.SelectedNode;
                monitoredItem.DisplayName    = session.NodeCache.GetDisplayText(monitoredItem.StartNodeId);
                monitoredItem.RelativePath   = null;
                monitoredItem.AttributeId    = (uint)(AttributeCB.SelectedIndex + 1);
                monitoredItem.MonitoringMode = (MonitoringMode)MonitoringModeCB.SelectedItem;
            }

            monitoredItem.SamplingInterval = (int)SamplingIntervalUP.Value;
            monitoredItem.DiscardOldest    = DiscardOldestCK.Checked;

            if (!isEvent)
            {
                if (!monitoredItem.Created)
                {
                    monitoredItem.IndexRange = IndexRangeTB.Text.Trim();
                    monitoredItem.Encoding   = ((EncodingInfo)DataEncodingCB.SelectedItem).EncodingName;
                }

                monitoredItem.QueueSize = (uint)QueueSizeUP.Value;

                DataChangeTrigger trigger      = (DataChangeTrigger)TriggerTypeCB.SelectedItem;
                DeadbandType      deadbandType = (DeadbandType)DeadbandTypeCB.SelectedItem;

                if (monitoredItem.Filter != null || deadbandType != DeadbandType.None || trigger != DataChangeTrigger.StatusValue)
                {
                    DataChangeFilter filter = new DataChangeFilter();
                    filter.DeadbandType  = (uint)deadbandType;
                    filter.DeadbandValue = (double)DeadbandValueUP.Value;
                    filter.Trigger       = trigger;
                    monitoredItem.Filter = filter;
                }
            }
            else
            {
                if (!monitoredItem.Created)
                {
                    monitoredItem.IndexRange = null;
                    monitoredItem.Encoding   = null;
                }

                monitoredItem.QueueSize = 0;
                monitoredItem.Filter    = new EventFilter();
            }

            return(true);
        }