 //#define data

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text.RegularExpressions;
using System.Collections;
using GcDevicePc.Common;
using System.Runtime.InteropServices;
using GcDevicePc.IniParam;
using GcDevicePc.GCBuffer;
using System.Diagnostics;

namespace GcDevicePc.ProThread
{   
    class GcDataTh
    {
        public struct stTemp
        {
            public ushort usCurTemp_Word1;
            public ushort usCurTemp_Word2;
        }

        [StructLayout(LayoutKind.Explicit, Size = 8)]
        public struct UNION_TEMP
        {
            [FieldOffset(0)]
            public float fCurTemp;

            [FieldOffset(0)]
            public stTemp t;
        }

        #region 基础参数flag
        private string strIP = null;
        private ushort netPost = 0;
        private bool setflag = false;
        #endregion

       // public int checkflag=0;

        //modbus
        private static GCModbus m_modbus = new GCModbus();

        //数据线程
        Thread t_GetShowData;
        Thread t_GetChannelData;
        Thread t_GetStatusData;

        //转换数据使用
        UNION_TEMP channel1_value;

        UNION_TEMP utemp;

        /// <summary>
        /// 排序最大时间戳
        /// </summary>
        private UInt32 fDetMax_Time = 0;  

        public GcDataTh(string ip, ushort post)
        {
            if (!String.IsNullOrEmpty(ip) && post > 0)
            {
                this.strIP = ip;
                this.netPost = post;
                this.setflag = true;
            }else{
                setflag = false;
            }
        }

        ~GcDataTh()
        {
            this.strIP = null;
            this.netPost = 0;
            this.setflag = false;
        }

        #region Tool function
        private void BubbleSort(ref UInt32[] arr, ref float[] value, int len, ushort useflag)
        {
            int i = 0;
            int j = 0;
            int k = len - 1;
            int n = 0;

            for (i = 0; i < len - 1; i++)
            {
                int flag = 1;
                n = 0;

                for (j = 0; j < k; j++)
                {
                    UInt32 tmp = 0;
                    float tmpv = 0.0f;
                    if (arr[j] > arr[j + 1])
                    {
                        tmp = arr[j];
                        tmpv = value[j];

                        arr[j] = arr[j + 1];
                        value[j] = value[j + 1];

                        arr[j + 1] = tmp;
                        value[j + 1] = tmpv;

                        flag = 0;
                        n = j;
                    }
                }
                if (flag == 1)
                    break;
                k = n;
            }

            if (useflag == 0)
            {
                if ((Int32)(arr[0] - fDetMax_Time) < -100000)
                {
                    fDetMax_Time = arr[0];
                }
            }
        }

        #endregion


        #region Modbus功能函数
        /// <summary>
        /// 获取线圈状态
        /// </summary>
        /// <param name="address"></param>
        /// <param name="num"></param>
        /// <param name="temp"></param>
        private int GetCState(ushort address, ushort num, ref byte[] temp)
        {
            int ret = -1;
            int count = 0;
            if (setflag)
            {
                ret = m_modbus.ReadCoilStatus(address, num, this.strIP, this.netPost, ref temp);
                while (ret != 0)
                {
                    count++;
                    if (count > 3)
                        break;
                    ret = m_modbus.ReadCoilStatus(address, num, this.strIP, this.netPost, ref temp);
                }
            }
            return ret;
        }

        /// <summary>
        /// 获取状态
        /// </summary>
        /// <param name="address"></param>
        /// <param name="num"></param>
        /// <param name="state"></param>
        private int GetState(ushort address, ushort num, ref UInt16[] state)
        {
            int ret = -1;
            int count = 0;
            if (setflag)
            {
                ret = m_modbus.ReadHoldingReg(address, num, this.strIP, this.netPost, ref state);
                while (ret != 0)
                {
                    count++;
                    if (count > 3)
                        break;
                    ret = m_modbus.ReadHoldingReg(address, num, this.strIP, this.netPost, ref state);
                }
            }
            return ret;
        }

        /// <summary>
        /// 读设备温度
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="num">读取数目</param>
        /// <param name="temp">存储单元</param>
        private void GetTemp(ushort address, ushort num, ref float[] temp)
        {
            UInt16[] dest = new UInt16[num];
            int ret = 0;
            int count = 0;

            if (setflag)
            {
                ret = m_modbus.ReadHoldingReg(address, num, this.strIP, this.netPost, ref dest);
                while (ret != 0)
                {
                    count++;
                    if (count > 3)
                        break;
                    ret = m_modbus.ReadHoldingReg(address, num, this.strIP, this.netPost, ref dest);
                }
            }

            for (int i = 0; i < 12; i += 2)
            {
                utemp.t.usCurTemp_Word1 = dest[i];
                utemp.t.usCurTemp_Word2 = dest[i + 1];
                temp[i / 2] = utemp.fCurTemp;
            }

            int no = 6;
            for (int j = 16; j < 22; j++)
            {
                temp[no] = (dest[j]);
                no++;
            }
        }

        #endregion



        /// <summary>
        /// 获取通道数据
        /// </summary>
        /// <param name="address"></param>
        /// <param name="num"></param>
        private void Get_Channel_Data(ushort address, ushort num)
        {
            UInt16[] dest = new UInt16[num];

            UInt32[] timev = new UInt32[30];
            float[] fidv = new float[30];

            int ret;
            if (this.setflag)
                ret = m_modbus.ReadHoldingReg(address, num, this.strIP, this.netPost, ref dest);

            UInt32 tmp;
            int j = 0;
       
            for (int start = 0, i=0; start < num;)
            {
                tmp = dest[start + 1];
                tmp <<= 16;
                tmp = tmp + dest[start];
                timev[i] = tmp;

                channel1_value.t.usCurTemp_Word1 = dest[start + 2];
                channel1_value.t.usCurTemp_Word2 = dest[start + 3];
                fidv[i] = channel1_value.fCurTemp;
                start += 4;
                i++;
            }

            BubbleSort(ref timev, ref fidv, num / 4, 0);

            {
                for (int i = 0; i < num / 4; i++)
                {
                    tmp = timev[i];

                    if (tmp > fDetMax_Time)
                    {
                        
                        fDetMax_Time = tmp;
                        globaldata.m_signalbuffer.Channel1_Port.ctimer = tmp;
                        globaldata.m_signalbuffer.Channel1_Port.cdata = fidv[i];
                        globaldata.m_dpbuffer.ShowList.showDet.fDetValue = fidv[i] * 1000.0f;

                        j++;
                     
                        globaldata.m_signalbuffer.Draw_Port.Add(globaldata.m_signalbuffer.Channel1_Port);
                    }
                }
            }                           
        }

       

        ///////////////////////////////////////////////////////////
        /// <summary>
        /// 获取设备相关温度
        /// </summary>
        /// <param name="temp"></param>
        private void GetGCTemp(ref float[] temp)
        {
            try
            {
                GetTemp(globaldata.tempstart, 24, ref temp);
            }
            catch (Exception e)
            {
                Log.Error(e.Message);
            }
            
        }

        /// <summary>
        /// 获取程升过程状态
        /// </summary>
        /// <param name="state"></param>
        private void GetProUpState(ref ushort[] state)
        {
            try
            {
                GetState(globaldata.statusstart, 6, ref state);
            }
            catch (Exception e)
            {
                Log.Error(e.Message);
            }
            
        }

        private int LoseNum = 0;
        /// <summary>
        /// 获取HMI运行状态
        /// </summary>
        /// <param name="state"></param>
        private int GetHMIState(ref ushort[] state)
        {
            int ret = -1;
            try
            {
                ret = GetState(globaldata.hmistatus, 9, ref state);

                if (ret != 0)
                {
                    LoseNum++;
                    if (LoseNum > 5)
                    {
                        globaldata.m_hmibuffer.gcinfo.hmioffline = true;
                    }
                }
                else
                {
                    globaldata.m_hmibuffer.gcinfo.hmioffline = false;
                    LoseNum = 0;
                }
            }
            catch (Exception e)
            {
                Log.Error(e.Message);
            }

            return ret;
        }

        /// <summary>
        /// 获取点火时间
        /// </summary>
        /// <param name="state"></param>
        /// <returns></returns>
        public int GetFireUpTime(ref ushort[] state)
        {
            int ret = 0;
            try
            {
                ret = GetState(153, 2, ref state);
            }
            catch (Exception e)
            {
                Log.Error(e.Message);
            }
            return ret;
        }

        /// <summary>
        /// 获取各个固件版本
        /// </summary>
        /// <param name="state"></param>
        /// <returns></returns>
        public int GetFireWareVersion(ref ushort[] state)
        {
            int ret = 0;
            try
            {
                ret = GetState(1000, 12, ref state);
            }
            catch (Exception e)
            {
                Log.Error(e.Message);
            }
            return ret;

        }

        /// <summary>
        /// 获取阀状态
        /// </summary>
        /// <param name="state"></param>
        private void GetValveState(ref byte[] state)
        {
            try
            {
                GetCState(globaldata.valusstatus, 4, ref state);
            }
            catch (Exception e)
            {
                Log.Error(e.Message);
            }
           
        }

        /// <summary>
        /// 获取错误状态
        /// </summary>
        /// <param name="state"></param>
        private void GetErrorState(ref byte[] state)
        {
            try
            {
                GetCState(globaldata.errortatus, 9, ref state);
            }
            catch (Exception e)
            {
                Log.Error(e.Message);
            }
            
        }

        /// <summary>
        /// 点火状态
        /// </summary>
        /// <param name="state"></param>
        private void GetFireState(ref byte[] state)
        {
            try
            {
                GetCState(globaldata.detstatus, 3, ref state);
            }
            catch (Exception e)
            {
                Log.Error(e.Message);
            }
        }

        /// <summary>
        /// TCD SW
        /// </summary>
        /// <param name="state"></param>
        public int GetTCDSWState(ref byte[] state)
        {
            int ret = 0;
            try
            {
                ret = GetCState(11, 3, ref state);
            }
            catch (Exception e)
            {
                Log.Error(e.Message);
            }
            
            return ret;
        }

        /// <summary>
        /// 点火状态2
        /// </summary>
        /// <param name="state"></param>
        public void GetFireState2(ref ushort[] state)
        {     
            GetState(155, 4, ref state);
        }

        public int GetDACValState(ref ushort[] state)
        {
            int ret = 0;
            ret =  GetState(132, 6, ref state);
            return ret;
        }

        /// <summary>
        /// 获取10路继电器
        /// </summary>
        /// <param name="state"></param>
        public void GetALLSWState(ref byte[] state)
        {
            GetCState(16, 10, ref state);
        }

        /// <summary>
        /// 获取链路数据
        /// </summary>
        public void get_channel_data()
        {
            if (globaldata.m_hwconfig.hwconfiginfo.u16DetFront == 1)
            {
                Get_Channel_Data(160, 120);
            }          
        }

        /// <summary>
        /// 获取方法开始  结束时间
        /// </summary>
        /// <param name="start"></param>
        /// <param name="endtime"></param>
        public void Get_Method_StartEndTime(ref UInt32 start,ref UInt32 endtime)
        {
            UInt32 starttime = 0;
            UInt32 end = 0;
            UInt32 tmp = 0;
            int ret = 0;
            int count = 0;
            UInt16[] dest = new UInt16[2];

            if (setflag)
            {
                ret = m_modbus.ReadHoldingReg(88, 4, this.strIP, this.netPost, ref dest);
                while (ret != 0)
                {
                    count++;
                    if (count > 3)
                        break;
                    ret = m_modbus.ReadHoldingReg(88, 4, this.strIP, this.netPost, ref dest);
                }

                if (ret == 0)
                {
                    tmp = dest[1];
                    tmp <<= 16;
                    tmp = tmp + dest[0];
                    starttime = tmp;

                    tmp = 0;
                    tmp = dest[3];
                    tmp <<= 16;
                    tmp = tmp + dest[2];
                    end = tmp;
                }
                else
                {
                    start = 0;
                    endtime = 0;
                }
               
            }
            start = starttime;
            endtime = end;

        }

        /// <summary>
        /// 获取方法开始时间
        /// </summary>
        /// <returns></returns>
        public UInt32 Get_Method_StartTime()
        {
            UInt32 time = 0;
            UInt32 tmp = 0;
            int ret = 0;
            int count = 0;
            System.UInt16[] dest = new System.UInt16[2];

            if (setflag)
            {
                ret = m_modbus.ReadHoldingReg(88, 2, this.strIP, this.netPost, ref dest);
                while (ret != 0)
                {
                    count++;
                    if (count > 3)
                        break;
                    ret = m_modbus.ReadHoldingReg(88, 2, this.strIP, this.netPost, ref dest);
                }

                if (ret == 0)
                {
                    tmp = dest[1];
                    tmp <<= 16;
                    tmp = tmp + dest[0];
                    time = tmp;
                }
                else
                {
                    time = 0;
                }
            }
            return time;
        }

        /// <summary>
        /// 获取方法结束时间
        /// </summary>
        /// <returns></returns>
        public UInt32 Get_Method_EndTime()
        {
            UInt32 time = 0;
            UInt32 tmp = 0;
            int ret = 0;
            int count = 0;
            UInt16[] dest = new UInt16[2];

            if (this.setflag)
            {
                ret = m_modbus.ReadHoldingReg(90, 2, this.strIP, this.netPost, ref dest);
                while (ret != 0)
                {
                    count++;
                    if (count > 3)
                        break;
                    ret = m_modbus.ReadHoldingReg(90, 2, this.strIP, this.netPost, ref dest);
                }

                if (ret == 0)
                {
                    tmp = dest[1];
                    tmp <<= 16;
                    tmp = tmp + dest[0];
                    time = tmp;
                }
                else
                {
                    time = 0;
                }
            }
            return time;
        }
 
        /// <summary>
        /// 更新显示数据
        /// </summary>
        public void update_showdata()
        {
           float[] gctemp = new float[12] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
           byte[] valvestate = new byte[4];
           byte[] detstate = new byte[3];
           byte[] errstate = new byte[2]{0,0};
           byte[] tenstate = new byte[2]{0,0};

           GetGCTemp(ref gctemp);     
           globaldata.m_dpbuffer.ShowList.showtemp.FPActualTemp = gctemp[0];         
           globaldata.m_dpbuffer.ShowList.showtemp.BPActualTemp = gctemp[4];       
           globaldata.m_dpbuffer.ShowList.showtemp.FPSetTemp = gctemp[6];       
           globaldata.m_dpbuffer.ShowList.showtemp.BPSetTemp = gctemp[10];         
           globaldata.m_dpbuffer.ShowList.showtemp.ColActualTemp = gctemp[3];   
           globaldata.m_dpbuffer.ShowList.showtemp.ColSetTemp = gctemp[9];         
           if (CProfileDevice.m_DevParam.syspara.u16DetFront == 1)
           {             
               globaldata.m_dpbuffer.ShowList.showtemp.fDetActualTemp = gctemp[1];
               globaldata.m_dpbuffer.ShowList.showtemp.fDetSetTemp = gctemp[7];
           }
           if (CProfileDevice.m_DevParam.syspara.u16DetInter == 1)
           {             
               globaldata.m_dpbuffer.ShowList.showtemp.iDetActualTemp = gctemp[2];
               globaldata.m_dpbuffer.ShowList.showtemp.iDetSetTemp = gctemp[8];
           }

           if (CProfileDevice.m_DevParam.syspara.u16DetBehind == 1)
           {
               globaldata.m_dpbuffer.ShowList.showtemp.bDetActualTemp = gctemp[5];
               globaldata.m_dpbuffer.ShowList.showtemp.bDetSetTemp = gctemp[11];
           }

           if (CProfileDevice.m_DevParam.syspara.u16AuxHeaterNum > 0)
           {
               if (CProfileDevice.m_DevParam.syspara.u16AuxHeater1 == 1)  //TCD
               {                 
                   globaldata.m_dpbuffer.ShowList.showtemp.AuxActualTemp1 =gctemp[2];
                   globaldata.m_dpbuffer.ShowList.showtemp.AuxSetTemp1 = gctemp[8];
               }

               if (CProfileDevice.m_DevParam.syspara.u16AuxHeater2 == 1)
               {                 
                   globaldata.m_dpbuffer.ShowList.showtemp.AuxActualTemp2 = gctemp[5];
                   globaldata.m_dpbuffer.ShowList.showtemp.AuxSetTemp2 = gctemp[11];
               }
           }

           GetValveState(ref valvestate);
           globaldata.m_dpbuffer.ShowList.showValve.u16ValveOne = (((valvestate[0] >> 0) & 0x1) == 1) ? true : false;
           globaldata.m_dpbuffer.ShowList.showValve.u16ValveTwo = (((valvestate[0] >> 1) & 0x1) == 1) ? true : false;
           globaldata.m_dpbuffer.ShowList.showValve.u16ValveThree = (((valvestate[0] >> 2) & 0x1) == 1) ? true : false;
           globaldata.m_dpbuffer.ShowList.showValve.u16ValveFour = (((valvestate[0] >> 3) & 0x1) == 1) ? true : false;

           GetALLSWState(ref tenstate );
           for (int i = 0; i < 10; i++ )
           {
               if(i < 8)
                    globaldata.m_hmibuffer.gcinfo.TenRelay[i] = (byte)((((tenstate[0] >> i) & 0x1) == 1) ? 1 : 0);
               else
                    globaldata.m_hmibuffer.gcinfo.TenRelay[i] = (byte)((((tenstate[1] >>(i-8)) & 0x1) == 1) ? 1 : 0);
           }

           globaldata.m_dpbuffer.ShowList.showValve.u16ValveFive = (((tenstate[1] >>1) & 0x1) == 1) ? true : false;
           globaldata.m_dpbuffer.ShowList.showValve.u16ValveSix = (((tenstate[1] >> 0) & 0x1) == 1) ? true : false;


           //Console.WriteLine("*******10路寄存器状态*********");
           //for (int ti = 0; ti < globaldata.m_hmibuffer.gcinfo.TenRelay.Length;ti++ )
           //{
           //    Console.WriteLine(string.Format("寄存器【{0}】{1}", ti+1, globaldata.m_hmibuffer.gcinfo.TenRelay[ti]));
           //}
           GetFireState(ref detstate);
           globaldata.m_dpbuffer.ShowList.showDet.fDetSwitch = ((((detstate[0] >> 0) & 0x1) == 1) ? true : false);
           //globaldata.m_dpbuffer.ShowList.showDet.iDetSwitch = ((((detstate[0] >> 0) & 0x1) == 1) ? true : false);
           //globaldata.m_dpbuffer.ShowList.showDet.bDetSwitch = ((((detstate[0] >> 0) & 0x1) == 1) ? true : false);

           GetFireState2(ref globaldata.m_hmibuffer.gcinfo.FireStatus);
           globaldata.m_dpbuffer.ShowList.showDet.fDetStatue = globaldata.m_hmibuffer.gcinfo.FireStatus[0];
           //globaldata.m_dpbuffer.ShowList.showDet.iDetStatue = globaldata.m_hmibuffer.gcinfo.FireStatus[2];
           //globaldata.m_dpbuffer.ShowList.showDet.bDetStatue = globaldata.m_hmibuffer.gcinfo.FireStatus[3];

            GetErrorState(ref errstate);
            for (int i = 0; i < 9; i++)
            {
                globaldata.m_hmibuffer.gcinfo.ErrorStatus[i] = (byte)((((errstate[0] >> i) & 0x1) == 1) ? 1 : 0);
            }
        }

        /// <summary>
        /// 更新HMI状态数据
        /// </summary>
        private void update_hmidata()
        {
            UInt16[] hmistate = new UInt16[9];
            int ret = -1;
            ret = GetHMIState(ref hmistate);

            if (ret == 0)
            {
                globaldata.m_hmibuffer.gcinfo.batno = hmistate[0];
                globaldata.m_hmibuffer.gcinfo.batruncount = hmistate[1];
                globaldata.m_hmibuffer.gcinfo.oneruntime = hmistate[2];
                globaldata.m_hmibuffer.gcinfo.singlerun = hmistate[3];
                globaldata.m_hmibuffer.gcinfo.batrun = hmistate[4];
                globaldata.m_hmibuffer.gcinfo.methodstatus = hmistate[5];
                globaldata.m_hmibuffer.gcinfo.waitstart = hmistate[6];
                globaldata.m_hmibuffer.gcinfo.hmistatus = hmistate[7];
                globaldata.m_hmibuffer.gcinfo.runtime = hmistate[8];

                //额外设置
                globaldata.m_dpbuffer.ShowList.showtime.runtimenow = hmistate[2];
                globaldata.m_dpbuffer.ShowList.showtime.alltime = hmistate[8];
                //  Get_Method_StartEndTime(ref globaldata.m_hmibuffer.gcinfo.NowStartTime, ref globaldata.m_hmibuffer.gcinfo.NowEndTime);

                //获取开始时间
                if (globaldata.m_hmibuffer.gcinfo.methodstatus == 4 || globaldata.m_hmibuffer.gcinfo.methodstatus == 5)
                {
                    globaldata.m_hmibuffer.gcinfo.NowStartTime = Get_Method_StartTime();
                }

                //获取结束时间
                if (globaldata.m_hmibuffer.gcinfo.methodstatus == 0 || globaldata.m_hmibuffer.gcinfo.methodstatus > 5)
                {
                    globaldata.m_hmibuffer.gcinfo.NowEndTime = Get_Method_EndTime();
                }
            }
            
        }

        /// <summary>
        /// 更新通道采集数据
        /// </summary>
        private void update_channeldata()
        {
            get_channel_data();
        }
    
        /// <summary>
        /// 显示数据采集线程
        /// </summary>
        ManualResetEvent showmre = new ManualResetEvent(false);
        public void ShowDataStart()
        {
            if (showmre != null)
            {
                showmre.Reset();
            }
            t_GetShowData = new Thread(GetShowDataProc);
            t_GetShowData.IsBackground = true;
            t_GetShowData.Start();
        }

        public void ShowDataStop()
        {
            showmre.Set();    
        }

        private void GetShowDataProc()
        {
            while (!showmre.WaitOne(500))
            {
                update_showdata();
                Thread.Sleep(500);
            }
        }


        /// <summary>
        /// FID数据读取线程
        /// </summary>
        ManualResetEvent channelmre = new ManualResetEvent(false);
        public void ChannelDataStart()
        {
            if (channelmre != null)
            {
                channelmre.Reset();
            }
            t_GetChannelData = new Thread(GetChannelDataProc);
            t_GetChannelData.IsBackground = true;
            t_GetChannelData.Start();

        }

        public void ChannelDataStop()
        {
            channelmre.Set();        
        }

        private void GetChannelDataProc()
        {
            while (!channelmre.WaitOne(500))      
            {
                lock (globaldata.m_signalbuffer.Draw_Port)
                {                 
                    update_channeldata();
                }                                                 
            }
        }

        /// <summary>
        /// HMI状态读取线程
        /// </summary>
        ManualResetEvent hmimre = new ManualResetEvent(false);
        public void HmiStatueStart()
        {
            if (hmimre != null)
            {
                hmimre.Reset();
            }
            t_GetStatusData = new Thread(HmiStatueProc);
            t_GetStatusData.IsBackground = true;
            t_GetStatusData.Start();
        }

        public void HmiStatueStop()
        {
            hmimre.Set();
        }

        private void HmiStatueProc()
        {
            while (!hmimre.WaitOne(500))
            {
                update_hmidata();
            }
        }

    }
}
