using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using Microsoft.Azure.Devices.Client;
using Newtonsoft.Json;

using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace AnyI2C
{
    public class KentProj
    {
        [XmlIgnore ]
        CommInterface CommObj = null;
        // variables read from devices


        [XmlIgnore]
        static int ID = 0;
        [XmlIgnore]
        static DateTime LastReadTime = DateTime.Now;
        DateTime TimeInFile = DateTime.Now;
        const int buzzOnTime = 8;   // 2 seconds
        const int LightOnTime = 30;   // 2 seconds
        // flag for using 
        public bool UsingFahrenheit = true;
        public int PowerSetting = 10;
        public enum enumUserStatus
        {
            Approved,
            Unapproved,
            NoUser
        } ;
        public enumUserStatus UserStatus = enumUserStatus.NoUser;
        // Bus 0
        public double B0_SHT25_Humidity;
        public double B0_SHT25_Temperature;

        public int B0_BH1745_AmbientLight_R;
        public int B0_BH1745_AmbientLight_G;
        public int B0_BH1745_AmbientLight_B;
        public int B0_BH1745_AmbientLight_C;

        public double B0_HP203B_Pressure;
        public double B0_HP203B_Temperature;

        public int B0_TMD26721_Promimity;
        public int B0_A3G4250DTR_Gyro_X;
        public int B0_A3G4250DTR_Gyro_Y;
        public int B0_A3G4250DTR_Gyro_Z;

        public double B0_LPG_MQ4_Gas;
        public double B0_LPG_MQ9_Monoxide;

        public int B0_PCA9685_CH1 = 0;       // Position 0 to 255, for door lock
        public int B0_PCA9685_CH2 = 0;       // Position 0 to 255, for door lock

        // Bus 1
        public double B1_MCP9803_FRIDG_TOP_LEFT;

        public double B1_MCP9803_FRIDG_TOP_RIGHT;

        public double B1_MCP9803_FRIDG_BOTTOM_LEFT;

        public double B1_MCP9803_FRIDG_BOTTOM_RIGHT;

        public double B1_SHT25_Humidity;
        public double B1_SHT25_Temperature;

        public double B1_LED_Temperature; // show led value, range from -9.9 - 99.9, this value will be average of four fridg sensors' value

        public byte B1_LED_R; // LED R Value
        public byte B1_LED_G; // LED G Value
        public byte B1_LED_B; // LED B Value

        // Bus 2
        public double B2_MCP9803_FRZR_LEFT;
        public double B2_MCP9803_FRZR_RIGHT;

        public double B2_LED_Temperature; // show led value, range from -9.9 - 99.9, this value will be average of four fridg sensors' value

        public byte B2_LED_R; // LED R Value
        public byte B2_LED_G; // LED G Value
        public byte B2_LED_B; // LED B Value

        public bool B2_BuzzerOn;    // flag for buzzer, true for on, false for off

        // Bus 3
        public double B3_Voltage;              // Voltage
        public double B3_current;               // Amp
        public double B3_Power;                 // Watt
        public double B3_Energy;                // Kwh

        public bool B3_GPIO_Door1;                  // gpio input 1 for door 1 status, true for close, false for open
        public bool B3_GPIO_Door2;                  // gpio input 2 for door 2 status, true for close, false for open

        public bool B3_GPIO_Relay;                  // Relay status, true for on, flase for off

        public double B3_ADC121_Sound_Sensor;

        // Bus 4
        public double B4_MCP9600_Compressor_High_Side;

        public double B4_MCP9600_Compressor_Low_Side;

        public double B4_MCP9600_FRZR_Temp;

        // Flags for each bus i2c operation 
        public bool B0_Read_Success = true;
        public bool B1_Read_Success = true;
        public bool B2_Read_Success = true;
        public bool B3_Read_Success = true;
        public bool B4_Read_Success = true;

        
        public DateTime ApprovedTime = DateTime.MinValue;
        public DateTime DeniedTime = DateTime.MinValue;

        public KentProj(CommInterface _commObj)
        {
            CommObj = _commObj;
        }

        public KentProj()
        {
        }

        public bool ReadFile(string filename)
        {
            bool bSuccess = false;
            try
            {
                // sample file

                // ID: 670
                // Lock1: off
                // Lock2:off
                // Power:4
                // User: Approved,Xu,10 / 12 / 2017 2:07:09 PM

                StreamReader file = new StreamReader(filename);
                string line = file.ReadLine();  // read id

                line = file.ReadLine(); // read unit
                string unit = GetParameter(line);
                if (unit == "C")
                {
                    UsingFahrenheit = false;
                }
                else
                {
                    UsingFahrenheit = true;
                }

                line = file.ReadLine(); // read lock1
                string lock1 = GetParameter(line);
                B0_PCA9685_CH1 = lock1.ToLower().Contains("off") ? 255 : 0;

                line = file.ReadLine(); // read lock2
                string lock2 = GetParameter(line);
                B0_PCA9685_CH2 = lock2.ToLower().Contains("off") ? 255 : 0;

                line = file.ReadLine(); // read Power
                string power = GetParameter(line);
                PowerSetting = int.Parse(power);

                line = file.ReadLine(); // read User
                string approved = GetParameter(line);
                TimeInFile = File.GetLastWriteTime(filename);
                //string approved = line.Remove(0, 5);    // remove User:
                //string[] paras = approved.Split(',');
                //string strTime = paras[2];
                //TimeInFile = DateTime.Parse(strTime);
                B2_BuzzerOn = false;
                TimeSpan span = DateTime.Now - TimeInFile;
                if (approved.ToLower().Contains("denied"))
                {
                    //if (UserStatus != enumUserStatus.Unapproved)
                    //{
                    //    TimeInFile = DateTime.Now;
                    //}
                    if(span.TotalSeconds > 0 && span.TotalSeconds < buzzOnTime)   // first time denied detected
                    {
                        UserStatus = enumUserStatus.Unapproved;
                        B2_BuzzerOn = true;
                    }
                    else
                    {
                        B2_BuzzerOn = false;
                    }
                    if (span.TotalSeconds > 0 && span.TotalSeconds < LightOnTime)   // first time denied detected
                    {
                        UserStatus = enumUserStatus.Unapproved;
                        B1_LED_B = 0;
                        B1_LED_R = 0xFF;

                        B2_LED_B = 0;
                        B2_LED_R = 0xFF;
                        LastReadTime = TimeInFile;
                    }
                    else
                    {
                        B2_BuzzerOn = false;
                        B1_LED_G = 0;
                        B1_LED_R = 0;

                        B2_LED_G = 0;
                        B2_LED_R = 0;
                    }


                }
                else if(approved.ToLower().Contains("no user"))
                {
                    //if (UserStatus != enumUserStatus.NoUser)
                    //{
                    //    TimeInFile = DateTime.Now;
                    //}
                    UserStatus = enumUserStatus.NoUser;
                    B2_BuzzerOn = false;
                    B1_LED_G = 0;
                    B1_LED_R = 0;

                    B2_LED_G = 0;
                    B2_LED_R = 0;
                    LastReadTime = TimeInFile;
                }
                else if (approved.ToLower().Contains("approved"))
                {
                    //if (UserStatus != enumUserStatus.Approved)
                    //{
                    //    TimeInFile = DateTime.Now;
                    //}

                    if (span.TotalSeconds > 0 && span.TotalSeconds < LightOnTime * 2)
                    {
                        UserStatus = enumUserStatus.Approved;
                        B2_BuzzerOn = false;
                        B1_LED_G = 0x70;
                        B1_LED_R = 0;

                        B2_LED_G = 0x70;
                        B2_LED_R = 0;
                        LastReadTime = TimeInFile;
                    }
                    else
                    {
                        UserStatus = enumUserStatus.Approved;
                        B2_BuzzerOn = false;
                        B1_LED_G = 0;
                        B1_LED_R = 0;

                        B2_LED_G = 0;
                        B2_LED_R = 0;
                    }
                }

                file.Close();
                Debug.Print("Read File at " + DateTime.Now.ToLongTimeString());
                Debug.Print("LastReadTime at " + LastReadTime.ToLongTimeString());
                Debug.Print("span " + span.ToString());

            }
            catch
            {
                bSuccess = false;
            }
            return bSuccess;
        }

        private string GetParameter(string str)
        {
            string par = string.Empty;
            string[] pars = str.Split(':');
            if(pars.Length  > 1)
            {
                par = pars[1];
            }
            return par;
        }



        /// <summary>
        /// Read all sensors and send data to Iot cloud
        /// </summary>
        /// <returns></returns>
        public bool IotSend(string connectStr, string deviceID, int messageId)
        {
            InitialAllDevices();
            // read all sensors's value to variables
            ReadAllSensors();
            bool success = B0_Read_Success & B1_Read_Success & B2_Read_Success
                              & B3_Read_Success & B4_Read_Success;

            if (success)
            {
                SendDataToAzure(connectStr, deviceID, messageId);
            }
            return success;
        }

        private async Task SendDataToAzure(string connectStr, string deviceID, int messageId)
        {

            DeviceClient deviceClient = DeviceClient.CreateFromConnectionString(connectStr, TransportType.Mqtt);
            var telemetryDataPoint = new
            {
                deviceID,
                messageId,
                MessageType = "Sensor",
                time = DateTime.UtcNow.ToString("o"),
                UsingFahrenheit,
                PowerSetting,

                // Bus 0
                B0_SHT25_Humidity,
                B0_SHT25_Temperature,

                B0_BH1745_AmbientLight_R,
                B0_BH1745_AmbientLight_G,
                B0_BH1745_AmbientLight_B,
                B0_BH1745_AmbientLight_C,

                B0_HP203B_Pressure,
                B0_HP203B_Temperature,

                B0_TMD26721_Promimity,
                B0_A3G4250DTR_Gyro_X,
                B0_A3G4250DTR_Gyro_Y,
                B0_A3G4250DTR_Gyro_Z,

                B0_LPG_MQ4_Gas,
                B0_LPG_MQ9_Monoxide,

                // Bus 1
                B1_MCP9803_FRIDG_TOP_LEFT,

                B1_MCP9803_FRIDG_TOP_RIGHT,

                B1_MCP9803_FRIDG_BOTTOM_LEFT,

                B1_MCP9803_FRIDG_BOTTOM_RIGHT,

                B1_SHT25_Humidity,
                B1_SHT25_Temperature,

                B1_LED_Temperature,
                B1_LED_R,
                B1_LED_G,
                B1_LED_B,

                // Bus 2

                B2_LED_Temperature,
                B2_LED_R,
                B2_LED_G,
                B2_LED_B,

                B2_BuzzerOn,

                // Bus 3
                B3_Voltage,
                B3_current,
                B3_Power,
                B3_Energy,
                B3_ADC121_Sound_Sensor,
                B3_GPIO_Door1,
                B3_GPIO_Door2,
                B3_GPIO_Relay,

                // Bus 4
                B4_MCP9600_Compressor_High_Side,

                B4_MCP9600_Compressor_Low_Side,

                B4_MCP9600_FRZR_Temp,

                // Flags for each bus i2c operation 
                B0_Read_Success,
                B1_Read_Success,
                B2_Read_Success,
                B3_Read_Success,
                B4_Read_Success

            };

            //: 18.Serialize the telemetryDataPoint to JSON
            var messageString = JsonConvert.SerializeObject(telemetryDataPoint);

            //: 19.Encode the JSON string to ASCII as bytes and create new Message with the bytes
            var msg = new Microsoft.Azure.Devices.Client.Message(Encoding.ASCII.GetBytes(messageString));

            await deviceClient.SendEventAsync(msg);
        }


        /// <summary>
        /// Initial all devices/sensors here
        /// </summary>
        public void InitialAllDevices()
        {

        }


        /// <summary>
        /// 
        /// </summary>
        public void ReadAllSensors()
        {


            Debug.Print("Read All Sensors Begine");
            ReadBus3_0();     // has read door sensor first before lock/unlock door
            UpdateServo();

            ReadBus0();

            ReadBus3_0();     // has read door sensor first before lock/unlock door
            UpdateServo();

            ReadBus4();

            ReadBus3_0();     // has read door sensor first before lock/unlock door
            UpdateServo();

            ReadBus1();

            ReadBus3_0();     // has read door sensor first before lock/unlock door
            UpdateServo();

            ReadBus2();

            ReadBus3_0();     // has read door sensor first before lock/unlock door
            UpdateServo();

            ReadBus3_1();     // has read door sensor first before lock/unlock door
            Debug.Print("Read All Sensors End");
            Debug.Print(ToString());
        }

        private void UpdateServo()
        {
            CommObj.SetPort(0);
            SetServos(0x70);

        }

        private void UpdateLight_Buzzer()
        {
            CommObj.SetPort(1);
            //B1_LED_R = 0xA0;
            //B1_LED_G = 0x70;  
            //B1_LED_B = 0;
            // Set LED RGB value
            SetB1_LED_RGB(0x1);

            CommObj.SetPort(2);
            SetB2_LED_RGB(0x1);
            SetB2_Buzzer(0x41);

        }

        /// <summary>
        /// read all sensors on bus 0
        /// </summary>
        private void ReadBus0()
        {
            //Switch to port 0
            CommObj.SetPort(0);
            string str = string.Empty;
            // Read SHT25  0x40
            str = ReadSHT25(0x40, ref B0_SHT25_Humidity, ref B0_SHT25_Temperature) + Environment.NewLine;
            
            // Read BH1745 0x38
            str += ReadBH1745(0x38, ref B0_BH1745_AmbientLight_R, ref B0_BH1745_AmbientLight_G, 
                ref B0_BH1745_AmbientLight_B,  ref B0_BH1745_AmbientLight_C) + Environment.NewLine;

            // Read LPS25HB/HP203B
            str += ReadHP203B(0x77, ref B0_HP203B_Temperature, ref B0_HP203B_Pressure) + Environment.NewLine;

            // Read TMD26721 0x39
            str += ReadTMD26721(0x39, ref B0_TMD26721_Promimity) + Environment.NewLine;

            // Read LG4200 0x68, replaced by 4250
            str += ReadA3G4250(0x68, ref B0_A3G4250DTR_Gyro_X, ref B0_A3G4250DTR_Gyro_Y, ref B0_A3G4250DTR_Gyro_Z) + Environment.NewLine;

            // Read MQ-4, LPG LNG Gas sensor, 0x50
            str += ReadMQ4(0x50, ref B0_LPG_MQ4_Gas) + Environment.NewLine;
            
            // Read MQ-9, Carbon Monoxide Combustible Sensor, 0x51
            str += ReadMQ9(0x51, ref B0_LPG_MQ9_Monoxide) + Environment.NewLine;

            if (str.Contains("Fail"))
            {
                B0_Read_Success = false;
            }
            //SetServos(0x70);

            Debug.Print(str);
        }


        /// <summary>
        /// Read all sensors on bus 1
        /// </summary>
        private void ReadBus1()
        {
            //Switch to port 1
            CommObj.SetPort(1);
            string str = string.Empty;

            //// Read MCP9803 0x4A FRIDG-TOP-LEFT
            //str += ReadMCP9803(0x4A, ref B1_MCP9803_FRIDG_TOP_LEFT) + Environment.NewLine;

            //// Read MCP9803 0x4B FRIDG-TOP-RIGHT
            //str += ReadMCP9803(0x49, ref B1_MCP9803_FRIDG_TOP_RIGHT) + Environment.NewLine;

            //// Read MCP9803 0x4C FRIDG-BOTTOM-LEFT
            //str += ReadMCP9803(0x4B, ref B1_MCP9803_FRIDG_BOTTOM_LEFT) + Environment.NewLine;

            //// Read MCP9803 0x4D FRIDG-BOTTOM-RIGHT
            //str += ReadMCP9803(0x48, ref B1_MCP9803_FRIDG_BOTTOM_RIGHT) + Environment.NewLine;

            // Read SHT25 0x40 FRIDG-TOP-CENTER
            str += ReadSHT25(0x40, ref B1_SHT25_Humidity, ref B1_SHT25_Temperature) + Environment.NewLine;

            //B1_LED_Temperature = (B1_MCP9803_FRIDG_BOTTOM_LEFT + B1_MCP9803_FRIDG_BOTTOM_RIGHT + B1_MCP9803_FRIDG_TOP_LEFT + B1_MCP9803_FRIDG_TOP_RIGHT) / 4.0;
            B1_LED_Temperature = B1_SHT25_Temperature;


            // setup relay status by temperature
            double Fahrenheit = B1_LED_Temperature * 1.8 + 32;

            if ((Fahrenheit > (10 - PowerSetting) * 2.0 + 34) && PowerSetting > 0)
            {
                B3_GPIO_Relay = true;
            }
            else
            {
                B3_GPIO_Relay = false;
            }
            if (UsingFahrenheit)
            {
                B1_LED_Temperature = Fahrenheit;
            }

            if (UsingFahrenheit)
            {
                B4_MCP9600_FRZR_Temp = B1_LED_Temperature - 24;
            }
            else
            {
                B4_MCP9600_FRZR_Temp = B1_LED_Temperature - 12;
            }
            B2_LED_Temperature = B4_MCP9600_FRZR_Temp;

            // Set LED temperature, address 0x70
            str += SetB1_LED_Temperatue(0x0);

            //B1_LED_R = 0xA0;
            //B1_LED_G = 0x70;  
            //B1_LED_B = 0;
            // Set LED RGB value
            str += SetB1_LED_RGB(0x1);

            if (str.Contains("Fail"))
            {
                B1_Read_Success = false;
            }

            Debug.Print(str);

            Debug.Print(str);
        }


        /// <summary>
        /// Read all sensors on bus 2
        /// </summary>
        private void ReadBus2()
        {
            //Switch to port 2
            CommObj.SetPort(2);
            string str = string.Empty;

            //// Read 4 Channel A/D (FRZR Door, FRIDG Door), MCP3428(0x68)
            //str += ReadMCP3428(0x68, 0, ref B2_MCP3428_AD_FRZR_Door) + Environment.NewLine; // channel 0, for FRZR Door
            //str += ReadMCP3428(0x68, 1, ref B2_MCP3428_AD_FRIDG_Door) + Environment.NewLine; // channel 1, for FRIDG Door

            //// Read MCP9803 0x48 FRZR-LEFT
            //str += ReadMCP9803(0x4D, ref B2_MCP9803_FRZR_LEFT) + Environment.NewLine;

            //// Read MCP9803 0x49 FRZR-RIGHT
            //str += ReadMCP9803(0x4C, ref B2_MCP9803_FRZR_RIGHT) + Environment.NewLine;
            //str = ReadSHT25(0x40, ref B2_MCP9803_FRZR_LEFT, ref B2_MCP9803_FRZR_RIGHT) + Environment.NewLine;


            //B2_LED_Temperature = (B2_MCP9803_FRZR_LEFT);// + B2_MCP9803_FRZR_RIGHT) / 2.0;
            B2_LED_Temperature = (B4_MCP9600_FRZR_Temp);

            if (UsingFahrenheit)
            {
                //B2_LED_Temperature = B2_LED_Temperature * 1.8 + 32;
            }
            else
            {
                B2_LED_Temperature = (B2_LED_Temperature - 32) / 1.8;
            }

            // Set LED temperature, address 0x70
            str += SetB2_LED_Temperatue(0x0);

            //B2_LED_R = 0xA0;
            //B2_LED_G = 0x70;
            //B2_LED_B = 0;
            // Set LED RGB value
            str += SetB2_LED_RGB(0x1);

            str += SetB2_Buzzer(0x41);

            if (str.Contains("Fail"))
            {
                B2_Read_Success = false;
            }

            Debug.Print(str);
        }


        /// <summary>
        /// Read all sensors on bus 3
        /// </summary>
        private void ReadBus3_1()
        {
            string str = string.Empty;

            //Switch to port 3
            CommObj.SetPort(3);
            str += SetRelay(0x20);
            //// Read Relay & GPIO 0x20
            //str += ReadGPIO(0x20, ref B2_MCP23008_STATUS) + Environment.NewLine;

            //// Read Sound Sensor 0x41, ADC121(0x50?), this might not working
            str += ReadADC121(0x50, ref B3_ADC121_Sound_Sensor) + Environment.NewLine;

            // read energy meter
            str += ReadEnergyMeter(0x2A);
            Debug.Print(str);


        }


        /// <summary>
        /// Read GPIO on bus 3
        /// </summary>
        private void ReadBus3_0()
        {
            string str = string.Empty;
            string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            // input file
            string filename = folderPath + "\\app2fridge.txt";
            ReadFile(filename);
            //Switch to port 3
            //CommObj.SetPort(3);
            //str += UpdateGPIO(0x20);
            UpdateLight_Buzzer();
            Debug.Print(str);


        }


        /// <summary>
        /// Read all sensors on bus 4
        /// </summary>
        private void ReadBus4()
        {
            //Switch to port 4
            CommObj.SetPort(4);
            string str = string.Empty;
            //// Read Thermccouple(Compressor High-Side) 0x62
            //str += ReadMCP9600(0x62, ref B4_MCP9600_Compressor_High_Side) + Environment.NewLine;

            //// Read Thermccouple(Compressor Low-Side) 0x64
            //str += ReadMCP9600(0x64, ref B4_MCP9600_Compressor_Low_Side) + Environment.NewLine;
            
            //// Read Thermccouple(Compressor Evaporation Valve Low -Side) 0x67
            //str += ReadMCP9600(0x67, ref B4_MCP9600_FRZR_Temp) + Environment.NewLine;
            //if(UsingFahrenheit)
            //{
            //    B4_MCP9600_FRZR_Temp = B2_LED_Temperature - 24;
            //}
            //else
            //{
            //    B4_MCP9600_FRZR_Temp = B2_LED_Temperature - 12;
            //}

            if (str.Contains("Fail"))
            {
                B4_Read_Success = false;
            }

            Debug.Print(str);
        }


        /// <summary>
        /// Read sensor sht 25
        /// </summary>
        /// <param name="_addr"></param>
        /// <returns></returns>
        private string ReadSHT25(byte _addr, ref double humidity, ref double temperature)
        {
            string valuePair = string.Empty;
            try
            {
                // Read Humidity
                byte addr = (byte)(_addr * 2);
                int retry = 0;
                bool success = false;
                CommObj.Send(new byte[] { addr, 0xF5 }, 0);
                Thread.Sleep(10);
                while (!success && retry < 10)   // try 10 times
                {
                    byte[] value = CommObj.Send(new byte[] { addr }, 2);
                    if (value != null)
                    {
                        if (value.Length == 2)
                        {
                            success = true;
                            humidity = 125.0 * (value[0] * 256 + value[1]) / 65536.0 - 6.0;
                            //lbH.Text = humidity.ToString("F2");
                            break;
                        }

                    }
                    Thread.Sleep(100);
                    retry++;
                }
                if (!success)
                {
                    throw new Exception("Fail to read humidity");
                }
                retry = 0;
                success = false;
                // read temperature
                CommObj.Send(new byte[] { addr, 0xF3 }, 0);
                Thread.Sleep(100);
                while (!success && retry < 10)   // try 10 times
                {
                    byte[] value = CommObj.Send(new byte[] { addr }, 2);
                    if (value != null)
                    {
                        if (value.Length == 2)
                        {
                            success = true;
                            temperature = 175.72 * (value[0] * 256 + value[1]) / 65536.0 - 46.85;
                            //lbT.Text = temp.ToString("F2");
                            break;
                        }
                    }
                    retry++;
                    Thread.Sleep(100);
                }
                if (!success)
                {
                    throw new Exception("Fail to read temperature");
                }

                valuePair = string.Format("Humidity {0:F2}  Temperature {1:F2}", humidity, temperature);
            }
            catch
            {
                valuePair = string.Format("Fail to Read SHT25");
            }

            return valuePair;
        }

        /// <summary>
        /// Read BH1745
        /// </summary>
        /// <param name="_addr"></param>
        /// <returns></returns>
        private string ReadBH1745(byte _addr,ref int r, ref int g, ref int b, ref int c)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                // Congire Function Settings
                byte[] value = CommObj.Send(new byte[] { addr, 0x41, 0x00 }, 0);
                Thread.Sleep(500);
                value = CommObj.Send(new byte[] { addr, 0x42, 0x10 }, 0);
                value = CommObj.Send(new byte[] { addr, 0x44, 0x02 }, 0);
                value = CommObj.Send(new byte[] { addr, 0x50 }, 8);
                if (value != null)
                {

                    r = value[1] * 256 + value[0];
                    g = value[3] * 256 + value[2];
                    b = value[5] * 256 + value[4];
                    c = value[7] * 256 + value[6];
                    valuePair = string.Format("R {0} G {1} B {2} C{3}", r, g, b, c);
                }
                else
                {
                    throw new Exception("Fail to Read Color");
                }
            }
            catch
            {
                valuePair = string.Format("Fail Read BH1745");
            }

            return valuePair;
        }

        private string ReadHP203B(byte _addr, ref double temp, ref double pressure)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);

                // measure temperature and pressure
                byte[] value = CommObj.Send(new byte[] { addr, 0x40 }, 0);
                Thread.Sleep(500);
                value = CommObj.Send(new byte[] { addr, 0x10 }, 6);
                temp = 0;
                if ((value[0] & 0x8) == 0)
                {
                    temp = ((value[0] & 0x7) * 256 * 256 + value[1] * 256 + value[2]) / 100.0;
                }
                else // neg value
                {
                    temp = ((value[0] & 0x7) * 256 * 256 + value[1] * 256 + value[2] - Math.Pow(2, 20)) / 100.0;
                }

                pressure = ((value[3] & 0xf) * 256 * 256 + value[4] * 256 + value[5]) / 100.0;
                valuePair = string.Format("Pressure {0:F2}", pressure);
            }
            catch
            {
                valuePair = string.Format("Error Read HP203B");
            }

            return valuePair;

        }

        private string ReadTMD26721(byte _addr, ref int prox)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                // power on and measure
                // write to config
                byte[] value = CommObj.Send(new byte[] { addr, 0x80, 0x0D }, 0);
                value = CommObj.Send(new byte[] { addr, 0x98 }, 1);
                int p = value[0];
                value = CommObj.Send(new byte[] { addr, 0x99 }, 1);
                prox = p + value[0] * 256;
                valuePair = string.Format("Proximity {0}", p);
            }
            catch
            {
                valuePair = string.Format("Fail to Read TMD26721");
            }

            return valuePair;
        }


        private string ReadA3G4250(byte _addr, ref int x, ref int y ,  ref int z)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                //config the sensor
                CommObj.Send(new byte[] { addr, 0x20, 15 }, 0);
                CommObj.Send(new byte[] { addr, 0x23, 0 }, 0);
                Thread.Sleep(500);
                byte[] valuexl = CommObj.Send(new byte[] { addr, 0x28 }, 1);
                byte[] valuexh = CommObj.Send(new byte[] { addr, 0x29 }, 1);
                byte[] valueyl = CommObj.Send(new byte[] { addr, 0x2A }, 1);
                byte[] valueyh = CommObj.Send(new byte[] { addr, 0x2B }, 1);
                byte[] valuezl = CommObj.Send(new byte[] { addr, 0x2C }, 1);
                byte[] valuezh = CommObj.Send(new byte[] { addr, 0x2D }, 1);
                if (valuexh != null && valuexl != null && valueyh != null && valueyl != null && valuezh != null && valuezl != null)
                {
                    x = ((valuexh[0] * 256 + valuexl[0]) > 32767) ? ((((valuexh[0] * 256 + valuexl[0]) - 65536) / 16)) : (((valuexh[0] * 256 + valuexl[0]) / 16));
                    y = ((valueyh[0] * 256 + valueyl[0]) > 32767) ? ((((valueyh[0] * 256 + valueyl[0]) - 65536) / 16)) : (((valueyh[0] * 256 + valueyl[0]) / 16));
                    z = ((valuezh[0] * 256 + valuezl[0]) > 32767) ? ((((valuezh[0] * 256 + valuezl[0]) - 65536) / 16)) : (((valuezh[0] * 256 + valuezl[0]) / 16));
                    valuePair = string.Format("X {0} Y{1} Z{2}", x, y, z);
                }
                else
                {
                    throw new Exception("Fail to Read A3G4250");
                }
            }
            catch
            {
                valuePair = string.Format("Fail to Read A3G4250");
            }

            return valuePair;

        }

        private string ReadMQ4(byte _addr, ref double ppm)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                byte[] value = CommObj.Send(new byte[] { addr, 0x00 }, 2);
                if (value != null)
                {
                    int raw_adc = ((value[0] & 0x0F) * 256) + (value[1] & 0xFF);
                    ppm = ((10000.0 / 4096.0) * raw_adc) + 200;
                    valuePair = string.Format("Methane concentration {0:F2}", ppm);
                }
                else
                {
                    throw new Exception("Fail to Read MQ4");
                }
            }
            catch
            {
                valuePair = string.Format("Fail to Read MQ4");
            }
            return valuePair;
        }

        private string ReadMQ9(byte _addr, ref double ppm)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                byte[] value = CommObj.Send(new byte[] { addr, 0x00 }, 2);
                if (value != null)
                {
                    double raw_adc = (((value[0] & 0x0F) * 256) + (value[1] & 0xFF));
                    ppm = ((1000.0 / 4096.0) * raw_adc) + 10;
                    valuePair = string.Format("Monoxide concentration {0:F2}", ppm);
                }
                else
                {
                    throw new Exception("Fail to Read MQ9");
                }
            }
            catch
            {
                valuePair = string.Format("Fail to Read MQ9");
            }
            return valuePair;
        }

        private string ReadADC121(byte _addr, ref double v1)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                byte[] value = CommObj.Send(new byte[] { addr, 0 }, 2);
                if (value != null)
                {
                    byte v = (byte)(value[0] & 0xF);
                    v1 = (v * 256 + value[1]) / 4096.0 * 5.0;
                    valuePair = string.Format("ADC121 {0:F2}", v1);
                }
                else
                {
                    throw new Exception("Fail to Read ADC121");
                }
            }
            catch
            {
                valuePair = string.Format("Fail to Read ADC121");
            }
            return valuePair;
        }

        private string ReadMCP9803(byte _addr, ref double Temp)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                CommObj.Send(new byte[] { addr, 1, 60 }, 0);
                CommObj.Send(new byte[] { addr, 0 }, 0);
                byte[] value = CommObj.Send(new byte[] { addr }, 2);
                if (value != null)
                {
                    // Convert the data to 12-bits
                    int temp = ((value[0] * 256) + value[1]) / 16;
                    if (temp > 2047)
                    {
                        temp = -temp;
                    }
                    Temp = temp * 0.0625;

                    valuePair = string.Format("Temperature {0:F2}", Temp);
                }
                else
                {
                    throw new Exception("Fail to Read MCP9803");
                }

            }
            catch
            {
                valuePair = string.Format("Fail to Read XXX");
            }
            return valuePair;
        }

        /// <summary>
        /// Update the status of the MCP23008
        /// </summary>
        /// <param name="_addr"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        private string SetRelay(byte _addr)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                // initial board, gpio 0 as output, rest as input
                CommObj.Send(new byte[] { addr, 0, 254 }, 0);
                // update relay
                CommObj.Send(new byte[] { addr, 9, (byte)(B3_GPIO_Relay ? 1 : 0) }, 0);
            }
            catch
            {
                valuePair = string.Format("Fail to  Read GPIO");
            }
            return valuePair;
        }

        /// <summary>
        /// Update the status of the MCP23008
        /// </summary>
        /// <param name="_addr"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        private string UpdateGPIO(byte _addr)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                // initial board, gpio 0 as output, rest as input
                CommObj.Send(new byte[] { addr, 0, 254 }, 0);
                // set up pull up resister for gpio 1 and 2
                CommObj.Send(new byte[] { addr, 6, 6 }, 0);
                byte[] value = CommObj.Send(new byte[] { addr, 9 }, 1);
                if (value != null)
                {
                    B3_GPIO_Door1 = GetBit(value[0], 1) == 0;       // true for closed
                    B3_GPIO_Door2 = GetBit(value[0], 2) == 0;
                    valuePair = string.Format("Current B3_GPIO_Door1 {0}, B3_GPIO_Door2 {1}  ", B3_GPIO_Door1, B3_GPIO_Door2);

                }
                else
                {
                    throw new Exception("Fail to Read GPIO");
                }
                
            }
            catch
            {
                valuePair = string.Format("Fail to  Read GPIO");
            }
            return valuePair;
        }

        /// <summary>
        /// return the specific bit value
        /// </summary>
        /// <param name="v"></param>
        /// <param name="pos"></param>
        /// <returns></returns>
        static public byte GetBit(byte v, byte pos)
        {
            byte value = (byte)(1 << pos);
            byte result = (byte)((v & value) > 0 ? 1 : 0);

            return result;
        }

        private string ReadMCP3428(byte _addr, byte ch, ref double volt)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                bool read = false;
                for (int i = 0; i < 8; i++)  // try 8 times
                {
                    byte[] value = CommObj.Send(new byte[] { addr, ch }, 3);
                    if (value != null)
                    {
                        if ((value[2] & 128) == 0)       // valid data with 7bit of third byte is 0
                        {
                            read = true;
                            if (value[0] < 128)
                            {
                                int v = value[0] * 256 + value[1];
                                volt = (double)v / 32768.0 * 10.0;
                                break;
                            }
                            else
                            {
                                int v = (value[0] * 256 + value[1] - 65535);
                                volt = (double)v / 32768.0 * 10.0;
                                break;
                            }
                        }
                    }
                }
                if (read)
                {
                    valuePair = string.Format("Ch {0} Volt {1:F2}", ch, volt);
                }
                else
                {
                    throw new Exception("Failt to Read MCP3428");
                }
            }
            catch
            {
                valuePair = string.Format("Fail Read MCP3428");
            }
            return valuePair;
        }

        private string ReadMCP9600(byte _addr, ref double Temp)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                CommObj.Send(new byte[] { addr, 4, 0 }, 0);// clear status register
                CommObj.Send(new byte[] { addr, 0xc0, 0}, 0);// configure the type

                CommObj.Send(new byte[] { addr, 5, 7}, 0);// configure the type
                System.Threading.Thread.Sleep(100);

                CommObj.Send(new byte[] { addr, 6, 0x7c }, 0);// configure the device
                System.Threading.Thread.Sleep(100);

                byte[] value = CommObj.Send(new byte[] { addr, 4 }, 1);
                if (value != null)
                {
                    if ((value[0] & 0x40) == 0x40) // complete conversion
                    {
                        CommObj.Send(new byte[] { addr, 0 }, 0);
                        System.Threading.Thread.Sleep(500);
                        value = CommObj.Send(new byte[] { addr }, 2);
                        if (value != null)
                        {
                            if ((value[0] & 0x80) == 0x80)
                            {
                                Temp = ((value[0] & 0x7f) * 16 + value[1] / 16.0 - 1024);
                            }
                            else
                            {
                                Temp = (value[0] * 16 + value[1] / 16.0);
                            }
                            if(Temp > 1024)
                            {
                                Temp = 1024 - Temp; // change according kent
                            }
                            valuePair = string.Format("Temperature {0}", Temp);
                        }
                        else
                        {
                            throw new Exception("Fail to Read MCP9600");
                        }
                    }
                    else
                    {
                        throw new Exception("Fail to Read MCP9600");
                    }
                }
                else
                {
                    throw new Exception("Fail to Read MCP9600");
                }
            }
            catch
            {
                valuePair = string.Format("Fail Read MCP9600");
            }
            return valuePair;
        }


        /// <summary>
        /// template
        /// </summary>
        /// <param name="_addr"></param>
        /// <returns></returns>
        private string SetServos(byte _addr)
        {
            //CommObj.SetPort(2);
            //Servo1Pos = 0;
            //Servo2Pos = 0;
            //Led1 = 128;
            //Led2 = 128;
            //SetServos(0x40);
            //Thread.Sleep(1000);
            //Servo2Pos = 255;
            //SetServos(0x40);

            string valuePair = string.Empty;
            // put the logic of door lock/unlock here

            try
            {
                // setup pwm frequnce fist
                int freq = 50;  // 50 hz, for servos, works with led too
                byte addr = (byte)(_addr * 2);
                CommObj.Send(new byte[] { addr, 0x0, 0x10 }, 0); // enter sleep mode
                int prescale = 25000000 / 4096 / freq - 1;
                CommObj.Send(new byte[] { addr, 0xfe, (byte)(prescale) }, 0);
                CommObj.Send(new byte[] { addr, 0x0, 0x80 }, 0);  // resart
                CommObj.Send(new byte[] { addr, 0x1, 4 }, 0); // totem pole
                //if (/*!B3_GPIO_Door1 && */B0_PCA9685_CH1 == 0)  // do nothing if door is open while lock the door
                //{

                //}
                //else
                {
                    // setup servo1 pos, pulsa width is 20 ms for 50 hz. 0.7 ms is for 0, which is 143, 1.5 ms is for center, which is 429 in 4096
                    int off1 = 143 + B0_PCA9685_CH1 / 255 * 286;
                    byte OffL1 = (byte)(off1 & 0xff);
                    byte OffH1 = (byte)(off1 >> 8);
                    CommObj.Send(new byte[] { addr, 6, 0 }, 0); // OnL
                    CommObj.Send(new byte[] { addr, 7, 0 }, 0); // OnH
                    CommObj.Send(new byte[] { addr, 8, OffL1 }, 0); // OffL
                    CommObj.Send(new byte[] { addr, 9, OffH1 }, 0); // OffH
                }

                //if(/*!B3_GPIO_Door2 && */B0_PCA9685_CH2 == 0)
                //{

                //}
                //else
                {
                    // setup servo2 pos, pulsa width is 20 ms for 50 hz. 0.7 ms is for 0, which is 143, 1.5 ms is for center, which is 429 in 4096
                    int off2 = 143 + B0_PCA9685_CH2 / 255 * 286;
                    byte OffL2 = (byte)(off2 & 0xff);
                    byte OffH2 = (byte)(off2 >> 8);

                    CommObj.Send(new byte[] { addr, 10, 0 }, 0); // OnL
                    CommObj.Send(new byte[] { addr, 11, 0 }, 0); // OnH
                    CommObj.Send(new byte[] { addr, 12, OffL2 }, 0); // OffL
                    CommObj.Send(new byte[] { addr, 13, OffH2 }, 0); // OffH
                }

            }
            catch
            {
                valuePair = string.Format("Fail set Servos");
            }
            return valuePair;
        }

        /// <summary>
        /// Setup LED value, 
        /// </summary>
        /// <param name="_addr"></param>
        /// <returns></returns>
        private string SetB2_Buzzer(byte _addr)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                if (B2_BuzzerOn)
                {
                    CommObj.Send(new byte[] { addr, 3, 0xf0 }, 0);
                }
                else
                {
                    CommObj.Send(new byte[] { addr, 3, 0xff }, 0);
                }
            }
            catch
            {
                valuePair = string.Format("Fail set Buzzer");
            }
            return valuePair;
        }



        /// <summary>
        /// Setup LED value, 
        /// </summary>
        /// <param name="_addr"></param>
        /// <returns></returns>
        private string SetB2_LED_Temperatue(byte _addr)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);

                // initial
                CommObj.Send(new byte[] { addr, 9, 7 }, 0);
                CommObj.Send(new byte[] { addr, 0xa, 0xff }, 0);
                CommObj.Send(new byte[] { addr, 0xc, 0x01 }, 0);
                CommObj.Send(new byte[] { addr, 0xe, 0 }, 0);
                CommObj.Send(new byte[] { addr, 0xB, 3 }, 0);

                //CommObj.Send(new byte[] { addr, 0x1, 0 }, 0);
                //CommObj.Send(new byte[] { addr, 0x2, 0 }, 0);
                //CommObj.Send(new byte[] { addr, 0x3, 0 }, 0);
                if(B2_LED_Temperature < 0)
                {
                    double t = -B2_LED_Temperature;
                    byte d1 = (byte)((int)t / 10);
                    byte d2 = (byte)(((int)t - d1 * 10));
                    byte d3 = (byte)((int)((t - d1 * 10 - d2) * 10));
                    CommObj.Send(new byte[] { addr, 1, 10 }, 0);
                    CommObj.Send(new byte[] { addr, 2, (byte)(d2 + 128) }, 0);
                    CommObj.Send(new byte[] { addr, 3, d3 }, 0);
                }
                else
                {
                    byte d1 = (byte)((int)B2_LED_Temperature / 10);
                    byte d2 = (byte)(((int)B2_LED_Temperature - d1 * 10));
                    byte d3 = (byte)((int)((B2_LED_Temperature - d1 * 10 - d2) * 10));
                    CommObj.Send(new byte[] { addr, 1, d1 }, 0);
                    CommObj.Send(new byte[] { addr, 2, (byte)(d2 + 128) }, 0);
                    CommObj.Send(new byte[] { addr, 3, d3 }, 0);
                }

            }
            catch
            {
                valuePair = string.Format("Fail set LED");
            }
            return valuePair;
        }

        /// <summary>
        /// Setup LED value, 
        /// </summary>
        /// <param name="_addr"></param>
        /// <returns></returns>
        private string SetB2_LED_RGB(byte _addr)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                byte[] value = CommObj.Send(new byte[] { addr, 0x00, 0x00 }, 0);
                //value = CommObj.Send(new byte[] { addr, 0x08, 0xAA }, 0);

                CommObj.Send(new byte[] { addr, 2, B2_LED_R }, 0);
                CommObj.Send(new byte[] { addr, 3, B2_LED_G }, 0);
                CommObj.Send(new byte[] { addr, 4, B2_LED_B }, 0);

                value = CommObj.Send(new byte[] { addr, 0x00, 0x00 }, 0);
                value = CommObj.Send(new byte[] { addr, 0x08, 0xAA }, 0);

            }
            catch
            {
                valuePair = string.Format("Fail set LED");
            }
            return valuePair;
        }


        /// <summary>
        /// Setup LED value, 
        /// </summary>
        /// <param name="_addr"></param>
        /// <returns></returns>
        private string SetB1_LED_Temperatue(byte _addr)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);

                // initial
                CommObj.Send(new byte[] { addr, 9, 7 }, 0);
                CommObj.Send(new byte[] { addr, 0xa, 0xff }, 0);
                CommObj.Send(new byte[] { addr, 0xc, 0x01 }, 0);
                CommObj.Send(new byte[] { addr, 0xe, 0 }, 0);
                CommObj.Send(new byte[] { addr, 0xB, 3 }, 0);

                //CommObj.Send(new byte[] { addr, 0x1, 0 }, 0);
                //CommObj.Send(new byte[] { addr, 0x2, 0 }, 0);
                //CommObj.Send(new byte[] { addr, 0x3, 0 }, 0);

                byte d1 = (byte)((int)B1_LED_Temperature / 10);
                byte d2 = (byte)(((int)B1_LED_Temperature - d1 * 10));
                byte d3 = (byte)((int)((B1_LED_Temperature - d1 * 10- d2) * 10));
                CommObj.Send(new byte[] { addr, 1, d1 }, 0);
                CommObj.Send(new byte[] { addr, 2, (byte)(d2 + 128) }, 0);
                CommObj.Send(new byte[] { addr, 3, d3 }, 0);

            }
            catch
            {
                valuePair = string.Format("Fail set LED");
            }
            return valuePair;
        }

        /// <summary>
        /// Setup LED value, 
        /// </summary>
        /// <param name="_addr"></param>
        /// <returns></returns>
        private string SetB1_LED_RGB(byte _addr)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                byte[] value = CommObj.Send(new byte[] { addr, 0x00, 0x00 }, 0);
                //value = CommObj.Send(new byte[] { addr, 0x08, 0xAA }, 0);

                CommObj.Send(new byte[] { addr, 2, B1_LED_R}, 0);
                CommObj.Send(new byte[] { addr, 3, B1_LED_G }, 0);
                CommObj.Send(new byte[] { addr, 4, B1_LED_B }, 0);

                value = CommObj.Send(new byte[] { addr, 0x00, 0x00 }, 0);
                value = CommObj.Send(new byte[] { addr, 0x08, 0xAA }, 0);

            }
            catch
            {
                valuePair = string.Format("Fail set LED");
            }
            return valuePair;
        }


        /// <summary>
        /// template
        /// </summary>
        /// <param name="_addr"></param>
        /// <returns></returns>
        private string ReadEnergyMeter(byte _addr)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
                CommObj.Send(new byte[] { addr, 14 }, 0);
                Thread.Sleep(10);
                byte[] value = CommObj.Send(new byte[] { addr}, 3);
                if (value != null)
                {
                    B3_current = (double)(value[0] * 0x10000 + value[1] * 0x100 + value[2]) / 1000.0;
                }
                else
                {
                    throw new Exception("Fail to Read Current");
                }

                value = CommObj.Send(new byte[] { addr, 44 }, 0);
                Thread.Sleep(10);
                value = CommObj.Send(new byte[] { addr}, 3);
                if (value != null)
                {
                    B3_Voltage  = (double)(value[0] * 0x10000 + value[1] * 0x100 + value[2]) / 1000.0;
                }
                else
                {
                    throw new Exception("Fail to Read Voltage");
                }

                value = CommObj.Send(new byte[] { addr, 154 }, 0);
                value = CommObj.Send(new byte[] { addr}, 2);
                if (value != null)
                {
                    B3_Power = (double)(value[0] * 0x100 + value[1]);
                }
                else
                {
                    throw new Exception("Fail to Read Watt");
                }

                value = CommObj.Send(new byte[] { addr, 70 }, 0);
                value = CommObj.Send(new byte[] { addr}, 3);
                if (value != null)
                {
                    B3_Energy = (double)(value[0] * 0x10000 + value[1] * 0x100 + value[2]) / 1000.0;
                }
                else
                {
                    throw new Exception("Fail to Read Energy");
                }
                valuePair = string.Format("Voltage {0:F1} V Current {1:F1} A Power {2:F1} Watt, Energy {3:F1} Kwh", B3_Voltage, B3_current, B3_Power, B3_Energy);


            }
            catch
            {
                valuePair = string.Format("Fail Read Energy Sensor");
            }
            return valuePair;
        }

        /// <summary>
        /// template
        /// </summary>
        /// <param name="_addr"></param>
        /// <returns></returns>
        private string ReadXXX(byte _addr)
        {
            string valuePair = string.Empty;
            try
            {
                byte addr = (byte)(_addr * 2);
            }
            catch
            {
                valuePair = string.Format("Fail Read XXX");
            }
            return valuePair;
        }

        /// <summary>
        /// load config from file
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static  KentProj Load(string filename)
        {
            KentProj obj = null;
            if (!File.Exists(filename))
            {
                return obj;
            }

            try
            {
                XmlReader reader = XmlReader.Create(filename);
                obj = Load(reader);
                reader.Close();

            }
            catch (Exception e)
            {
                string exStr = string.Format("\n -------Load from XML File {0} Exception-------\n{1}",
                                        filename, e.ToString());
                obj = null;
            }
            return obj;
        }

        public static KentProj Load(XmlReader reader)
        {
            KentProj obj = null;
            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(KentProj));
                obj = (KentProj)serializer.Deserialize(reader);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
            return obj;
        }

        /// <summary>
        /// Save config to file
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public bool Save(string filename)
        {
            bool bSave = false;
            if (filename.Length == 0)
            {
                return bSave;
            }
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.IndentChars = "\t";
            settings.OmitXmlDeclaration = true;     //omit declaration
            settings.NewLineOnAttributes = true;

            try
            {
                XmlWriter writer = XmlWriter.Create(filename, settings);
                bSave = Save(writer);
                writer.Flush();
                writer.Close();
            }
            catch (Exception e)
            {
                string exStr = String.Format("\n -------Save to XML File {0} Exception-------\n{1}",
                                        filename, e.ToString());
                Debug.WriteLine(exStr);
                bSave = false;
            }

            return bSave;
        }

        public bool Save(XmlWriter writer)
        {
            bool bSave = false;
            try
            {
                XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
                ns.Add(String.Empty, String.Empty);
                XmlSerializer serializer = new XmlSerializer(typeof(KentProj));
                serializer.Serialize(writer, this, ns);

            }
            catch (Exception ex)
            {
                bSave = false;
                Debug.WriteLine(ex.ToString());
            }
            return bSave;
        }

        public void SaveToText(string filename)
        {
            StreamWriter file = new StreamWriter(filename);
            file.WriteLine("ID:{0}", ID);
            file.WriteLine("Temp1:{0:F2}", B2_LED_Temperature);
            file.WriteLine("Temp2:{0:F2}", B1_LED_Temperature);
            file.WriteLine("Hum:{0:F2}", B0_SHT25_Humidity);
            file.WriteLine("Say:Fridge");
            file.WriteLine("Status:Fridge is Running");
            file.WriteLine("Url:app.powerbi.com/view?r=eyJrIjoiNTFlOWIzYzItOWJiZi00MmE1LTk4ZWQtMDdjYTVlY2Q4MGEzIiwidCI6ImRmZWUzMWM0LTRiMWQtNGZkMi04YzE0LWNlYjk3YTYyZWYyMiJ9");
            file.Close();
            ID++;
        }


        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("----begin-----").AppendLine();
            sb.AppendFormat("B0_SHT25_Humidity={0:F2}", B0_SHT25_Humidity).AppendLine();
            sb.AppendFormat("B0_SHT25_Temperature={0:F2}", B0_SHT25_Temperature).AppendLine();

            sb.AppendFormat("B0_BH1745_AmbientLight_R={0}", B0_BH1745_AmbientLight_R).AppendLine();
            sb.AppendFormat("B0_BH1745_AmbientLight_G={0}", B0_BH1745_AmbientLight_G).AppendLine();
            sb.AppendFormat("B0_BH1745_AmbientLight_B={0}", B0_BH1745_AmbientLight_B).AppendLine();
            sb.AppendFormat("B0_BH1745_AmbientLight_C={0}", B0_BH1745_AmbientLight_C).AppendLine();

            sb.AppendFormat("B0_HP203B_Pressure={0:F2}", B0_HP203B_Pressure).AppendLine();
            sb.AppendFormat("B0_HP203B_Temperature={0:F2}", B0_HP203B_Temperature).AppendLine();

            sb.AppendFormat("B0_TMD26721_Promimity={0}", B0_TMD26721_Promimity).AppendLine();
            sb.AppendFormat("B0_A3G4250DTR_Gyro_X={0}", B0_A3G4250DTR_Gyro_X).AppendLine();
            sb.AppendFormat("B0_A3G4250DTR_Gyro_Y={0}", B0_A3G4250DTR_Gyro_Y).AppendLine();
            sb.AppendFormat("B0_A3G4250DTR_Gyro_Z={0}", B0_A3G4250DTR_Gyro_Z).AppendLine();

            sb.AppendFormat("B0_LPG_MQ4_Gas={0:F2}", B0_LPG_MQ4_Gas).AppendLine();
            sb.AppendFormat("B0_LPG_MQ9_Monoxide={0:F2}", B0_LPG_MQ9_Monoxide).AppendLine();

            sb.AppendFormat("B1_MCP9803_FRIDG_TOP_LEFT={0:F2}", B1_MCP9803_FRIDG_TOP_LEFT).AppendLine();
            sb.AppendFormat("B1_MCP9803_FRIDG_TOP_RIGHT={0:F2}", B1_MCP9803_FRIDG_TOP_RIGHT).AppendLine();
            sb.AppendFormat("B1_MCP9803_FRIDG_BOTTOM_LEFT={0:F2}", B1_MCP9803_FRIDG_BOTTOM_LEFT).AppendLine();
            sb.AppendFormat("B1_MCP9803_FRIDG_BOTTOM_RIGHT={0:F2}", B1_MCP9803_FRIDG_BOTTOM_RIGHT).AppendLine();

            sb.AppendFormat("B1_SHT25_Humidity={0:F2}", B1_SHT25_Humidity).AppendLine();
            sb.AppendFormat("B1_SHT25_Temperature={0:F2}", B1_SHT25_Temperature).AppendLine();

            sb.AppendFormat("B1_LED_Temperature={0:F2}", B1_LED_Temperature).AppendLine();

            sb.AppendFormat("B1_LED_R={0}", B1_LED_R).AppendLine();
            sb.AppendFormat("B1_LED_G={0}", B1_LED_G).AppendLine();
            sb.AppendFormat("B1_LED_B={0}", B1_LED_B).AppendLine();

            sb.AppendFormat("B2_MCP9803_FRZR_LEFT={0:F2}", B2_MCP9803_FRZR_LEFT).AppendLine();
            sb.AppendFormat("B2_MCP9803_FRZR_RIGHT={0:F2}", B2_MCP9803_FRZR_RIGHT).AppendLine();

            sb.AppendFormat("B2_LED_Temperature={0:F2}", B2_LED_Temperature).AppendLine();

            sb.AppendFormat("B2_LED_R={0}", B2_LED_R).AppendLine();
            sb.AppendFormat("B2_LED_G={0}", B2_LED_G).AppendLine();
            sb.AppendFormat("B2_LED_B={0}", B2_LED_B).AppendLine();

            sb.AppendFormat("B2_BuzzerOn={0}", B2_BuzzerOn).AppendLine();

            sb.AppendFormat("B3_current={0:F2}", B3_current).AppendLine();
            sb.AppendFormat("B3_Voltage={0:F2}", B3_Voltage).AppendLine();
            sb.AppendFormat("B3_Power={0:F2}", B3_Power).AppendLine();
            sb.AppendFormat("B3_Energy={0:F2}", B3_Energy).AppendLine();

            sb.AppendFormat("B3_GPIO_Door1={0}", B3_GPIO_Door1).AppendLine();
            sb.AppendFormat("B3_GPIO_Door2={0}", B3_GPIO_Door2).AppendLine();

            sb.AppendFormat("B3_GPIO_Relay={0}", B3_GPIO_Relay).AppendLine();

            sb.AppendFormat("B3_ADC121_Sound_Sensor={0:F2}", B3_ADC121_Sound_Sensor).AppendLine();

            sb.AppendFormat("B4_MCP9600_Compressor_High_Side={0:F2}", B4_MCP9600_Compressor_High_Side).AppendLine();
            sb.AppendFormat("B4_MCP9600_Compressor_Low_Side={0:F2}", B4_MCP9600_Compressor_Low_Side).AppendLine();
            sb.AppendFormat("B4_MCP9600_Evaporation_Vavle_Low_Side={0:F2}", B4_MCP9600_FRZR_Temp).AppendLine();

            sb.AppendFormat("B0_Read_Success={0}", B0_Read_Success).AppendLine();
            sb.AppendFormat("B1_Read_Success={0}", B1_Read_Success).AppendLine();
            sb.AppendFormat("B2_Read_Success={0}", B2_Read_Success).AppendLine();
            sb.AppendFormat("B3_Read_Success={0}", B3_Read_Success).AppendLine();
            sb.AppendFormat("B4_Read_Success={0}", B4_Read_Success).AppendLine();

            sb.AppendLine("----end-----").AppendLine();
            return sb.ToString();

        }




    }
}
