public void AddBacnetObject(BaCSharpObject newObj)
        {
            BacnetValue v = new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_DEVICE_OBJECT_REFERENCE, new BacnetDeviceObjectReference(newObj.PROP_OBJECT_IDENTIFIER));

            m_PROP_SUBORDINATE_LIST.Add(v);
            // Each object provided by the server must be added one by one to the DeviceObject
            Mydevice.AddBacnetObject(newObj);
        }
        // Copy the Present value into each reference properties value
        protected virtual void DoDispatchValue()
        {
            if ((m_PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES.references == null) || (Mydevice == null))
            {
                return;
            }

            foreach (object obj in m_PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES.references)
            {
                BacnetDeviceObjectPropertyReference reference = (BacnetDeviceObjectPropertyReference)obj;

                // reference.deviceIndentifier.type is not set to OBJECT_DEVICE for local object reference
                if (reference.deviceIndentifier.type != BacnetObjectTypes.OBJECT_DEVICE) // local object
                {
                    BaCSharpObject bcs = Mydevice.FindBacnetObject(reference.objectIdentifier);
                    if (bcs != null)
                    {
                        BacnetPropertyValue value = new BacnetPropertyValue();

                        if (m_PROP_PRIORITY == 0)
                        {
                            value.priority = (byte)16;
                        }
                        else
                        {
                            value.priority = (byte)m_PROP_PRIORITY;
                        }

                        value.property = new BacnetPropertyReference((uint)reference.propertyIdentifier, reference.arrayIndex);

                        value.value = new BacnetValue[] { new BacnetValue(m_PROP_PRESENT_VALUE) };

                        bcs.WritePropertyValue(value, false);
                    }
                }
                else
                {
                    KeyValuePair <BacnetClient, BacnetAddress>?recipient = null;

                    try
                    {
                        // SuroundingDevices is updated with Iam messages
                        recipient = Mydevice.SuroundingDevices[reference.deviceIndentifier.instance];
                    }
                    catch { }
                    if (recipient == null)
                    {
                        return;
                    }

                    BacnetValue[] value = new BacnetValue[] { new BacnetValue(m_PROP_PRESENT_VALUE) };
                    uint          wp    = m_PROP_PRIORITY;
                    System.Threading.ThreadPool.QueueUserWorkItem((o) =>
                    {
                        recipient.Value.Key.WritePriority = wp;
                        recipient.Value.Key.BeginWritePropertyRequest(recipient.Value.Value, reference.objectIdentifier, (BacnetPropertyIds)reference.propertyIdentifier, value, false);
                    }
                                                                  , null);
                }
            }
        }
        private void IntrinsicReportingManagement()
        {
            if (Mydevice == null)
            {
                return;
            }

            if (m_PROP_LIMIT_ENABLE.value[0] == 0)
            {
                Last_PRESENT_VALUE = m_PROP_PRESENT_VALUE;
                return;
            }

            // T type must be convertible to double of course
            double pv = Convert.ToDouble(m_PROP_PRESENT_VALUE);
            double hl = Convert.ToDouble(m_PROP_HIGH_LIMIT);
            double ll = Convert.ToDouble(m_PROP_LOW_LIMIT);
            double db = Convert.ToDouble(m_PROP_DEADBAND);

            bool LimitEnabledHigh = (m_PROP_LIMIT_ENABLE.value[0] & (uint)BacnetEventNotificationData.BacnetLimitEnable.EVENT_HIGH_LIMIT_ENABLE) != 0;
            bool LimitEnabledLow  = (m_PROP_LIMIT_ENABLE.value[0] & (uint)BacnetEventNotificationData.BacnetLimitEnable.EVENT_LOW_LIMIT_ENABLE) != 0;

            bool EventToOffNormal = (m_PROP_EVENT_ENABLE.value[0] & (uint)BacnetEventNotificationData.BacnetEventEnable.EVENT_ENABLE_TO_OFFNORMAL) != 0;
            bool EventToNormal    = (m_PROP_EVENT_ENABLE.value[0] & (uint)BacnetEventNotificationData.BacnetEventEnable.EVENT_ENABLE_TO_NORMAL) != 0;

            bool NotifyState = false;

            uint fromState = m_PROP_EVENT_STATE;
            int  toState   = -1;

            switch (fromState)
            {
            case (uint)BacnetEventNotificationData.BacnetEventStates.EVENT_STATE_NORMAL:
                /*  If LimitHigh flag is enabled and Present_Value exceed the High_Limit and Event to Offnormal is enabled then
                 * the notification must be done */
                if ((pv > hl) && LimitEnabledHigh)
                {
                    toState     = (int)BacnetEventNotificationData.BacnetEventStates.EVENT_STATE_HIGH_LIMIT;
                    NotifyState = EventToOffNormal;
                }

                /* If LowLimit flag is enabled and Present_Value exceed the Low_Limit and Event to Offnormal is enabled then
                 * the notification must be done */
                if ((pv < ll) & LimitEnabledLow)
                {
                    toState     = (int)BacnetEventNotificationData.BacnetEventStates.EVENT_STATE_LOW_LIMIT;
                    NotifyState = EventToOffNormal;
                }
                break;

            case (uint)BacnetEventNotificationData.BacnetEventStates.EVENT_STATE_HIGH_LIMIT:
                /* Present_Value fall below the High_Limit - Deadband ? */
                if (pv < (hl - db))
                {
                    toState     = (int)BacnetEventNotificationData.BacnetEventStates.EVENT_STATE_NORMAL;
                    NotifyState = EventToNormal;
                }
                /* Present_Value fall below the Low_Limit ? */
                if ((pv < ll) && LimitEnabledLow)
                {
                    toState = (int)BacnetEventNotificationData.BacnetEventStates.EVENT_STATE_LOW_LIMIT;
                    if (!NotifyState)
                    {
                        NotifyState = EventToOffNormal;
                    }
                }
                break;

            case (uint)BacnetEventNotificationData.BacnetEventStates.EVENT_STATE_LOW_LIMIT:
                /* Present_Value exceed the Low_Limit + Deadband ? */
                if (pv > (ll + db))
                {
                    toState     = (int)BacnetEventNotificationData.BacnetEventStates.EVENT_STATE_NORMAL;
                    NotifyState = EventToNormal;
                }
                /* Present_Value exceed the High_Limit ? */
                if ((pv > hl) && LimitEnabledHigh)
                {
                    toState = (int)BacnetEventNotificationData.BacnetEventStates.EVENT_STATE_HIGH_LIMIT;
                    if (!NotifyState)
                    {
                        NotifyState = EventToOffNormal;
                    }
                }
                break;
            }

            if (toState != -1)
            {
                // Update Event_State
                m_PROP_EVENT_STATE = (uint)toState;

                BacnetGenericTime stamp = new BacnetGenericTime(DateTime.Now, BacnetTimestampTags.TIME_STAMP_DATETIME);

                // Update EVENT_TIME_STAMPS, 1 is for FAULT (not used)
                if (toState == 0)
                {
                    m_PROP_EVENT_TIME_STAMPS[2] = new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_TIMESTAMP, stamp); // Normal
                }
                else
                {
                    m_PROP_EVENT_TIME_STAMPS[1] = new BacnetValue(BacnetApplicationTags.BACNET_APPLICATION_TAG_TIMESTAMP, stamp); // Limit
                }
            }
            Last_PRESENT_VALUE = m_PROP_PRESENT_VALUE;

            if (NotifyState == false)
            {
                return;
            }

            // look for the related notification class object
            NotificationClass nc = (NotificationClass)Mydevice.FindBacnetObject(new BacnetObjectId(BacnetObjectTypes.OBJECT_NOTIFICATION_CLASS, m_PROP_NOTIFICATION_CLASS));

            if (nc != null)
            {
                nc.SendIntrinsectEvent(
                    m_PROP_OBJECT_IDENTIFIER,
                    (BacnetEventNotificationData.BacnetNotifyTypes)m_PROP_NOTIFY_TYPE,
                    BacnetEventNotificationData.BacnetEventTypes.EVENT_CHANGE_OF_VALUE,
                    (BacnetEventNotificationData.BacnetEventStates)fromState,
                    (BacnetEventNotificationData.BacnetEventStates)toState);
            }
        }