using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using DBFactory;
using System.Threading;
namespace wcfControlMonitorClient
{
    /// <summary>
    /// Creator:Richard.liu
    /// 解析PLC返回的数据
    /// </summary>
    public static class CParsePLCData
    {
        
        static int[] AllReturns;//20110216
        /// <summary>
        /// 20110216根据S7Connection标识反馈所有DB1数据的虚拟设备
        /// </summary>
        /// <param name="sb">S7Connection标识</param>
        /// <returns></returns>
        public static Model.MDevice GetDevice28AllDB1Data(StringBuilder sb)
        {
            DataView dv = dbo.ExceSQL("SELECT F_DeviceIndex  FROM T_Base_Device WHERE (F_DeviceKindIndex = 28 and F_S7Connection='"+sb.ToString()+"')").Tables[0].DefaultView;
            if (dv.Count > 0)
            {
                return Model.CGetInfo.GetDeviceInfo(Convert.ToInt32(dv[0]["F_DeviceIndex"]));
            }
            else
            {
                return null;
            }
        }
        static StringBuilder sql = new StringBuilder();
        static char[] dd = new char[1] { '.' };//20101124
        static string[] sp ;//20101124
        static string _CParsePLCError = "";//监控调度类错误说明

        public static string CParsePLCError
        {
            get { return _CParsePLCError; }
            set { _CParsePLCError = value; }
        }
        static DBOperator dbo = new DBOperator();
        static DBOperator dboRoute = new DBOperator();
        static DBOperator dboMan = new DBOperator("ManConnString", "ManDBFactory");
        static Model.MDevice devinfo28 = Model.CGetInfo.GetDeviceInfo(65534);
        
        
        //static Thread mythreadRoute;
        static Thread mythread;
        static bool exitThread = false;//20091107
        private static void BeginListen()
        {//20091107
            while (!exitThread  )
            {
                try
                {
                    GetAllReturns();
                    SetDeviceState();

                }
                catch (Exception ex)
                {
                    _CParsePLCError = ex.Message;
                }
                Thread.Sleep(200);//20100710
            }
        }
        
        public static void EndListen()
        {//20091107
            exitThread = true;

            if (mythread != null)
            {

                mythread.Abort();
                mythread = null;
            }
            
            
        }
        public static void StartListen()
        {
            //20091107
            exitThread = false;
            mythread = new Thread(new ThreadStart(BeginListen));
            mythread.IsBackground = true;
            mythread.Start();
            
        }
        
        /// <summary>
        /// 取得指定光电开关(确认按钮)设备索引的信号(0,1)
        /// </summary>
        /// <param name="deviceIdx">设备索引</param>
        /// <returns>0,1</returns>

        public static int GetDevicePhotoelectric(int deviceIdx)
        {
            try
            {
                //20110216
                AllReturns = CStaticClass.MutiS7ConnReturns[GetDeviceS7Connection(deviceIdx)];
                if (AllReturns != null)
                    {
                        #region 获取开关量的值

                        sql.Remove(0, sql.Length);
                        sql.Append("SELECT F_DeviceIndex, F_DeviceKindIndex,F_DBWGetLength," ).Append(
                            " F_DBW2Address,F_S7Connection FROM T_Base_Device WHERE ((F_DeviceKindIndex = 14)" ).Append(
                            " OR (F_DeviceKindIndex = 18)) and (F_DBW2Address is not NULL) and F_DeviceIndex=" ).Append( deviceIdx);
                        DataView dvle = dbo.ExceSQL( sql.ToString()).Tables[0].DefaultView;
                        //devinfo = Model.CGetInfo.GetDeviceInfo(deviceIdx);

                        int glen = 0;
                        int IfVis = 0;
                        if (dvle.Count>0)//(devinfo.DeviceKind == 14) || (devinfo.DeviceKind == 18)
                        {
                            //20110216
                            devinfo28 =GetDevice28AllDB1Data(new StringBuilder(dvle[0]["F_S7Connection"].ToString()));
                            int temp = Convert.ToInt32(dvle[0]["F_DBW2Address"]) - devinfo28.Dbw2Address;
                            if (Convert.ToInt32((Convert.ToDecimal(dvle[0]["F_DBWGetLength"]) * 8 - 1)) > 7)//devinfo.Dbw2Getlength
                            {
                                glen = Convert.ToInt32((Convert.ToDecimal(dvle[0]["F_DBWGetLength"]) * 8 - 1)) - 8;
                                temp = temp + 1;
                            }
                            else
                            {
                                glen = Convert.ToInt32((Convert.ToDecimal(dvle[0]["F_DBWGetLength"]) * 8 - 1));
                            }
                            if (temp >= 0)
                            {
                                IfVis = CommonClassLib.CCarryConvert.GetBitFromInteger(AllReturns[temp], glen);
                                //if (dvle[0]["F_DeviceKindIndex"].ToString() == "18")
                                //{//配合孙宇光电开关0有探物,1无探物,在这里取反符合正常逻辑
                                //    if (IfVis == 1)
                                //    {
                                //        IfVis = 0;
                                //    }
                                //    else
                                //    {
                                //        IfVis = 1;
                                //    }
                                //}
                                return IfVis;
                            }
                            else
                            {
                                return -1;
                            }

                        }
                        else
                        {
                            return -1;
                        }


                        #endregion


                    }
                    else
                    {
                        return -1;
                    }
                
            }
            catch //(Exception ex)
            {
                //if (FrmControlMonitor.FormInstance.GetObjectText("tsStatus").IndexOf("取得指定光电开关的信号时:" + ex.Message) < 0)
                //{

                //    FrmControlMonitor.FormInstance.FlashPanit("tsStatus", "取得指定光电开关的信号时:" + ex.Message, true);
                //}
                return -1;
            }
        }
        /// <summary>
        /// 20101118根据设备号和bit位,取得F_SplitByte里的光电bit值:0,1
        /// </summary>
        /// <param name="deviceIdx"></param>
        /// <param name="bit"></param>
        /// <returns></returns>
        public static int GetDevicePhotoelectric(int deviceIdx, int abit)
        {
            try
            {
                //20110216
                AllReturns = CStaticClass.MutiS7ConnReturns[GetDeviceS7Connection(deviceIdx)];
                if (AllReturns != null)
                {
                    #region 获取开关量的值

                    sql.Remove(0, sql.Length);
                    sql.Append("SELECT F_SplitByte,F_S7Connection  FROM T_Base_Device WHERE  F_DeviceIndex=").Append(deviceIdx).Append(" and F_SplitByte>=0");
                    DataView dvle = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;

                    int glen = 0;
                    int IfVis = 0;
                    if (dvle.Count > 0)
                    {
                        //20110216
                        devinfo28 =GetDevice28AllDB1Data(new StringBuilder(dvle[0]["F_S7Connection"].ToString()));
                        int temp = Convert.ToInt32(dvle[0]["F_SplitByte"]) - devinfo28.Dbw2Address;
                        if (abit > 7)
                        {
                            glen = abit - 8;
                            temp = temp + 1;
                        }
                        else
                        {
                            glen = abit;
                        }
                        if (temp >= 0)
                        {
                            IfVis = CommonClassLib.CCarryConvert.GetBitFromInteger(AllReturns[temp], glen);
                            //if (dvle[0]["F_DeviceKindIndex"].ToString() == "18")
                            //{//配合孙宇光电开关0有探物,1无探物,在这里取反符合正常逻辑
                            //    if (IfVis == 1)
                            //    {
                            //        IfVis = 0;
                            //    }
                            //    else
                            //    {
                            //        IfVis = 1;
                            //    }
                            //}
                            return IfVis;
                        }
                        else
                        {
                            return -1;
                        }

                    }
                    else
                    {
                        return -1;
                    }


                    #endregion


                }
                else
                {
                    return -1;
                }
                
            }
            catch 
            {
                
                return -1;
            }
        }
        /// <summary>
        /// //20101124根据【设备号.bit位】的字符串,取得F_SplitByte里的光电bit值:0,1
        /// </summary>
        /// <param name="deviceIdx"></param>
        /// <param name="bit"></param>
        /// <returns></returns>
        public static int GetDevicePhotoelectric(string devicebit)
        {
            sp = devicebit.Split(dd);
            if (sp.GetLength(0) <= 1) return -1;
            int deviceIdx, abit;
            int.TryParse(sp[0], out deviceIdx);
            int.TryParse(sp[1], out abit);
            try
            {
                //20110216
                AllReturns = CStaticClass.MutiS7ConnReturns[GetDeviceS7Connection(deviceIdx)];
                if (AllReturns != null)
                    {
                        #region 获取开关量的值


                        sql.Remove(0, sql.Length);
                        sql.Append("SELECT F_SplitByte,F_S7Connection  FROM T_Base_Device WHERE  F_DeviceIndex=").Append(deviceIdx).Append(" and F_SplitByte>=0");
                        DataView dvle = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;

                        int glen = 0;
                        int IfVis = 0;
                        if (dvle.Count > 0)
                        {
                            //20110216
                            devinfo28 = GetDevice28AllDB1Data(new StringBuilder(dvle[0]["F_S7Connection"].ToString()));
                            int temp = Convert.ToInt32(dvle[0]["F_SplitByte"]) - devinfo28.Dbw2Address;
                            if (abit > 7)
                            {
                                glen = abit - 8;
                                temp = temp + 1;
                            }
                            else
                            {
                                glen = abit;
                            }
                            if (temp >= 0)
                            {
                                IfVis = CommonClassLib.CCarryConvert.GetBitFromInteger(AllReturns[temp], glen);
                                //if (dvle[0]["F_DeviceKindIndex"].ToString() == "18")
                                //{//配合孙宇光电开关0有探物,1无探物,在这里取反符合正常逻辑
                                //    if (IfVis == 1)
                                //    {
                                //        IfVis = 0;
                                //    }
                                //    else
                                //    {
                                //        IfVis = 1;
                                //    }
                                //}
                                return IfVis;
                            }
                            else
                            {
                                return -1;
                            }

                        }
                        else
                        {
                            return -1;
                        }


                        #endregion


                    }
                    else
                    {
                        return -1;
                    }
                
            }
            catch (Exception ex)
            {
                //if (FrmControlMonitor.FormInstance.GetObjectText("tsStatus").IndexOf("取得指定光电开关的信号时:" + ex.Message) < 0)
                //{

                //    FrmControlMonitor.FormInstance.FlashPanit("tsStatus", "取得指定光电开关的信号时:" + ex.Message, true);
                //}
                return -1;
            }
        }
        /// <summary>
        /// 取得指定设备索引的设备状态:[0]读写标志;[1]状态;[2]任务号;[3]X坐标;[4]Y坐标;[5]设备索引
        /// </summary>
        /// <param name="deviceIdx">设备索引</param>
        /// <returns></returns>

        public static int[] GetDeviceState(int deviceIdx)
        {
            try
            {


                //20110216
                AllReturns = CStaticClass.MutiS7ConnReturns[GetDeviceS7Connection(deviceIdx)];
                if (AllReturns != null)
                    {
                        #region 获取设备状态
                        sql.Remove(0, sql.Length);
                        sql.Append("SELECT F_DeviceIndex, F_DeviceKindIndex,F_DBWGetLength," ).Append(
                            " F_DBW2Address,F_S7Connection FROM T_Base_Device WHERE (F_DBW2Address is not NULL) and F_DeviceIndex=").Append(deviceIdx);
                        DataView dvle = dbo.ExceSQL( sql.ToString()).Tables[0].DefaultView;
                        //devinfo = Model.CGetInfo.GetDeviceInfo(deviceIdx);

                        if (dvle.Count>0)//devinfo.Dbw2Address != -1
                        {
                            //20110216
                            devinfo28 =GetDevice28AllDB1Data(new StringBuilder(dvle[0]["F_S7Connection"].ToString()));
                            int temp = Convert.ToInt32(dvle[0]["F_DBW2Address"]) - devinfo28.Dbw2Address;//devinfo.Dbw2Address
                            decimal glen = Convert.ToDecimal(dvle[0]["F_DBWGetLength"]);//devinfo.Dbw2Getlength
                            int[] states = new int[6];
                            switch (dvle[0]["F_DeviceKindIndex"].ToString())//devinfo.DeviceKind.ToString()
                            {

                                #region 其他设备
                                case "1"://堆垛机

                                    states[0] = AllReturns[temp];//读写标志
                                    states[1] = AllReturns[temp + 1];//状态
                                    states[2] = (AllReturns[temp + 2] << 8) + AllReturns[temp + 3];//任务号
                                    states[3] = AllReturns[temp + 7] + (AllReturns[temp + 6] << 8) + (AllReturns[temp + 5] << 16) + (AllReturns[temp + 4] << 32);//X坐标
                                    states[4] = AllReturns[temp + 11] + (AllReturns[temp + 10] << 8) + (AllReturns[temp + 9] << 16) + (AllReturns[temp + 8] << 32);//Y坐标
                                    states[5] = deviceIdx;//设备号索引

                                    break;
                                case "2"://输送机
                                    states[0] = AllReturns[temp];//读写标志
                                    states[1] = AllReturns[temp + 1];//状态
                                    states[2] = (AllReturns[temp + 2] << 8) + AllReturns[temp + 3];//任务号
                                    states[3] = 0;
                                    states[4] = 0;
                                    states[5] = deviceIdx;//设备号索引

                                    break;
                                case "4"://RGV
                                    states[0] = AllReturns[temp];//读写标志
                                    states[1] = AllReturns[temp + 1];//状态
                                    states[2] = (AllReturns[temp + 2] << 8) + AllReturns[temp + 3];//任务号
                                    states[3] = AllReturns[temp + 7] + (AllReturns[temp + 6] << 8) + (AllReturns[temp + 5] << 16) + (AllReturns[temp + 4] << 32);//X坐标
                                    states[4] = 0;
                                    states[5] = deviceIdx;//设备号索引

                                    break;
                                #endregion
                            }


                            return states;
                        }
                        else
                        {
                            return null;
                        }


                        #endregion


                    }
                    else
                    {
                        return null;
                    }
                
            }
            catch //(Exception ex)
            {
                //if (FrmControlMonitor.FormInstance.GetObjectText("tsStatus").IndexOf("取得指定光电开关的信号时:" + ex.Message) < 0)
                //{

                //    FrmControlMonitor.FormInstance.FlashPanit("tsStatus", "取得指定光电开关的信号时:" + ex.Message, true);
                //}
                return null;
            }
        }


        /// <summary>
        /// 设置所有设备的当前动态属性
        /// </summary>
        public static void SetDeviceState()
        {
            DataView dvv = new DataView(); DataView dvb = new DataView();
            try
            {
                int[] States;
                foreach (Model.MDevice devinfo1 in Model.CGetInfo.DeviceInfo.Values)
                {
                    sql.Remove(0, sql.Length);
                    sql.Append("SELECT F_DeviceIndex FROM T_Base_Device WHERE (F_LockedState = - 1) and F_DeviceIndex=").Append(devinfo1.DeviceIndex);
                    dvv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                    if (dvv.Count > 0)
                    {
                        devinfo1.ErrorCode = 98;
                    }
                    else
                    {
                        if ((devinfo1.DeviceKind == 14) || (devinfo1.DeviceKind == 18))
                        {
                            devinfo1.DeviceVisual = GetDevicePhotoelectric(devinfo1.DeviceIndex);
                            continue;
                        }
                        if ((devinfo1.DeviceKind == 2) || (devinfo1.DeviceKind == 3) || (devinfo1.DeviceKind == 5) || (devinfo1.DeviceKind == 17) || (devinfo1.DeviceKind == 31))
                        {
                            //有些输送机、提升机在调度路径中存在,但是不需要调度来下指令,电器自己控制,只考察是否运行和故障位就可以了
                            if (devinfo1.OnlyDetectIO == "1")
                            {

                                #region 运行位(设备索引+7)
                                devinfo1.RunState = GetDevicePhotoelectric(Convert.ToInt32(devinfo1.DeviceIndex.ToString() + "7"));

                                int err = 0;
                                //devinfo1.ErrorCode = 0;
                                #endregion



                                #region 故障位(设备索引+6)
                                if (GetDevicePhotoelectric(Convert.ToInt32(devinfo1.DeviceIndex.ToString() + "6")) == 1)
                                {

                                    devinfo1.RunState = 2;

                                    err = 97;


                                }

                                devinfo1.ErrorCode = err;
                                //20090926

                                #endregion


                            }
                            else
                            {

                                States = GetDeviceState(devinfo1.DeviceIndex);
                                if (States == null) continue;

                                if (States[1] >= 30)
                                {
                                    devinfo1.ErrorCode = States[1];
                                    devinfo1.RunState = 2;
                                }

                                else if ((States[1] == 0) || (States[1] == 1) || (States[1] == 2))
                                {
                                    if (States[1] == 2)
                                    {
                                        //20090920
                                        devinfo1.RunState = 5;
                                    }
                                    else
                                    {
                                        devinfo1.RunState = States[1];
                                    }
                                    //20100131


                                    //20091006
                                    devinfo1.ErrorCode = States[1];
                                    //20090926
                                }
                                devinfo1.TaskNo = States[2];
                                //20101118
                                if (devinfo1.SplitByte != -1)
                                {
                                    devinfo1.SplitByte_0 = GetDevicePhotoelectric(devinfo1.DeviceIndex, 0);
                                    devinfo1.SplitByte_1 = GetDevicePhotoelectric(devinfo1.DeviceIndex, 1);
                                    devinfo1.SplitByte_2 = GetDevicePhotoelectric(devinfo1.DeviceIndex, 2);
                                    devinfo1.SplitByte_3 = GetDevicePhotoelectric(devinfo1.DeviceIndex, 3);
                                    devinfo1.SplitByte_4 = GetDevicePhotoelectric(devinfo1.DeviceIndex, 4);
                                    devinfo1.SplitByte_5 = GetDevicePhotoelectric(devinfo1.DeviceIndex,5);
                                    devinfo1.SplitByte_6 = GetDevicePhotoelectric(devinfo1.DeviceIndex, 6);
                                    devinfo1.SplitByte_7 = GetDevicePhotoelectric(devinfo1.DeviceIndex, 7);
                                }
                            }

                        }
                        if ((devinfo1.DeviceKind == 1) || (devinfo1.DeviceKind == 4))
                        {
                            States = GetDeviceState(devinfo1.DeviceIndex);

                            if (States == null) continue;


                            if (States[1] >= 30)
                            {

                                devinfo1.ErrorCode = States[1];
                                devinfo1.RunState = 2;
                            }
                            else if ((States[1] == 0) || (States[1] == 1) || (States[1] == 2))
                            {
                                if (States[1] == 2)
                                {
                                    //20090920
                                    devinfo1.RunState = 5;
                                }
                                else
                                {
                                    devinfo1.RunState = States[1];
                                }
                                //20100131
                                devinfo1.ErrorCode = States[1];

                            }
                            devinfo1.TaskNo = States[2];
                            devinfo1.XCoor = States[3];
                            devinfo1.YCoor = States[4];

                        }
                        int bdv = 0, bdov = 0;
                        //20101118


                        if (devinfo1.BindingDevice != null)
                        {

                            bdv = GetDevicePhotoelectric(devinfo1.BindingDevice);//20101124
                        }
                        if (devinfo1.BindingDeviceOut != null)
                        {

                            bdov = GetDevicePhotoelectric(devinfo1.BindingDeviceOut);//20101124

                        }
                        //20101118
                        if ((bdv + bdov) >= 1)
                        {
                            devinfo1.HaveGoods = true;
                        }
                        else
                        {
                            devinfo1.HaveGoods = false;
                        }
                        sql.Remove(0, sql.Length);
                        sql.Append("SELECT F_MonitorIndex,F_NumParam1,F_NumParam2,F_NumParam3,F_NumParam4,F_NumParam5,F_NumParam6, F_TxtParam FROM T_Monitor_Task WHERE (F_MonitorIndex = ").Append(devinfo1.TaskNo).Append(")");
                        dvb = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                        if (dvb.Count > 0)
                        {
                            if (devinfo1.DeviceKind == 1)
                            {
                                devinfo1.ArrowLocation = string.Format("{0}排{1}列{2}层", dvb[0]["F_NumParam4"].ToString(), dvb[0]["F_NumParam5"].ToString(), dvb[0]["F_NumParam6"].ToString());
                            }
                            if (devinfo1.DeviceKind == 4)
                            {
                                devinfo1.ArrowLocation = dvb[0]["F_NumParam1"].ToString();
                            }
                            if (devinfo1.DeviceKind == 2)
                            {
                                devinfo1.ArrowLocation = dvb[0]["F_NumParam4"].ToString();
                            }
                            devinfo1.Barcode = dvb[0]["F_TxtParam"].ToString();

                        }
                        else
                        {
                            devinfo1.Barcode = "";
                            devinfo1.ArrowLocation = "";
                        }


                    }

                    Model.CGetInfo.SetDeviceInfo(devinfo1);


                }


            }

            catch (Exception exa)
            {

                _CParsePLCError = "解析PLC反馈数据的记录设备状态时发生错误:" + exa.Message;

            }
            finally
            {
                dvv.Dispose();
                dvb.Dispose();

            }
        }
       
        static string GetDeviceS7Connection(int deviceindex)
        {//20110216
            DataView dv = dbo.ExceSQL("SELECT F_S7Connection FROM T_Base_Device WHERE (F_DeviceIndex = " + deviceindex + ")").Tables[0].DefaultView;
            if (dv.Count > 0)
            {
                return dv[0]["F_S7Connection"].ToString();
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// 取得所有光电开关的信号
        /// </summary>
        static void GetAllReturns()
        {//20110216

            try
            {
                DataView dv = dbo.ExceSQL("SELECT F_DeviceIndex,F_S7Connection FROM T_Base_Device WHERE (F_DeviceKindIndex = 28)").Tables[0].DefaultView;
                if (dv.Count > 0)
                {
                    byte[] rr = null;
                    for (int i = 0; i < dv.Count; i++)
                    {
                       OPCClient.CCommonOPCClient.Hostname = CommonClassLib.AppSettings.GetValue("HostName");
                       OPCClient.CCommonOPCClient.ProgID = CommonClassLib.AppSettings.GetValue("OPCProgID");

                       rr= OPCClient.CCommonOPCClient.SyncReadAllItems(dv[i]["F_S7Connection"].ToString());
                       if (rr != null)
                       {
                           
                           Array.Copy(rr, CStaticClass.MutiS7ConnReturns[dv[i]["F_S7Connection"].ToString()], rr.GetLength(0));
                           
                       }
                    }
                }
                else
                {
                    CStaticClass.MutiS7ConnReturns = null;

                }
            }
            catch (Exception ex)
            {
                //if (FrmControlMonitor.FormInstance.GetObjectText("tsStatus").IndexOf("取得所有光电开关的信号时:" + ex.Message) < 0)
                //{

                //    FrmControlMonitor.FormInstance.FlashPanit("tsStatus", "取得所有光电开关的信号时:" + ex.Message, true);
                //}
                return;
            }
        }
       
    }
}