/***************************************************************************
 * Copyright (c) 2009 Digi International Inc., All Rights Reserved
 * 
 * This software contains proprietary and confidential information of Digi
 * International Inc.  By accepting transfer of this copy, Recipient agrees
 * to retain this software in confidence, to prevent disclosure to others,
 * and to make no use of this software other than that for which it was
 * delivered.  This is an unpublished copyrighted work of Digi International
 * Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
 * prohibited.
 * 
 * Restricted Rights Legend
 *
 * Use, duplication, or disclosure by the Government is subject to
 * restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
 * Technical Data and Computer Software clause at DFARS 252.227-7031 or
 * subparagraphs (c)(1) and (2) of the Commercial Computer Software -
 * Restricted Rights at 48 CFR 52.227-19, as applicable.
 *
 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
 *
 ***************************************************************************
 *
 * @Descr: XBeeWallRouter Class
 *
 * @History:
 *    10/01/09:   gsarabia      initial version.
 *
 ***************************************************************************/

#region Namespace Inclusions

using System;
using System.Text;

#endregion

namespace Digi.ZigBee
{
    public class XBeeWallRouter
    {
        #region Variables

        public struct ChannelSourceDevice
        {
            public string Name;
            public string Unit;
            public float Value;
            public DateTime? TimeStamp;
        }

        private XBeeDeviceManager InternalXBeeDeviceManager = null;
        private ulong InternalIEEEAddress = 0x00;
        
        private ushort InternalIR = 1000;

        private ChannelSourceDevice InternalLight = new ChannelSourceDevice();
        private ChannelSourceDevice InternalTemperature = new ChannelSourceDevice();

        #endregion

        #region Constructors

        /// <summary>Initializes a new instance of the XBeeWallRouter class using the specified XBee device manager, and IEEE address.</summary>
        /// <param name="MyXBeeDeviceManager">Must be set to the name of an XBeeDeviceManager object.</param>
        /// <param name="IEEEAddress">The extended address of the XBee device you would like to monitor.</param>
        public XBeeWallRouter(XBeeDeviceManager MyXBeeDeviceManager, ulong IEEEAddress)
        {
            InternalLight.Name = "Light";
            InternalLight.Unit = "Brightness";
            InternalLight.Value = 0.0F;
            InternalLight.TimeStamp = null;

            InternalTemperature.Name = "Temperature";
            InternalTemperature.Unit = "ºC";
            InternalTemperature.Value = 0.0F;
            InternalTemperature.TimeStamp = null;

            InternalXBeeDeviceManager = MyXBeeDeviceManager;
            InternalIEEEAddress = IEEEAddress; 

            InternalXBeeDeviceManager.ReceivePacket += new XBeeDeviceManager.ReceivePacketEventHandler(XBeeWallRouterRx);
            InternalXBeeDeviceManager.ExplicitReceivePacket += new XBeeDeviceManager.ExplicitReceivePacketEventHandler(XBeeWallRouterExplicitRx);
            InternalXBeeDeviceManager.IOSample += new XBeeDeviceManager.IOSampleEventHandler(XBeeWallRouterIOSampleRx);
            InternalXBeeDeviceManager.NodeIdentification += new XBeeDeviceManager.NodeIdentificationEventHandler(XBeeWallRouterNodeIdentificationRx);
            InternalXBeeDeviceManager.RouteRecord += new XBeeDeviceManager.RouteRecordEventHandler(XBeeWallRouterRouteRecordRx);
        }

        /// <summary>Initializes a new instance of the XBeeWallRouter class using the specified XBee device manager, IEEE address, and sample rate.</summary>
        /// <param name="MyXBeeDeviceManager">Must be set to the name of an XBeeDeviceManager object.</param>
        /// <param name="IEEEAddress">The extended address of the XBee device you would like to monitor.</param>
        /// <param name="SampleRate">The sample rate of the XBee Wall Router.</param>
        public XBeeWallRouter(XBeeDeviceManager MyXBeeDeviceManager, ulong IEEEAddress, ushort SampleRate)
        {
            InternalLight.Name = "Light";
            InternalLight.Unit = "Brightness";
            InternalLight.Value = 0.0F;
            InternalLight.TimeStamp = null;

            InternalTemperature.Name = "Temperature";
            InternalTemperature.Unit = "ºC";
            InternalTemperature.Value = 0.0F;
            InternalTemperature.TimeStamp = null;

            InternalXBeeDeviceManager = MyXBeeDeviceManager;
            InternalIEEEAddress = IEEEAddress;
            InternalIR = SampleRate;

            InternalXBeeDeviceManager.ReceivePacket += new XBeeDeviceManager.ReceivePacketEventHandler(XBeeWallRouterRx);
            InternalXBeeDeviceManager.ExplicitReceivePacket += new XBeeDeviceManager.ExplicitReceivePacketEventHandler(XBeeWallRouterExplicitRx);
            InternalXBeeDeviceManager.IOSample += new XBeeDeviceManager.IOSampleEventHandler(XBeeWallRouterIOSampleRx);
            InternalXBeeDeviceManager.NodeIdentification += new XBeeDeviceManager.NodeIdentificationEventHandler(XBeeWallRouterNodeIdentificationRx);
            InternalXBeeDeviceManager.RouteRecord += new XBeeDeviceManager.RouteRecordEventHandler(XBeeWallRouterRouteRecordRx);
        }

        #endregion

        #region Properties

            #region Light Channel

            /// <summary>Gets light channel source device property.</summary>
            public ChannelSourceDevice Light
            {
                get
                {
                    return InternalLight;
                }
            }

            #endregion

            #region Temperature Channel

            /// <summary>Gets temperature channel source device property.</summary>
            public ChannelSourceDevice Temperature
            {
                get
                {
                    return InternalTemperature;
                }
            }

            #endregion

        #endregion

        #region Methods

            #region XBee Wall Router Rx

            public void XBeeWallRouterRx(XBeeDeviceManager sender, ulong? IEEEAddress, ushort? NwkAddress, Rx_Options? Options, byte[] ReceivedData)
            {
                if (InternalIEEEAddress == IEEEAddress)
                {
                    if (ReceivePacket != null)
                        ReceivePacket(this, IEEEAddress, NwkAddress, Options, ReceivedData);
                }
            }

            #endregion

            #region XBee Wall Router Explicit Rx

            public void XBeeWallRouterExplicitRx(XBeeDeviceManager sender, ulong IEEEAddress, ushort NwkAddress, byte SourceEndPoint, byte DestinationEndPoint, ushort ClusterID, ushort ProfileID, Rx_Options Options, byte[] ReceivedData)
            {
                if (InternalIEEEAddress == IEEEAddress)
                {
                    if (ExplicitReceivePacket != null)
                        ExplicitReceivePacket(this, IEEEAddress, NwkAddress, SourceEndPoint, DestinationEndPoint, ClusterID, ProfileID, Options, ReceivedData);
                }
            }

            #endregion

            #region XBee Wall Router IO Sample Received

            public void XBeeWallRouterIOSampleRx(XBeeDeviceManager sender, ulong IEEEAddress, ushort NwkAddress, Rx_Options Options, byte Samples, ushort? DigitalMask, byte? AnalogMask, ushort? DigitalSamples, ushort[] AnalogSamples)
            {
                if (InternalIEEEAddress == IEEEAddress)
                {
                    DateTime Time = DateTime.Now;

                    InternalLight.Value = (float)AnalogSamples[0];
                    InternalLight.TimeStamp = Time;

                    InternalTemperature.Value = (float)((AnalogSamples[1] - 500.0) / 10.0 - 4.0);
                    InternalTemperature.TimeStamp = Time;

                    if (IOSample != null)
                        IOSample(this, IEEEAddress, NwkAddress, Options, Samples, DigitalMask, AnalogMask, DigitalSamples, AnalogSamples);
                }
            }

            #endregion

            #region XBee Wall Router Node Identification

            public void XBeeWallRouterNodeIdentificationRx(XBeeDeviceManager sender, Rx_Options Options, ulong IEEEAddress, ushort NwkAddress, string NodeIdentifier, ushort Parent, Node_Type DeviceType, Source_Event SourceEvent, ushort ProfileID, ushort ManufacturerID, uint? DeviceTypeID)
            {
                if (InternalIEEEAddress == IEEEAddress)
                {
                    if (NodeIdentification != null)
                        NodeIdentification(this, Options, IEEEAddress, NwkAddress, NodeIdentifier, Parent, DeviceType, SourceEvent, ProfileID, ManufacturerID, DeviceTypeID);
                }
            }

            #endregion

            #region XBee Wall Router Route Record

            public void XBeeWallRouterRouteRecordRx(XBeeDeviceManager sender, ulong IEEEAddress, ushort NwkAddress, Rx_Options Options, byte NumberAddresses, ushort[] Addresses)
            {
                if (InternalIEEEAddress == IEEEAddress)
                {
                    if (RouteRecord != null)
                        RouteRecord(this, IEEEAddress, NwkAddress, Options, NumberAddresses, Addresses);
                }
            }

            #endregion

            #region SampleRate

            /// <summary>
            /// Sets the IO Sample Rate to enable periodic sampling. For periodic sampling 
            /// to be enabled, IO Sample Rate must be set to a non-zero value. IO Samples 
            /// are sent to the Destination Address.
            /// </summary>
            /// <param name="Time">Sample rate of the XBee Wall Router in milliseconds.</param>
            /// <returns>True if successful.</returns>
            public bool SampleRate(ushort Time)
            {
                bool XBeeRemoteATCmdEnable = InternalXBeeDeviceManager.RemoteATCmdEnable;
                byte XBeeBroadcastRadius = InternalXBeeDeviceManager.BroadcastRadius;
                bool XBeeMulticastTransmissionEnable = InternalXBeeDeviceManager.MulticastTransmissionEnable;
                bool XBeeExplicitAddressingEnable = InternalXBeeDeviceManager.ExplicitAddressingEnable;
                InternalXBeeDeviceManager.RemoteATCmdEnable = false;
                InternalXBeeDeviceManager.BroadcastRadius = 0x00;
                InternalXBeeDeviceManager.MulticastTransmissionEnable = false;
                InternalXBeeDeviceManager.ExplicitAddressingEnable = false;
                
                bool Status = false;
                try
                {
                    InternalXBeeDeviceManager.DestinationAddress(InternalIEEEAddress);
                    InternalXBeeDeviceManager.RemoteATCmdEnable = true;
                    InternalXBeeDeviceManager.IOSampleRate(Time);
                    InternalIR = Time;
                    InternalXBeeDeviceManager.Write();
                    Status = true;
                }
                catch
                {
                    Status = false;
                }
                finally
                {
                    InternalXBeeDeviceManager.ExplicitAddressingEnable = XBeeExplicitAddressingEnable;
                    InternalXBeeDeviceManager.MulticastTransmissionEnable = XBeeMulticastTransmissionEnable;
                    InternalXBeeDeviceManager.BroadcastRadius = XBeeBroadcastRadius;
                    InternalXBeeDeviceManager.RemoteATCmdEnable = XBeeRemoteATCmdEnable;
                }
                return Status;
            }

            #endregion

            #region Start

            /// <summary>Start the device driver.</summary>
            /// <returns>True if successful.</returns>
            public bool Start()
            {
                bool XBeeRemoteATCmdEnable = InternalXBeeDeviceManager.RemoteATCmdEnable;
                byte XBeeBroadcastRadius = InternalXBeeDeviceManager.BroadcastRadius;
                bool XBeeMulticastTransmissionEnable = InternalXBeeDeviceManager.MulticastTransmissionEnable;
                bool XBeeExplicitAddressingEnable = InternalXBeeDeviceManager.ExplicitAddressingEnable;
                InternalXBeeDeviceManager.RemoteATCmdEnable = false;
                InternalXBeeDeviceManager.BroadcastRadius = 0x00;
                InternalXBeeDeviceManager.MulticastTransmissionEnable = false;
                InternalXBeeDeviceManager.ExplicitAddressingEnable = false;

                bool Status = false;
                try
                {
                    // Get the host IEEE address
                    ulong IEEEAddress = InternalXBeeDeviceManager.SerialNumber();
                    
                    InternalXBeeDeviceManager.DestinationAddress(InternalIEEEAddress);
                    InternalXBeeDeviceManager.RemoteATCmdEnable = true;

                    // Set the destination for I/O samples to be the host
                    InternalXBeeDeviceManager.DestinationAddress(IEEEAddress);

                    // Configure pins DI1 & DI2 for analog input
                    InternalXBeeDeviceManager.AD1DIO1Configuration(AD1DIO1.Analog_Input);
                    InternalXBeeDeviceManager.AD2DIO2Configuration(AD2DIO2.Analog_Input);

                    // Configure the IO Sample Rate
                    InternalXBeeDeviceManager.IOSampleRate(InternalIR);

                    InternalXBeeDeviceManager.Write();

                    Status = true;
                }
                catch
                {
                    Status = false;
                }
                finally
                {
                    InternalXBeeDeviceManager.ExplicitAddressingEnable = XBeeExplicitAddressingEnable;
                    InternalXBeeDeviceManager.MulticastTransmissionEnable = XBeeMulticastTransmissionEnable;
                    InternalXBeeDeviceManager.BroadcastRadius = XBeeBroadcastRadius;
                    InternalXBeeDeviceManager.RemoteATCmdEnable = XBeeRemoteATCmdEnable;
                }
                return Status;
            }

            #endregion

            #region Stop

            /// <summary>Stop the device driver..</summary>
            /// <returns>True if successful.</returns>
            public bool Stop()
            {
                return SampleRate(0);
            }

            #endregion

        #endregion

        #region Events & Delegates

        public event XBeeReceivePacketEventHandler ReceivePacket;
        public delegate void XBeeReceivePacketEventHandler(XBeeWallRouter sender, ulong? IEEEAddress, ushort? NwkAddress, Rx_Options? Options, byte[] ReceivedData);

        public event XBeeExplicitReceivePacketEventHandler ExplicitReceivePacket;
        public delegate void XBeeExplicitReceivePacketEventHandler(XBeeWallRouter sender, ulong IEEEAddress, ushort NwkAddress, byte SourceEndPoint, byte DestinationEndPoint, ushort ClusterID, ushort ProfileID, Rx_Options Options, byte[] ReceivedData);

        public event XBeeIOSampleEventHandler IOSample;
        public delegate void XBeeIOSampleEventHandler(XBeeWallRouter sender, ulong IEEEAddress, ushort NwkAddress, Rx_Options Options, byte Samples, ushort? DigitalMask, byte? AnalogMask, ushort? DigitalSamples, ushort[] AnalogSamples);

        public event XBeeNodeIdentificationEventHandler NodeIdentification;
        public delegate void XBeeNodeIdentificationEventHandler(XBeeWallRouter sender, Rx_Options Options, ulong IEEEAddress, ushort NwkAddress, string NodeIdentifier, ushort Parent, Node_Type DeviceType, Source_Event SourceEvent, ushort ProfileID, ushort ManufacturerID, uint? DeviceTypeID);

        public event XBeeRouteRecordEventHandler RouteRecord;
        public delegate void XBeeRouteRecordEventHandler(XBeeWallRouter sender, ulong IEEEAddress, ushort NwkAddress, Rx_Options Options, byte NumberAddresses, ushort[] Addresses);

        #endregion
    }
}
