using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetSDKCS;
using System.Runtime.InteropServices;

namespace NetClient
{
    public class LogClient : BaseClient
    {
        private int m_CurrentLogNumber = 0;
        private EM_LOG_QUERY_TYPE m_CurrentType;
        private DateTime m_CurrentStartTime;
        private DateTime m_CurrentEndTime;

        private int m_PageLine = 0;
        /// <summary>
        /// one page show logs number
        /// </summary>
        public int PageviewNumber
        {
            get { return m_PageLine; }
            set { m_PageLine = value; }
        }

        private bool m_IsPrePage = false;
        /// <summary>
        /// prepage is enable or not.
        /// </summary>
        public bool IsPrePage
        {
            get { return m_IsPrePage; }
        }

        private bool m_IsNextPage = false;
        /// <summary>
        /// nextpage is enable or not.
        /// </summary>
        public bool IsNextPage
        {
            get { return m_IsNextPage; }
        }

        public LogClient()
        {
            //set wait time 10000ms
            WaitTime = 10000;
        }

        public override void Logout()
        {
            base.Logout();
            m_IsPrePage = false;
            m_IsNextPage = false;
        }

        public override void Dispose()
        {
            Logout();
        }

        /// <summary>
        /// query logs by start time to end time and log type.
        /// </summary>
        /// <param name="type">log type</param>
        /// <param name="startTime">start time</param>
        /// <param name="endTime">end time</param>
        /// <returns>logs</returns>
        public List<NET_DEVICE_LOG_ITEM_EX> Query(EM_LOG_QUERY_TYPE type, DateTime startTime, DateTime endTime)
        {
            if (LoginID == IntPtr.Zero || m_PageLine == 0)
            {
                return null;
            }
            if (startTime >= endTime)
            {
                return null;
            }
            m_IsPrePage = false;
            m_CurrentType = type;
            m_CurrentStartTime = startTime;
            m_CurrentEndTime = endTime;
            List<NET_DEVICE_LOG_ITEM_EX> result = new List<NET_DEVICE_LOG_ITEM_EX>();
            NET_QUERY_DEVICE_LOG param = new NET_QUERY_DEVICE_LOG();
            param.emLogType = type;
            param.stuStartTime = startTime;
            param.stuEndTime = endTime;
            param.nChannelID = 0; //all
            param.nStartNum = 0;
            param.nEndNum = m_PageLine - 1;
            try
            {
                QueryDeviceLog(LoginID, param, ref result);
            }
            catch (NetSDKCS.NETClientExcetion ex)
            {
                throw new NETClientExcetion(ex.ErrorCode, ex.Message);
            }
            if (result.Count == 0)
            {
                return null;
            }
            if (result.Count == m_PageLine)
            {
                m_CurrentLogNumber = param.nEndNum;
                try
                {
                    m_IsNextPage = CheckIsEnable();
                }
                catch (NETClientExcetion ex)
                {
                    throw ex;
                }
                return result;
            }
            while (true)
            {
                m_CurrentLogNumber = result.Count - 1;
                List<NET_DEVICE_LOG_ITEM_EX> ret = new List<NET_DEVICE_LOG_ITEM_EX>();
                NET_QUERY_DEVICE_LOG paramLog = new NET_QUERY_DEVICE_LOG();
                paramLog.emLogType = type;
                paramLog.stuStartTime = startTime;
                paramLog.stuEndTime = endTime;
                paramLog.nChannelID = 0; //all
                paramLog.nStartNum = m_CurrentLogNumber + 1;
                paramLog.nEndNum = m_PageLine - 1;
                try
                {
                    QueryDeviceLog(LoginID, paramLog, ref ret);
                }
                catch (NetSDKCS.NETClientExcetion ex)
                {
                    throw new NETClientExcetion(ex.ErrorCode, ex.Message);
                }
                if (ret.Count == 0)
                {
                    break;
                }
                if (ret.Count + result.Count == m_PageLine)
                {
                    result.AddRange(ret);
                    break;
                }
                result.AddRange(ret);
            }
            m_CurrentLogNumber = result.Count;
            try
            {
                m_IsNextPage = CheckIsEnable();
            }
            catch (NETClientExcetion ex)
            {
                throw ex;
            }
            return result;
        }

        /// <summary>
        /// query prepage logs 
        /// </summary>
        /// <returns>logs</returns>
        public List<NET_DEVICE_LOG_ITEM_EX> PrePage()
        {
            if (LoginID == IntPtr.Zero || m_PageLine == 0)
            {
                return null;
            }
            int startNum = (m_CurrentLogNumber / m_PageLine) * m_PageLine - m_PageLine;
            int endNum = startNum + m_PageLine - 1;
            List<NET_DEVICE_LOG_ITEM_EX> result = new List<NET_DEVICE_LOG_ITEM_EX>();
            try
            {
                result = GetLog(startNum, endNum, false);
            }
            catch (NETClientExcetion ex)
            {
                throw ex;
            }
            if ((m_CurrentLogNumber + 1 - m_PageLine) <= 0)
            {
                m_IsPrePage = false;
                m_IsNextPage = true;
            }
            else
            {
                m_IsPrePage = true;
                m_IsNextPage = true;
            }
            return result;
        }

        /// <summary>
        /// query nextpage logs.
        /// </summary>
        /// <returns>logs</returns>
        public List<NET_DEVICE_LOG_ITEM_EX> NextPage()
        {
            if (LoginID == IntPtr.Zero || m_PageLine == 0)
            {
                return null;
            }
            int startNum = m_CurrentLogNumber + 1;
            int endNum = startNum + m_PageLine - 1;
            List<NET_DEVICE_LOG_ITEM_EX> result = new List<NET_DEVICE_LOG_ITEM_EX>();
            try
            {
                result = GetLog(startNum, endNum, true);
                m_IsNextPage = CheckIsEnable();
                m_IsPrePage = true;
            }
            catch (NETClientExcetion ex)
            {
                throw ex;
            }
            return result;
        }

        //check is nextpage enable
        private bool CheckIsEnable()
        {
            List<NET_DEVICE_LOG_ITEM_EX> result = new List<NET_DEVICE_LOG_ITEM_EX>();
            NET_QUERY_DEVICE_LOG param = new NET_QUERY_DEVICE_LOG();
            param.emLogType = m_CurrentType;
            param.stuStartTime = m_CurrentStartTime;
            param.stuEndTime = m_CurrentEndTime;
            param.nChannelID = 0; //all
            param.nStartNum = m_CurrentLogNumber + 1;
            param.nEndNum = param.nStartNum + m_PageLine - 1;
            try
            {
                QueryDeviceLog(LoginID, param, ref result);
            }
            catch (NetSDKCS.NETClientExcetion ex)
            {
                throw new NETClientExcetion(ex.ErrorCode, ex.Message);
            }
            if (result.Count == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        //get log by start number to end number and is nextpage or prepage.
        private List<NET_DEVICE_LOG_ITEM_EX> GetLog(int startNum, int endNum, bool isNext)
        {
            List<NET_DEVICE_LOG_ITEM_EX> result = new List<NET_DEVICE_LOG_ITEM_EX>();
            NET_QUERY_DEVICE_LOG param = new NET_QUERY_DEVICE_LOG();
            param.emLogType = m_CurrentType;
            param.stuStartTime = m_CurrentStartTime;
            param.stuEndTime = m_CurrentEndTime;
            param.nChannelID = 0; //all
            param.nStartNum = startNum;
            param.nEndNum = endNum;
            try
            {
                QueryDeviceLog(LoginID, param, ref result);
            }
            catch (NetSDKCS.NETClientExcetion ex)
            {
                throw new NETClientExcetion(ex.ErrorCode, ex.Message);
            }
            if (result.Count == 0)
            {
                return null;
            }
            if (result.Count == m_PageLine)
            {
                if (isNext)
                {
                    m_CurrentLogNumber += result.Count;
                }
                else
                {
                    m_CurrentLogNumber = endNum;
                }
                return result;
            }
            while (true)
            {
                int currentCount = result.Count + startNum;
                List<NET_DEVICE_LOG_ITEM_EX> ret = new List<NET_DEVICE_LOG_ITEM_EX>();
                NET_QUERY_DEVICE_LOG paramLog = new NET_QUERY_DEVICE_LOG();
                paramLog.emLogType = m_CurrentType;
                paramLog.stuStartTime = m_CurrentStartTime;
                paramLog.stuEndTime = m_CurrentEndTime;
                paramLog.nChannelID = 0; //all
                paramLog.nStartNum = currentCount;
                paramLog.nEndNum = endNum;
                try
                {
                    QueryDeviceLog(LoginID, paramLog, ref ret);
                }
                catch (NetSDKCS.NETClientExcetion ex)
                {
                    throw new NETClientExcetion(ex.ErrorCode, ex.Message);
                }
                if (ret.Count == 0)
                {
                    break;
                }
                if (ret.Count + result.Count == m_PageLine)
                {
                    result.AddRange(ret);
                    break;
                }
                result.AddRange(ret);
            }
            if (isNext)
            {
                m_CurrentLogNumber += result.Count;
            }
            else
            {
                m_CurrentLogNumber = startNum + result.Count - 1;
            }
            return result;
        }

        //query device logs.
        private void QueryDeviceLog(IntPtr lLoginID, NET_QUERY_DEVICE_LOG pQueryParam, ref List<NET_DEVICE_LOG_ITEM_EX> logList)
        {
            NetSDKCS.NET_QUERY_DEVICE_LOG_PARAM param = new NetSDKCS.NET_QUERY_DEVICE_LOG_PARAM();
            param.emLogType = (NetSDKCS.EM_LOG_QUERY_TYPE)pQueryParam.emLogType;
            param.stuStartTime = NET_TIME.FromDateTime(pQueryParam.stuStartTime);
            param.stuEndTime = NET_TIME.FromDateTime(pQueryParam.stuEndTime);
            param.nStartNum = pQueryParam.nStartNum;
            param.nEndNum = pQueryParam.nEndNum;
            param.nLogStuType = 1;
            param.reserved = new byte[3];
            param.nChannelID = pQueryParam.nChannelID;
            param.bReserved = new byte[40];
            int nLogBufferLen = param.nEndNum - param.nStartNum + 1;
            IntPtr pLogBuffer = Marshal.AllocHGlobal(nLogBufferLen * Marshal.SizeOf(typeof(NET_DEVICE_LOG_ITEM_EX)));
            int pRecLogNum = 0;
            try
            {
                NETClient.QueryDeviceLog(lLoginID, ref param, pLogBuffer, nLogBufferLen * Marshal.SizeOf(typeof(NET_DEVICE_LOG_ITEM_EX)), ref pRecLogNum, (int)WaitTime);
                if (pRecLogNum != 0)
                {
                    int count = nLogBufferLen == pRecLogNum ? nLogBufferLen : pRecLogNum;
                    NET_DEVICE_LOG_ITEM_EX[] buffer = new NET_DEVICE_LOG_ITEM_EX[count];
                    for (int i = 0; i < count; i++)
                    {
                        buffer[i] = (NET_DEVICE_LOG_ITEM_EX)Marshal.PtrToStructure((pLogBuffer + Marshal.SizeOf(typeof(NET_DEVICE_LOG_ITEM_EX)) * i), typeof(NET_DEVICE_LOG_ITEM_EX));
                    }
                    logList = buffer.ToList<NET_DEVICE_LOG_ITEM_EX>();
                }
            }
            catch (NetSDKCS.NETClientExcetion ex)
            {
                throw new NETClientExcetion(ex.ErrorCode, ex.Message);
            }
            finally
            {
                Marshal.FreeHGlobal(pLogBuffer);
            }
        }
    }

    //query device log struct
    struct NET_QUERY_DEVICE_LOG
    {
        public EM_LOG_QUERY_TYPE emLogType;				                // Searched log type
        public DateTime stuStartTime;			                        // The searched log start time
        public DateTime stuEndTime;				                        // The searched log end time. 
        public int nStartNum;				                            // The search begins from which log in one period. It shall begin with 0 if it is the first time search.
        public int nEndNum;				                                // The ended log serial number in one search,the max returning number is 1024 
        public uint nChannelID;                                         // Channel no. 0:Compatible with previous all channel numbers. The channel No. begins with 1.1: The first channel.
    }

    //device log information struct
    public struct NET_DEVICE_LOG_ITEM_EX
    {
        public int nLogType;				                            // Log type 
        public NETDEVTIME stuOperateTime;			                    // Date
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
        public string szOperator; 		                                // Operator
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
        public byte[] bReserved;                                        // Reserved
        public byte bUnionType;				                            // union structure type,0:szLogContext;1:stuOldLog
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public byte[] szLogContext;                                     // 0:Log content,1:Old log structure NET_OLDLOG
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string szOperation;                                      // Detail operation
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4 * 1024)]
        public string szDetailContext;                                  // DetailContext
    }

    // The time definition in the log information
    [StructLayout(LayoutKind.Explicit, Size = 4)]
    public struct NETDEVTIME
    {
        [FieldOffset(0)]
        private uint _value;

        /// <summary>
        /// 6bit
        /// </summary>
        public uint Second
        {
            set
            {
                _value = (value & 0x003f) | (_value & 0xffffffc0);
            }
            get
            {
                return _value & 0x003f;
            }
        }

        /// <summary>
        /// 6bit
        /// </summary>
        public uint Minute
        {
            set
            {
                _value = ((value & 0x003f) << 6) | (_value & 0xfffff03f);
            }
            get
            {
                return (_value >> 6) & 0x003f;
            }
        }

        /// <summary>
        /// 5bit
        /// </summary>
        public uint Hour
        {
            set
            {
                _value = ((value & 0x001f) << 12) | (_value & 0xfffe0fff);
            }
            get
            {
                return (_value >> 12) & 0x001f;
            }
        }

        /// <summary>
        /// 5bit
        /// </summary>
        public uint Day
        {
            set
            {
                _value = ((value & 0x001f) << 17) | (_value & 0xffc3ffff);
            }
            get
            {
                return (_value >> 17) & 0x001f;
            }
        }

        /// <summary>
        /// 4bit
        /// </summary>
        public uint Month
        {
            set
            {
                _value = ((value & 0x000f) << 22) | (_value & 0xfc3fffff);
            }
            get
            {
                return (_value >> 22) & 0x000f;
            }
        }

        /// <summary>
        /// 6bit 2000-2063
        /// </summary>
        public uint Year
        {
            set
            {
                _value = (((value - 2000) & 0x003f) << 26) | (_value & 0x3ffffff);
            }
            get
            {
                return ((_value >> 26) & 0x003f) + 2000;
            }
        }

        public override string ToString()
        {
            return string.Format("{0}-{1}-{2} {3}:{4}:{5}", Year.ToString("D4"), Month.ToString("D2"), Day.ToString("D2"), Hour.ToString("D2"), Minute.ToString("D2"), Second.ToString("D2"));
        }
    }

    // enum query log type
    public enum EM_LOG_QUERY_TYPE
    {
        ALL = 0,								                            // All logs
        SYSTEM,								                                // System logs 
        CONFIG,								                                // Configuration logs 
        STORAGE,								                            // Storage logs
        ALARM,								                                // Alarm logs 
        RECORD,								                                // Record related
        ACCOUNT,								                            // Account related
        CLEAR,								                                // Clear log 
        PLAYBACK,								                            // Playback related 
        MANAGER                                                             // Concerning the front-end management and running
    }

    // enum log type
    public enum EM_LOG_TYPE
    {
        REBOOT = 0x0000,						                            // Device reboot 
        SHUT,								                                // Shut down device 
        REPORTSTOP,                                                         // Report stop
        REPORTSTART,                                                        // Rreport start
        UPGRADE = 0x0004,				                                    // Device Upgrade
        SYSTIME_UPDATE = 0x0005,                                            // system time update
        GPS_TIME_UPDATE = 0x0006,			                                // GPS time update
        AUDIO_TALKBACK,	  					                                // Voice intercom, true representative open, false on behalf of the closed
        COMM_ADAPTER,						                                // Transparent transmission, true representative open, false on behalf of the closed
        NET_TIMING,                                                         // Net sync
        TYPE_NR,                                                            // NR
        CONFSAVE = 0x0100,					                                // Save configuration 
        CONFLOAD,							                                // Read configuration 
        FSERROR = 0x0200,					                                // File system error
        HDD_WERR,							                                // HDD write error 
        HDD_RERR,							                                // HDD read error
        HDD_TYPE,							                                // Set HDD type 
        HDD_FORMAT,							                                // Format HDD
        HDD_NOSPACE,							                            // Current working HDD space is not sufficient
        HDD_TYPE_RW,							                            // Set HDD type as read-write 
        HDD_TYPE_RO,							                            // Set HDD type as read-only
        HDD_TYPE_RE,							                            // Set HDD type as redundant 
        HDD_TYPE_SS,							                            // Set HDD type as snapshot
        HDD_NONE,							                                // No HDD
        HDD_NOWORKHDD,						                                // No work HDD
        HDD_TYPE_BK,							                            // Set HDD type to backup HDD
        HDD_TYPE_REVERSE,					                                // Set HDD type to reserve subarea
        HDD_START_INFO = 0x20e,                                             // note the boot-strap's hard disk info
        HDD_WORKING_DISK,                                                   // note the disk number after the disk change
        HDD_OTHER_ERROR,                                                    // note other errors of disk
        HDD_SLIGHT_ERR,						                                // there has some little errors on disk
        HDD_SERIOUS_ERR,                                                    // there has some serious errors on disk
        HDD_NOSPACE_END,                                                    // the end of the alarm that current disk has no space left 
        HDD_TYPE_RAID_CONTROL,                                              // Raid control
        HDD_TEMPERATURE_HIGH,				                                // excess temperature
        HDD_TEMPERATURE_LOW,					                            // lower die temperature
        HDD_ESATA_REMOVE,					                                // remove eSATA
        ALM_IN = 0x0300,						                            // External alarm begin 
        NETALM_IN,							                                // Network alarm input 
        ALM_END = 0x0302,					                                // External input alarm stop 
        LOSS_IN,								                            // Video loss alarm begin 
        LOSS_END,							                                // Video loss alarm stop
        MOTION_IN,							                                // Motion detection alarm begin 
        MOTION_END,							                                // Motion detection alarm stop 
        ALM_BOSHI,							                                // Annunciator alarm input 
        NET_ABORT = 0x0308,					                                // Network disconnected 
        NET_ABORT_RESUME,					                                // Network connection restore 
        CODER_BREAKDOWN,						                            // Encoder error
        CODER_BREAKDOWN_RESUME,				                                // Encoder error restore 
        BLIND_IN,							                                // Camera masking 
        BLIND_END,							                                // Restore camera masking 
        ALM_TEMP_HIGH,						                                // High temperature 
        ALM_VOLTAGE_LOW,						                            // Low voltage
        ALM_BATTERY_LOW,						                            // Battery capacity is not sufficient 
        ALM_ACC_BREAK,						                                // ACC power off 
        ALM_ACC_RES,                                                        // ACC res
        GPS_SIGNAL_LOST,						                            // GPS signal lost
        GPS_SIGNAL_RESUME,					                                // GPS signal resume
        LOG_3G_SIGNAL_LOST,						                            // 3G signal lost
        LOG_3G_SIGNAL_RESUME,					                            // 3G signal resume
        ALM_IPC_IN,							                                // IPC external alarms
        ALM_IPC_END,							                            // IPC external alarms recovery
        ALM_DIS_IN,							                                // Broken network alarm
        ALM_DIS_END,							                            // Broken network alarm recovery
        ALM_UPS_IN, 				                                        // UPS alarm 
        ALM_UPS_END, 				                                        // UPS alarm resume 
        ALM_NAS_IN,				                                            // NAS server abnormal alarm 
        ALM_NAS_END,				                                        // NAS server abnormal alarm resume 
        ALM_REDUNDANT_POWER_IN,                                             // Redundant power alarm 
        ALM_REDUNDANT_POWER_END,                                            // Redundant alarm resume  
        ALM_RECORD_FAILED_IN,				                                // Record failure alarm 
        ALM_RECORD_FAILED_END,			                                    // Record failure alarm resume 
        ALM_VGEXCEPT_IN,				                                    // Storage pool abnormal alarm 
        ALM_VGEXCEPT_END,				                                    // Storage abnormal alarm resume 		
        ALM_FANSPEED_IN,			                                        // Fan alarm starts
        ALM_FANSPEED_END,			                                        // Fan alarm stops 
        ALM_DROP_FRAME_IN,			                                        // Frame loss alarm starts 
        ALM_DROP_FRAME_END,			                                        // Frame loss alarm stops
        ALM_DISK_STATE_CHECK,		                                        // HDD pre-check tour alarm event log type 
        ALARM_COAXIAL_SMOKE,		                                        // HDCVI smoke alarm event
        ALARM_COAXIAL_TEMP_HIGH,	                                        // HDCVI temperature alarm event 
        ALARM_COAXIAL_ALM_IN,		                                        // HDCVI external alarm event 
        INFRAREDALM_IN = 0x03a0,				                            // Wireless alarm begin 
        INFRAREDALM_END,						                            // Wireless alarm end 
        IPCONFLICT,							                                // IP conflict 
        IPCONFLICT_RESUME,					                                // IP restore
        SDPLUG_IN,							                                // SD Card insert
        SDPLUG_OUT,							                                // SD Card Pull-out
        NET_PORT_BIND_FAILED,				                                // Failed to bind port
        HDD_BEEP_RESET,                                                     // Hard disk error beep reset 
        MAC_CONFLICT,                                                       // MAC conflict
        MAC_CONFLICT_RESUME,                                                // MAC conflict resume
        ALARM_OUT,							                                // alarm out
        ALM_RAID_STAT_EVENT,                                                // RAID state event    
        ABLAZE_ON,				                                            // Fire alarm, smoker or high temperature
        ABLAZE_OFF,			                                                // Fire alarm reset 
        INTELLI_ALARM_PLUSE,					                            // Intelligence pulse alarm
        INTELLI_ALARM_IN,					                                // Intelligence alarm start
        INTELLI_ALARM_END,					                                // Intelligence alarm end
        LOG_3G_SIGNAL_SCAN,						                            // 3G signal scan
        GPS_SIGNAL_SCAN,						                            // GPS signal scan
        AUTOMATIC_RECORD = 0x0400,			                                // Auto record 
        MANUAL_RECORD = 0x0401,				                                // Manual record 
        CLOSED_RECORD,						                                // Stop record 
        LOGIN = 0x0500,						                                // Log in 
        LOGOUT,								                                // Log off 
        ADD_USER,							                                // Add user
        DELETE_USER,							                            // Delete user
        MODIFY_USER,							                            // Modify user 
        ADD_GROUP,							                                // Add user group 
        DELETE_GROUP,						                                // Delete user group 
        MODIFY_GROUP,						                                // Modify user group 
        NET_LOGIN = 0x0508,					                                // Network Login
        MODIFY_PASSWORD,						                            // Modify password
        CLEAR = 0x0600,						                                // Clear log 
        SEARCHLOG,							                                // Search log 
        SEARCH = 0x0700,						                            // Search record 
        DOWNLOAD,							                                // Record download
        PLAYBACK,							                                // Record playback
        BACKUP,								                                // Backup recorded file 
        BACKUPERROR,							                            // Failed to backup recorded file
        BACK_UPRT,							                                // Real-time backup, that is, copy CD
        BACKUPCLONE,							                            // CD copy
        DISK_CHANGED,						                                // Manual changed
        IMAGEPLAYBACK,						                                // Image playback
        LOCKFILE,							                                // Lock the video
        UNLOCKFILE,							                                // Unlock the video
        ATMPOS,								                                // Add log superposition of ATM card number
        PLAY_PAUSE,								                            // Pause
        PLAY_START,								                            // Start
        PLAY_STOP,								                            // Stop
        PLAY_BACK,								                            // Back
        PLAY_FAST,								                            // Fast
        PLAY_SLOW,								                            // Slow
        SMART_SEARCH,							                            // Search
        RECORD_SNAP,							                            // Snap
        ADD_TAG,								                            // Add tag
        DEL_TAG,								                            // Delete tag
        USB_IN,									                            // USB connected
        USB_OUT,								                            // USB disconnected
        BACKUP_FILE,							                            // Backup file
        BACKUP_LOG,								                            // Backup log
        BACKUP_CONFIG,							                            // Backup config
        TIME_UPDATE = 0x0800,                                               // Time update
        REMOTE_STATE = 0x0850,                                              // remote diary 
        USER_DEFINE = 0x0900,                                               // User define
    }
}
