using System;
using System.Collections.Generic;
using System.Text;
using ICommLayer;
using DBFactory;
using System.Data;
using Microsoft.VisualBasic;
namespace OPCClient
{
    public class CSendDeviceOrder : ISendDeviceOrder
    {
        Model.MDevice devinfo;
        string _commLayerError;
        StringBuilder sql = new StringBuilder();
        StringBuilder sss = new StringBuilder();
        public string CommLayerError
        {
            get { return _commLayerError; }
            set { _commLayerError = value; }
        }
        DBOperator dbo = CCommonOPCClient.dbo;
        //Model.MDevice devinfo;
        public CSendDeviceOrder()
        {
            dbo.Open();
        }



        /// <summary>
        /// 发送堆垛机命令
        /// </summary>
        /// <param name="MessageIndex">消息编号</param>
        /// <param name="TaskIndex">任务编号</param>
        /// <param name="Order">堆垛机命令字</param>
        ///1-复位 
        ///2-将取 
        ///3-将送
        ///4-取货
        ///5-放货
        ///6-取放货
        /// <param name="DeviceIndex">设备编号</param>
        /// <param name="StartX">起始x坐标,排-沿轨道方向</param>
        /// <param name="StartY">起始y坐标,层-高度方向</param>
        /// <param name="StartZ">起始z坐标,列-面向堆垛机操作面板,1-左侧,2-右侧</param>
        /// <param name="EndX">目标x坐标,列-沿轨道方向</param>
        /// <param name="EndY">目标y坐标,层-高度方向</param>
        /// <param name="EndZ">目标z坐标,排-面向堆垛机操作面板,1-左侧,2-右侧</param>
        /// <returns>发送堆垛机命令是否成功</returns>
        public bool SendDeviceOrder(int MessageIndex, int TaskIndex, int Order, int DeviceIndex, int StartX, int StartY, int StartZ, int EndX, int EndY, int EndZ)
        {//20120820

            string barcode = GetBarcodeFromMonitorIndex(TaskIndex);
            int sn = 0; int UseAwayFork = 0;
            devinfo = Model.CGetInfo.GetDeviceInfo(DeviceIndex);
            if (devinfo.YCoor == 0) return false;
            try
            {
                int[] sendmes = new int[10] { MessageIndex, TaskIndex, Order, DeviceIndex, StartX, StartY, StartZ, EndX, EndY, EndZ };
                devinfo.SendMessage = sendmes;
                Model.CGetInfo.SetDeviceMessage(devinfo);


                if (devinfo == null)
                {
                    _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:在设备表中没找到设备所引!";
                    return false;
                }
                else
                {
                    if (devinfo.DeviceKind != 1)
                    {//堆垛机使用此方法
                        _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:堆垛机和RGV以外的设备使用此方法不正确!";
                        return false;
                    }
                    #region 堆垛机

                    if (devinfo.DeviceKind == 1)
                    {
                        int[] startz = new int[devinfo.ForkAmount];
                        int[] endz = new int[devinfo.ForkAmount];
                        if (devinfo.IfCorrelDoubleFork == "1")
                        { 
                            #region 多叉堆垛机
                            //堆垛机的原点属性
                            char[] sp = new char[1] { ',' };
                            string[] yd = devinfo.StackZeroColLayer.Split(sp);
                            int zeroXcoor = 0;
                            if (yd.GetLength(0) > 0)
                            {
                                zeroXcoor = Convert.ToInt32(yd[0]);
                            }
                            else
                            {
                                _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:堆垛机的原点坐标没有填写!";
                                return false;
                            }
                            for (int i = 0; i < devinfo.ForkAmount; i++)
                            {
                                startz[i] = 0;
                                endz[i] = 0;
                            }
                           

                            #region 堆垛机的双叉取货指令,在此决定分配货叉、同步还是异步发送
                            if ((Order == 4) || (Order == 2))
                            {
                                EndX = 0; EndY = 0; EndZ = 0;

                                int mti = Model.CGeneralFunction.GetManageTaskKindIndexFromMonitor(TaskIndex);
                                int fid = Model.CGeneralFunction.GetManageTaskIndexfromMonitor(TaskIndex);
                                #region 分配货叉,修改路径的双叉自关联站台信息

                                //如果不是多叉关联任务:ST_CELL的FDoubleFork=0,则奇数列使用近货叉,偶数列使用远货叉;否则货叉按照ST_CELL的FDoubleFork的值
                                Dictionary<int, string[]> rr = Model.CGeneralFunction.GetDoubleForkMonitorInfo(TaskIndex, DeviceIndex);
                                if (rr == null)
                                {
                                    #region 无关联任务

                                    //如果F_UseAwayFork='0',分配货叉,否则已经分配好货叉无需再分配
                                    if (Model.CGeneralFunction.GetUseAwayFork(TaskIndex) == "0")
                                    {
                                        UseAwayFork = Model.CGeneralFunction.GetDoubleForkFromST_CELL(StartZ, StartX, StartY, Model.CGeneralFunction.GetWAREHOUSEFromSTCELL(DeviceIndex));
                                        if (UseAwayFork == 0)
                                        {
                                            devinfo = Model.CGetInfo.GetDeviceInfo(DeviceIndex);
                                            if (devinfo != null)
                                            {
                                                int stackno = 0;
                                                if (devinfo.VirtualStack > 0)
                                                {
                                                    stackno = devinfo.VirtualStack;
                                                }
                                                else
                                                {
                                                    stackno = DeviceIndex;
                                                }
                                                #region 巷道货位判断是否为极限列,以极限列为准分配货叉
                                                sql.Clear();
                                                sql.Append("SELECT F_ForwardLimitX,F_BackLimitX FROM T_Base_LaneInfo WHERE  F_StackIndex = ").Append(stackno).Append(" and F_ForwardLimitX>0 and F_BackLimitX>0");
                                                DataView dvl = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                                                if ((devinfo.IfCorrelDoubleFork == "1") && (dvl.Count > 0))
                                                {

                                                    if (zeroXcoor < Convert.ToInt32(dvl[0]["F_ForwardLimitX"]))
                                                    {//如果原点列坐标小于ForwardLimitX,检查ForwardLimitX至ForwardLimitX+(n-2);
                                                        if ((StartX - Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) >= 0) && ((StartX - Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) <= (devinfo.ForkAmount - 2))))
                                                        {
                                                            UseAwayFork = (StartX - Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) + 1);
                                                        }
                                                        else if ((EndX - Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) >= 0) && ((EndX - Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) <= (devinfo.ForkAmount - 2))))
                                                        {
                                                            UseAwayFork = (EndX - Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) + 1);
                                                        }
                                                    }
                                                    else if (zeroXcoor > Convert.ToInt32(dvl[0]["F_ForwardLimitX"]))
                                                    {//如果原点列坐标大于ForwardLimitX,检查ForwardLimitX至ForwardLimitX-(n-2).
                                                        if ((Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) - StartX >= 0) && ((Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) - StartX <= (devinfo.ForkAmount - 2))))
                                                        {
                                                            UseAwayFork = (Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) - StartX + 1);
                                                        }
                                                        else if ((Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) - EndX >= 0) && ((Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) - EndX <= (devinfo.ForkAmount - 2))))
                                                        {
                                                            UseAwayFork = (Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) - EndX + 1);
                                                        }
                                                    }

                                                    if (zeroXcoor < Convert.ToInt32(dvl[0]["F_BackLimitX"]))
                                                    {//如果原点列坐标小于F_BackLimitX,检查F_BackLimitX至F_BackLimitX-(n-2);
                                                        if ((Convert.ToInt32(dvl[0]["F_BackLimitX"]) - StartX >= 0) && ((Convert.ToInt32(dvl[0]["F_BackLimitX"]) - StartX <= (devinfo.ForkAmount - 2))))
                                                        {
                                                            UseAwayFork = (devinfo.ForkAmount - (Convert.ToInt32(dvl[0]["F_BackLimitX"]) - StartX));
                                                        }
                                                        else if ((Convert.ToInt32(dvl[0]["F_BackLimitX"]) - EndX >= 0) && ((Convert.ToInt32(dvl[0]["F_BackLimitX"]) - EndX <= (devinfo.ForkAmount - 2))))
                                                        {
                                                            UseAwayFork = (devinfo.ForkAmount - (Convert.ToInt32(dvl[0]["F_BackLimitX"]) - EndX));
                                                        }

                                                    }
                                                    else if (zeroXcoor > Convert.ToInt32(dvl[0]["F_BackLimitX"]))
                                                    {//如果原点列坐标大于F_BackLimitX,检查F_BackLimitX至F_BackLimitX+(n-2).
                                                        if ((StartX - Convert.ToInt32(dvl[0]["F_BackLimitX"]) >= 0) && ((StartX - Convert.ToInt32(dvl[0]["F_BackLimitX"]) <= (devinfo.ForkAmount - 2))))
                                                        {
                                                            UseAwayFork = (devinfo.ForkAmount - (StartX - Convert.ToInt32(dvl[0]["F_BackLimitX"])));
                                                        }
                                                        else if ((EndX - Convert.ToInt32(dvl[0]["F_BackLimitX"]) >= 0) && ((EndX - Convert.ToInt32(dvl[0]["F_BackLimitX"]) <= (devinfo.ForkAmount - 2))))
                                                        {
                                                            UseAwayFork = (devinfo.ForkAmount - (EndX - Convert.ToInt32(dvl[0]["F_BackLimitX"])));
                                                        }
                                                    }


                                                }
                                                #endregion
                                            }
                                            if (UseAwayFork == 0)
                                            {
                                                if ((StartX % devinfo.ForkAmount) == 0)
                                                {
                                                    UseAwayFork = devinfo.ForkAmount;
                                                }
                                                else
                                                {
                                                    UseAwayFork = StartX % devinfo.ForkAmount;
                                                }
                                            }
                                        }
                                        if (UseAwayFork > devinfo.ForkAmount)
                                        {
                                            CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "发送多叉堆垛机命令", DeviceIndex.ToString(), barcode.ToCharArray() + ",分配货叉失败,排:" + StartZ.ToString() + "列:" + StartX.ToString() + "层:" + StartY.ToString() + ",货叉总数" + devinfo.ForkAmount.ToString() + ",分配的实际货叉" + UseAwayFork.ToString());
                                            _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + barcode + ",分配货叉失败,排:" + StartZ.ToString() + "列:" + StartX.ToString() + "层:" + StartY.ToString() + ",货叉总数" + devinfo.ForkAmount.ToString() + ",分配的实际货叉" + UseAwayFork.ToString();
                                            return false;
                                        }
                                        //20111226同时考虑调整路径所选站台和提前检测
                                        bool rp = SetLaneGateReplace(mti, fid, DeviceIndex, TaskIndex, UseAwayFork);//20120217

                                        sql.Clear();
                                        sql.Append("UPDATE T_Monitor_Task SET F_UseAwayFork = '").Append(UseAwayFork).Append("' WHERE (F_ManageTaskIndex = ")
                                            .Append(fid).Append(") AND (F_ManageTASKKINDINDEX = ")
                                            .Append(mti).Append(") AND F_DeviceIndex = ").Append(DeviceIndex);
                                        dbo.ExecuteSql(sql.ToString());
                                        if (rp == true) return false;//20120217


                                    }
                                    else
                                    {
                                        UseAwayFork = Convert.ToInt32(Model.CGeneralFunction.GetUseAwayFork(TaskIndex));
                                        if (UseAwayFork > devinfo.ForkAmount)
                                        {
                                            CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "发送多叉堆垛机命令", DeviceIndex.ToString(), barcode.ToCharArray() + ",获取任务时分配的货叉错误,排:" + StartZ.ToString() + "列:" + StartX.ToString() + "层:" + StartY.ToString() + ",货叉总数" + devinfo.ForkAmount.ToString() + ",分配的实际货叉" + UseAwayFork.ToString());
                                            _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + barcode + ",获取任务时分配的货叉错误,排:" + StartZ.ToString() + "列:" + StartX.ToString() + "层:" + StartY.ToString() + ",货叉总数" + devinfo.ForkAmount.ToString() + ",分配的实际货叉" + UseAwayFork.ToString();
                                            return false;
                                        }
                                        //20111226同时考虑调整路径所选站台和提前检测
                                        bool rp = SetLaneGateReplace(mti, fid, DeviceIndex, TaskIndex, UseAwayFork);//20120217
                                        sql.Clear();
                                        sql.Append("UPDATE T_Monitor_Task SET F_UseAwayFork = '").Append(UseAwayFork).Append("' WHERE (F_ManageTaskIndex = ")
                                            .Append(fid).Append(") AND (F_ManageTASKKINDINDEX = ")
                                            .Append(mti).Append(") AND F_DeviceIndex = ").Append(DeviceIndex);
                                        dbo.ExecuteSql(sql.ToString());
                                        if (rp == true) return false;//20120217
                                    }
                                    
                                    #endregion
                                }
                                else
                                {
                                    #region 有关联任务
                                    Dictionary<int, double> minzerodis = new Dictionary<int, double>();
                                    Dictionary<int, string[]> rrnew = rr;
                                    int mintask = 0; double minDist = 0; int[] tasks;
                                    while (rrnew.Keys.Count > 0)
                                    {
                                        tasks = new int[rrnew.Keys.Count];
                                        rrnew.Keys.CopyTo(tasks, 0);
                                        //计算任务离原点的距离由小到大排序
                                        Model.CGeneralFunction.GetMinZeroDistanceTask(tasks, devinfo, Order, out mintask, out minDist);
                                        minzerodis.Add(mintask, minDist);
                                        rrnew.Remove(mintask);
                                    }
                                    int forkno = 1; int tempStartX = 0, tempEndX = 0;
                                    bool Ifreturn = false;
                                    foreach (int task in minzerodis.Keys)
                                    {
                                        UseAwayFork = 0;
                                        mti = Model.CGeneralFunction.GetManageTaskKindIndexFromMonitor(task);
                                        fid = Model.CGeneralFunction.GetManageTaskIndexfromMonitor(task);
                                        if (Model.CGeneralFunction.GetUseAwayFork(task) == "0")
                                        {
                                            //未分配货叉,判断是否为极限货位,n叉考虑极限货位的n-1列;
                                            #region 巷道货位判断是否为极限列,以极限列为准分配货叉
                                            int stackno = 0;
                                            if (devinfo.VirtualStack > 0)
                                            {
                                                stackno = devinfo.VirtualStack;
                                            }
                                            else
                                            {
                                                stackno = DeviceIndex;
                                            }
                                            sql.Clear();
                                            sql.Append("SELECT F_ForwardLimitX,F_BackLimitX FROM T_Base_LaneInfo WHERE  F_StackIndex = ").Append(stackno).Append(" and F_ForwardLimitX>0 and F_BackLimitX>0");
                                            DataView dvl = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                                            if ((devinfo.IfCorrelDoubleFork == "1") && (dvl.Count > 0))
                                            {
                                                tempStartX = Model.CGeneralFunction.GetXCoorFromMonitor(task, DeviceIndex, 4);
                                                tempEndX = Model.CGeneralFunction.GetXCoorFromMonitor(task, DeviceIndex, 5);

                                                if (zeroXcoor < Convert.ToInt32(dvl[0]["F_ForwardLimitX"]))
                                                {//如果原点列坐标小于ForwardLimitX,检查ForwardLimitX至ForwardLimitX+(n-2);
                                                    if ((tempStartX - Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) >= 0) && ((tempStartX - Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) <= (devinfo.ForkAmount - 2))))
                                                    {
                                                        UseAwayFork = (tempStartX - Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) + 1);
                                                    }
                                                    else if ((tempEndX - Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) >= 0) && ((tempEndX - Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) <= (devinfo.ForkAmount - 2))))
                                                    {
                                                        UseAwayFork = (tempEndX - Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) + 1);
                                                    }
                                                }
                                                else if (zeroXcoor > Convert.ToInt32(dvl[0]["F_ForwardLimitX"]))
                                                {//如果原点列坐标大于ForwardLimitX,检查ForwardLimitX至ForwardLimitX-(n-2).
                                                    if ((Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) - tempStartX >= 0) && ((Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) - tempStartX <= (devinfo.ForkAmount - 2))))
                                                    {
                                                        UseAwayFork = (Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) - tempStartX + 1);
                                                    }
                                                    else if ((Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) - tempEndX >= 0) && ((Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) - tempEndX <= (devinfo.ForkAmount - 2))))
                                                    {
                                                        UseAwayFork = (Convert.ToInt32(dvl[0]["F_ForwardLimitX"]) - tempEndX + 1);
                                                    }
                                                }

                                                if (zeroXcoor < Convert.ToInt32(dvl[0]["F_BackLimitX"]))
                                                {//如果原点列坐标小于F_BackLimitX,检查F_BackLimitX至F_BackLimitX-(n-2);
                                                    if ((Convert.ToInt32(dvl[0]["F_BackLimitX"]) - tempStartX >= 0) && ((Convert.ToInt32(dvl[0]["F_BackLimitX"]) - tempStartX <= (devinfo.ForkAmount - 2))))
                                                    {
                                                        UseAwayFork = (devinfo.ForkAmount - (Convert.ToInt32(dvl[0]["F_BackLimitX"]) - tempStartX));
                                                    }
                                                    else if ((Convert.ToInt32(dvl[0]["F_BackLimitX"]) - tempEndX >= 0) && ((Convert.ToInt32(dvl[0]["F_BackLimitX"]) - tempEndX <= (devinfo.ForkAmount - 2))))
                                                    {
                                                        UseAwayFork = (devinfo.ForkAmount - (Convert.ToInt32(dvl[0]["F_BackLimitX"]) - tempEndX));
                                                    }

                                                }
                                                else if (zeroXcoor > Convert.ToInt32(dvl[0]["F_BackLimitX"]))
                                                {//如果原点列坐标大于F_BackLimitX,检查F_BackLimitX至F_BackLimitX+(n-2).
                                                    if ((tempStartX - Convert.ToInt32(dvl[0]["F_BackLimitX"]) >= 0) && ((tempStartX - Convert.ToInt32(dvl[0]["F_BackLimitX"]) <= (devinfo.ForkAmount - 2))))
                                                    {
                                                        UseAwayFork = (devinfo.ForkAmount - (tempStartX - Convert.ToInt32(dvl[0]["F_BackLimitX"])));
                                                    }
                                                    else if ((tempEndX - Convert.ToInt32(dvl[0]["F_BackLimitX"]) >= 0) && ((tempEndX - Convert.ToInt32(dvl[0]["F_BackLimitX"]) <= (devinfo.ForkAmount - 2))))
                                                    {
                                                        UseAwayFork = (devinfo.ForkAmount - (tempEndX - Convert.ToInt32(dvl[0]["F_BackLimitX"])));
                                                    }
                                                }


                                            }
                                            #endregion
                                            //和堆垛机原点坐标做差取绝对值,值最小的是1叉,货叉已经分配过的不要重复
                                            if (UseAwayFork == 0)
                                            {
                                                UseAwayFork = forkno;
                                            }
                                        }
                                        else
                                        {
                                            UseAwayFork = Convert.ToInt32(Model.CGeneralFunction.GetUseAwayFork(task));
                                        }
                                        #region 如果货叉已经被关联任务占用,极限列会出现,需要剔除关联关系
                                        if (IfDeleteRelative(mti, fid, task, UseAwayFork) == true)
                                        {
                                            return false;
                                        }
                                        #endregion
                                        if (UseAwayFork > devinfo.ForkAmount)
                                        {
                                            CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "发送多叉堆垛机命令", DeviceIndex.ToString(), barcode.ToCharArray() + ",关联任务分配货叉错误,排:" + StartZ.ToString() + "列:" + StartX.ToString() + "层:" + StartY.ToString() + ",货叉总数" + devinfo.ForkAmount.ToString() + ",分配的实际货叉" + UseAwayFork.ToString());
                                            _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + barcode + ",关联任务分配货叉错误,排:" + StartZ.ToString() + "列:" + StartX.ToString() + "层:" + StartY.ToString() + ",货叉总数" + devinfo.ForkAmount.ToString() + ",分配的实际货叉" + UseAwayFork.ToString();
                                            
                                            dbo.ExecuteSql(string.Format("UPDATE T_Manage_Task SET F_RELATIVECONTORLID = - 1 WHERE (F_ManageTaskKindIndex = {0}) AND (FID = {1})", mti, fid));
                                            return false;
                                        }
                                        forkno = UseAwayFork;
                                        
                                        //20111226同时考虑调整路径所选站台和提前检测
                                        bool rp = SetLaneGateReplace(mti, fid, DeviceIndex, task, UseAwayFork);//20120217
                                        if (rp == true) Ifreturn = true;
                                        sql.Clear();
                                        sql.Append("UPDATE T_Monitor_Task SET F_UseAwayFork = '").Append(UseAwayFork).Append("' WHERE (F_ManageTaskIndex = ")
                                            .Append(fid).Append(") AND (F_ManageTASKKINDINDEX = ")
                                            .Append(mti).Append(") AND F_DeviceIndex = ").Append(DeviceIndex);
                                        dbo.ExecuteSql(sql.ToString());

                                        forkno++;
                                    }
                                    if (Ifreturn == true) return false;
                                    #endregion
                                }
                                #endregion

                                #region 同步还是异步发送


                                int[] mutitasks = Model.CGeneralFunction.MutiForkIfSync(TaskIndex, DeviceIndex, devinfo.DeviceKind);
                                if (mutitasks != null)
                                {
                                    foreach (int temptask in mutitasks)
                                    {
                                        UseAwayFork = Convert.ToInt32(Model.CGeneralFunction.GetUseAwayFork(temptask));
                                        if (temptask == TaskIndex)
                                        {
                                            if (StartX > zeroXcoor)
                                            {
                                                StartX = StartX - (UseAwayFork - 1);
                                            }
                                            else
                                            {
                                                StartX = StartX + (UseAwayFork - 1);
                                            }
                                        }
                                        startz[UseAwayFork - 1] = Model.CGeneralFunction.GetZCoorFromMonitor(temptask, DeviceIndex, Order);
                                        if (startz[UseAwayFork - 1] != 0)
                                        {
                                            if (startz[UseAwayFork - 1] % 2 == 0)
                                            {
                                                startz[UseAwayFork - 1] = 2;
                                            }
                                            else
                                            {
                                                startz[UseAwayFork - 1] = 1;
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    UseAwayFork = Convert.ToInt32(Model.CGeneralFunction.GetUseAwayFork(TaskIndex));
                                    if (StartX > zeroXcoor)
                                    {
                                        StartX = StartX - (UseAwayFork - 1);
                                    }
                                    else
                                    {
                                        StartX = StartX + (UseAwayFork - 1);
                                    }

                                    startz[UseAwayFork - 1] = StartZ;
                                    if (startz[UseAwayFork - 1] != 0)
                                    {
                                        if (startz[UseAwayFork - 1] % 2 == 0)
                                        {
                                            startz[UseAwayFork - 1] = 2;
                                        }
                                        else
                                        {
                                            startz[UseAwayFork - 1] = 1;
                                        }
                                    }

                                }

                            }
                                #endregion

                            #region 堆垛机的双叉送货指令,在此决定同步还是异步发送

                            if ((Order == 5) || (Order == 3))
                            {
                                UseAwayFork = Convert.ToInt32(Model.CGeneralFunction.GetUseAwayFork(TaskIndex));
                                #region 同步还是异步发送
                                int[] mutitasks = Model.CGeneralFunction.MutiForkIfSync(TaskIndex, DeviceIndex, devinfo.DeviceKind);
                                if (mutitasks != null)
                                {
                                    foreach (int temptask in mutitasks)
                                    {
                                        UseAwayFork = Convert.ToInt32(Model.CGeneralFunction.GetUseAwayFork(temptask));
                                        if (temptask == TaskIndex)
                                        {
                                            if (EndX > zeroXcoor)
                                            {
                                                EndX = EndX - (UseAwayFork - 1);
                                            }
                                            else
                                            {
                                                EndX = EndX + (UseAwayFork - 1);
                                            }
                                        }
                                        endz[UseAwayFork - 1] = Model.CGeneralFunction.GetZCoorFromMonitor(temptask, DeviceIndex, Order);
                                        if (endz[UseAwayFork - 1] != 0)
                                        {
                                            if (endz[UseAwayFork - 1] % 2 == 0)
                                            {
                                                endz[UseAwayFork - 1] = 2;
                                            }
                                            else
                                            {
                                                endz[UseAwayFork - 1] = 1;
                                            }
                                        }
                                    }

                                }
                                else
                                {

                                    if (EndX > zeroXcoor)
                                    {
                                        EndX = EndX - (UseAwayFork - 1);
                                    }
                                    else
                                    {
                                        EndX = EndX + (UseAwayFork - 1);
                                    }

                                    endz[UseAwayFork - 1] = EndZ;
                                    if (endz[UseAwayFork - 1] != 0)
                                    {
                                        if (endz[UseAwayFork - 1] % 2 == 0)
                                        {
                                            endz[UseAwayFork - 1] = 2;
                                        }
                                        else
                                        {
                                            endz[UseAwayFork - 1] = 1;
                                        }
                                    }

                                }
                                #endregion

                            }

                            #endregion
                            //9,11,13
                            int arrAmout = 9 + (devinfo.ForkAmount - 1) * 2;
                            int arrsn = 0; StringBuilder strap = new StringBuilder();
                            StringBuilder[] itemnames = new StringBuilder[arrAmout];
                            StringBuilder[] itemvalues = new StringBuilder[arrAmout];
                            for (int i = 0; i < arrAmout; i++)
                            {
                                itemnames[i] = new StringBuilder();
                                itemvalues[i] = new StringBuilder();
                            }
                            #endregion

                            sn = devinfo.Dbw1Address;
                            itemnames[0].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 0)).Append(",b");
                            itemvalues[0].Append("0");
                            itemnames[1].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 1)).Append(",b");
                            itemvalues[1].Append("0");

                            itemnames[2].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 2)).Append(",i");
                            itemvalues[2].Append(TaskIndex.ToString());
                            itemnames[3].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 4)).Append(",b");
                            itemvalues[3].Append(StartX.ToString());
                            itemnames[4].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 5)).Append(",b");
                            itemvalues[4].Append(StartY.ToString());

                            for (int i = 1; i <= devinfo.ForkAmount; i++)
                            {
                                itemnames[4 + i].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 5 + i)).Append(",b");
                                itemvalues[4 + i].Append(startz[i - 1].ToString());
                                strap.Append(i.ToString()).Append("叉取排Z:").Append(startz[i - 1].ToString()).Append(";");
                            }

                            arrsn = 4 + devinfo.ForkAmount;

                            itemnames[arrsn + 1].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + arrsn + 2)).Append(",b");
                            itemvalues[arrsn + 1].Append(EndX.ToString());
                            itemnames[arrsn + 2].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + arrsn + 3)).Append(",b");
                            itemvalues[arrsn + 2].Append(EndY.ToString());
                            for (int i = 1; i <= devinfo.ForkAmount; i++)
                            {
                                itemnames[arrsn + 2 + i].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + arrsn + 3 + i)).Append(",b");
                                itemvalues[arrsn + 2 + i].Append(endz[i - 1].ToString());
                                strap.Append(i.ToString()).Append("叉送排Z:").Append(endz[i - 1].ToString()).Append(";");
                            }

                            
                            CCommonOPCClient.Hostname = CommonClassLib.AppSettings.GetValue("HostName");//20090922 devinfo.RemoteIP;
                            CCommonOPCClient.ProgID = CommonClassLib.AppSettings.GetValue("OPCProgID");
                            CCommonOPCClient.PlcConnectionID = devinfo.S7Connection;//20110216
                            if (CCommonOPCClient.SyncWriteAllItemValue(itemnames, itemvalues) == false)
                            {
                                _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + CCommonOPCClient.OpcError;
                                return false;
                            }
                            itemvalues[0].Remove(0, itemvalues[0].Length);
                            itemvalues[0].Append(MessageIndex.ToString());
                            itemvalues[1].Remove(0, itemvalues[1].Length);
                            itemvalues[1].Append(Order.ToString());

                            if (CCommonOPCClient.SyncWriteAllItemValue(itemnames, itemvalues) == false)
                            {
                                _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + CCommonOPCClient.OpcError;
                                return false;
                            }
                            sss.Remove(0, sss.Length);
                            sss.Append("条码:").Append(barcode).Append("**写标志").Append(MessageIndex.ToString()).Append("**命令字" + Order.ToString()).Append("**任务号" + TaskIndex.ToString())
                                            .Append("**起始排" + StartZ.ToString()).Append("**起始列" + StartX.ToString()).Append("**起始层" + StartY.ToString())
                                            .Append("**终止排" + EndZ.ToString()).Append("**终止列" + EndX.ToString()).Append("**终止层" + EndY.ToString())
                                            .Append(";").Append(strap);

                            CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "发送多叉堆垛机命令", DeviceIndex.ToString(), sss.ToString());
                            #endregion
                        }
                        else
                        {
                            #region 单叉堆垛机

                            StringBuilder[] itemnames = { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder("") };
                            StringBuilder[] itemvalues = { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder("") };
                            #region 转换(Z)排坐标
                            if (devinfo.StackReach == 2 && DeviceIndex != 11012)// 20190723  双伸堆垛机Z坐标转换
	                        {

                                if (StartZ != 0)
                                {
                                    if (StartZ % 4 == 0)
                                    {
                                        StartZ = 4;
                                    }
                                    else
                                    {
                                        StartZ = StartZ % 4;
                                    }
                                }
                                if (EndZ != 0)
                                {
                                    if (EndZ % 4 == 0)
                                    {
                                        EndZ = 4;
                                    }
                                    else
                                    {
                                        EndZ = EndZ % 4;
                                    }
                                }

	                        }
                            else if (DeviceIndex == 11012)
                            {
                                if (StartZ != 0)
                                {
                                    if ((StartZ + 2) % 4 == 0)
                                    {
                                        StartZ = 4;
                                    }
                                    else
                                    {
                                        StartZ = (StartZ + 2) % 4;
                                    }
                                } 
                                if (EndZ != 0)
                                {
                                    if ((EndZ + 2) % 4 == 0)
                                    {
                                        EndZ = 4;
                                    }
                                    else
                                    {
                                        EndZ = (EndZ+2) % 4;
                                    }
                                }
                            }
                            else
                            {
                                if (StartZ != 0)
                                {
                                    if (StartZ % 2 == 0)
                                    {
                                        StartZ = 2;
                                    }
                                    else
                                    {
                                        StartZ = 1;
                                    }
                                }
                                if (EndZ != 0)
                                {
                                    if (EndZ % 2 == 0)
                                    {
                                        EndZ = 2;
                                    }
                                    else
                                    {
                                        EndZ = 1;
                                    }
                                }
                            }
                           
                            


                            #endregion

                            //byte0,byte1,byte2,byte3,byte4
                            //      int1         int3       
                            //int0(byte0,byte1);int1(byte1,byte2);int2(byte2,byte3);int3(byte3,byte4)
                            sn = Convert.ToInt32(devinfo.Dbw1Address);

                            itemnames[0].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 2)).Append(",i");
                            itemvalues[0].Append(TaskIndex.ToString());
                            itemnames[1].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 4)).Append(",b");
                            itemvalues[1].Append((StartX).ToString());
                            itemnames[2].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 5)).Append(",b");
                            itemvalues[2].Append(StartY.ToString());
                            itemnames[3].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 6)).Append(",b");
                            itemvalues[3].Append(StartZ.ToString());
                            itemnames[4].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 8)).Append(",b");
                            itemvalues[4].Append((EndX).ToString());
                            itemnames[5].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 9)).Append(",b");
                            itemvalues[5].Append(EndY.ToString());
                            itemnames[6].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 10)).Append(",b");
                            itemvalues[6].Append(EndZ.ToString());
                            //itemnames[7].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 0)).Append(",b");
                            //itemvalues[7].Append(MessageIndex.ToString());
                            //itemnames[8].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 1)).Append(",b");
                            //itemvalues[8].Append(Order.ToString());

                            CCommonOPCClient.Hostname = CommonClassLib.AppSettings.GetValue("HostName");//20090922 devinfo.RemoteIP;
                            CCommonOPCClient.ProgID = CommonClassLib.AppSettings.GetValue("OPCProgID");
                            CCommonOPCClient.PlcConnectionID = devinfo.S7Connection;//20110216
                            if (CCommonOPCClient.SyncWriteAllItemValue(itemnames, itemvalues) == false)//注释,用异步通信方式
                            {
                                _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + CCommonOPCClient.OpcError;
                                return false;
                            }
                            //itemvalues[7].Remove(0, itemvalues[7].Length);
                            //itemvalues[7].Append(MessageIndex.ToString());
                            //itemvalues[8].Remove(0, itemvalues[8].Length);
                            //itemvalues[8].Append(Order.ToString());
                            itemnames[7].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 0)).Append(",b");
                            itemvalues[7].Append(MessageIndex.ToString());
                            itemnames[8].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 1)).Append(",b");
                            itemvalues[8].Append(Order.ToString());

                            //if (CCommonOPCClient.SyncWriteAllItemValue(itemnames, itemvalues) == false)
                            if (CCommonOPCClient.ASyncWriteAllItemValue(itemnames, itemvalues) == false)
                            {
                                _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + CCommonOPCClient.OpcError;
                                return false;
                            }
                            sss.Remove(0, sss.Length);
                            sss.Append("条码:").Append(barcode).Append("**写标志").Append(MessageIndex.ToString()).Append("**命令字" + Order.ToString()).Append("**任务号" + TaskIndex.ToString())
                                            .Append("**起始排" + StartZ.ToString()).Append("**起始列" + StartX.ToString()).Append("**起始层" + StartY.ToString())
                                            .Append("**终止排" + EndZ.ToString()).Append("**终止列" + EndX.ToString()).Append("**终止层" + EndY.ToString());

                            CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "发送堆垛机命令", DeviceIndex.ToString(), sss.ToString());
                            //if (WriteBarcode(DeviceIndex, TaskIndex) == false)
                            //{
                            //    return false;
                            //}

                            #endregion
                        }
                        if (WriteBarcode(DeviceIndex, TaskIndex) == false)
                        {
                            return false;
                        }
                    }

                    #endregion

                }
                return true;
            }
            catch (Exception ex)
            {
                _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + ex.Message;
                return false;
            }
            finally
            {
                devinfo = null;
            }
        }
        bool IfDeleteRelative(int mti, int fid, int moniTask,int useawayfork)
        {
            DataView dv = new DataView();
            try
            {
                int relfid= Model.CGeneralFunction.GetRelativeControlID(mti, fid);
                sql.Clear();
                sql.Append("SELECT DISTINCT T_Manage_Task.FID FROM T_Manage_Task,T_Monitor_Task where ")
                    .Append(" T_Manage_Task.F_ManageTaskKindIndex = T_Monitor_Task.F_ManageTASKKINDINDEX ")
                    .Append(" AND T_Manage_Task.FID = T_Monitor_Task.F_ManageTaskIndex  and ")
                    .Append(" (T_Manage_Task.F_RELATIVECONTORLID = ").Append(relfid).Append(") AND (T_Monitor_Task.F_UseAwayFork = '").Append(useawayfork).Append("') ")
                    .Append(" AND  (T_Monitor_Task.F_ManageTASKKINDINDEX = ").Append(mti).Append(") AND (T_Monitor_Task.F_ManageTaskIndex <> ").Append(fid).Append(")");

                dv=dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                if (dv.Count > 0)
                {
                    dbo.ExecuteSql(string .Format("UPDATE T_Manage_Task SET F_RELATIVECONTORLID = - 1 WHERE (F_ManageTaskKindIndex = {0}) AND (FID = {1})",mti,fid));
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dv.Dispose();
            }

        }
        private void GetLaneGateDeviceZXY(int StackIndex, int laneGate, out string DeviceZXY)
        {

            DeviceZXY = string.Empty;
            sql.Clear();
            sql.Append(string.Format("SELECT  T_Base_Lane_Gate.F_ZXY FROM T_Base_Lane_Gate,T_Base_LaneInfo where T_Base_Lane_Gate.F_LaneIndex = T_Base_LaneInfo.F_LaneDeviceIndex and T_Base_LaneInfo.F_StackIndex={0} and T_Base_Lane_Gate.F_LaneGateDeviceIndex={1}", StackIndex, laneGate));
            DataView dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
            if (dv.Count > 0)
            {
                DeviceZXY = dv[0][0].ToString();
            }
        }


        /// <summary>
        /// LHDF
        /// </summary>
        /// <param name="deviceindex"></param>
        /// <param name="type"></param>
        private void GetRGVGatePalletType(int taskindex, out int type)
        {

            int deviceindex = 0;
            type = 0;
            DataView dvr = null;
            string str = string.Format("select  FSTARTDEVICE, FENDDEVICE from  T_Manage_Task where  FID = {0}", Model.CGeneralFunction.GetManageTaskIndexfromMonitor(taskindex));
            DataView dv = dbo.ExceSQL(str).Tables[0].DefaultView;
            if (dv.Count > 0)
            {
                deviceindex = Convert.ToInt32(dv[0]["FSTARTDEVICE"].ToString());
                sql.Clear();
                sql.Append(string.Format("SELECT  F_TYPE FROM  T_Base_LaneInfo where  F_LaneDeviceIndex={0}", deviceindex));
                dvr = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                if (dvr.Count > 0)
                {
                    type = Convert.ToInt32(dvr[0][0].ToString());
                }
                else
                {
                    deviceindex = Convert.ToInt32(dv[0]["FENDDEVICE"].ToString());
                    sql.Clear();
                    sql.Append(string.Format("SELECT  F_TYPE FROM T_Base_LaneInfo where  F_LaneDeviceIndex={0}", deviceindex));
                    dvr = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                    if (dvr.Count > 0)
                    {
                        type = Convert.ToInt32(dvr[0][0].ToString());
                    }
                    else
                    {
                        type = 0;

                    }

                }
            }

        }


        /// <summary>
        /// 根据设备命令,PALLET_SIZE,STACK_TYPE\STACK_QTY
        /// </summary>
        /// <param name="TaskIndx"></param>
        /// <returns></returns>
        private int GetManageInfo(int TaskIndx,string Field)
        {
            DataView dv = new DataView();
            try
            {
                sql.Clear();
                sql.Append(string.Format("select {0} from T_Manage_Task where FID in(select F_ManageTaskIndex from T_Monitor_Task where F_MonitorIndex = {1})",Field, TaskIndx));
                dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                if (dv.Count > 0)
                {
                    return Convert.ToInt32(dv[0][Field]);
                }
                return -1;
            }
            catch (Exception ex)
            {
                
                throw ex;
            }
            finally
            {
                dv.Dispose();
            }

        }


        /// <summary>
        /// 发送穿梭车、输送机设备命令 STACK_TYPE\STACK_QTY
        /// </summary>
        /// <param name="MessageIndex">消息编号</param>
        /// <param name="TaskIndex">任务编号</param>
        /// <param name="Order">命令字</param>
        /// 穿梭车命令字: 
        ///1-复位 
        ///2-左接货
        ///3-左送货
        ///4-右接货
        ///5-右送货
        ///6-停止
        ///7-运动(运动到第4、5字节指定的目标设备所引)
        ///输送机命令字:
        ///1-入库(朝向库)
        ///2-出库(背向库)
        ///3-送货
        ///4-接货
        ///5-停止
        /// <param name="DeviceIndex">设备编号</param>
        ///<param name="ArrowDeviceIndex">对于输送机、穿梭车代表目标设备所引,
        /// 0-代表单一设备控制,无目标设备所引;1…65535代表目标设备所引(终点输送机的设备所引)</param>
        /// <returns>发送穿梭车、输送机设备命令是否成功</returns>
        public bool SendDeviceOrder(int MessageIndex, int TaskIndex, int Order, int DeviceIndex, int ArrowDeviceIndex)
        {
            
            StringBuilder[] itemnames;
            StringBuilder[] itemvalues;
            
            devinfo = Model.CGetInfo.GetDeviceInfo(DeviceIndex);
            int iRemark = 0; // 备用字段1
            int iRemark2 = 0;// 备用字段2



            if (devinfo.XCoor == 0 && devinfo.YCoor == 0 && devinfo.DeviceKind == 4) return false;//20130510

            #region  旧版通信协议,目标设备两个byte 最大到32767 ,进行转换;新版4个byte不需要转换
            //if (ArrowDeviceIndex >= 32767)
            //{
            //    StringBuilder a1 = new StringBuilder(ArrowDeviceIndex.ToString().Substring(0, 1));
            //    if (ArrowDeviceIndex > 0)
            //    {
            //        StringBuilder a2 = new StringBuilder(ArrowDeviceIndex.ToString().Substring(2));
            //        a1.Append(a2);
            //    }
            //    ArrowDeviceIndex = Convert.ToInt32(a1.ToString());
            //}
            #endregion 


            string barcode = GetBarcodeFromMonitorIndex(TaskIndex);
            try
            {
                //int nowdev = GetNowDevice(TaskIndex);
                //if ((devinfo.DeviceKind == 13) && (nowdev != 0))
                //{
                //    devinfo = Model.CGetInfo.GetDeviceInfo(nowdev);
                //}
               
                int[] sendmes = new int[5] { MessageIndex, TaskIndex, Order, DeviceIndex, ArrowDeviceIndex };
                devinfo.SendMessage = sendmes;
                Model.CGetInfo.SetDeviceMessage(devinfo);
                int sn = 0;
                if (devinfo == null)
                {
                    _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:设备索引不存在!";
                    return false;
                }
                else
                {

                    #region LHDF 穿梭车需要提供托盘类型,1小2大先根据出入巷道判断托盘类型,再根据管理任务判断托盘类型,没有报错
                    if (devinfo.DeviceKind == 4 && (Order == 2 || Order==3))
                {
                    sn = Convert.ToInt32(devinfo.Dbw1Address);
                    // 找到命令入口输送线编号,发送到入口输送线DB1;电梯入口输送线索引:正常输送线+"2"
                    int type = 0;
                    GetRGVGatePalletType(TaskIndex, out type); //先根据出入巷道判断托盘类型
                    if (type == 0) //再根据管理任务判断托盘类型
                        {
                            type = GetGoodsHigh(TaskIndex);
                            if (type == 0)
                            {
                                _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:穿梭车" + DeviceIndex.ToString() + "没有找到托盘类型信息:" + type.ToString();
                                return false;
                            }
                        }




                    itemnames = new StringBuilder[5] { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder("") }; ;
                    itemvalues = new StringBuilder[5] { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder("") }; ;
                    itemnames[0].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 0)).Append(",b");
                    itemvalues[0].Append("0");
                    itemnames[1].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 1)).Append(",b");
                    itemvalues[1].Append(Order.ToString());
                    itemnames[2].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 2)).Append(",i");
                    itemvalues[2].Append(TaskIndex.ToString());
                    //itemnames[3].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 4)).Append(",i");
                    itemnames[3].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 4)).Append(",di"); // 新协议 目标位4byte
                    itemvalues[3].Append(ArrowDeviceIndex.ToString());
                    itemnames[4].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 8)).Append(",b"); // 新协议 目标位4byte
                    itemvalues[4].Append(type.ToString());

                    CCommonOPCClient.Hostname = CommonClassLib.AppSettings.GetValue("HostName");//20090922 devinfo.RemoteIP;
                    CCommonOPCClient.ProgID = CommonClassLib.AppSettings.GetValue("OPCProgID");
                    CCommonOPCClient.PlcConnectionID = devinfo.S7Connection;//20110216

                    if (CCommonOPCClient.SyncWriteAllItemValue(itemnames, itemvalues) == false)
                    {
                        _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + CCommonOPCClient.OpcError;
                        return false;
                    }
                    // 修改消息标记头,可以考虑一次性写入
                    itemnames[0].Remove(0, itemnames[0].Length);
                    itemnames[0].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 0)).Append(",b");
                    itemvalues[0].Remove(0, itemvalues[0].Length);
                    itemvalues[0].Append(MessageIndex);
                    if (CCommonOPCClient.SyncWriteAllItemValue(itemnames, itemvalues) == false)
                    {
                        _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + CCommonOPCClient.OpcError;
                        return false;
                    }

                    sss.Remove(0, sss.Length);
                    sss.Append("条码:").Append(barcode).Append("**写标志").Append(MessageIndex.ToString()).Append("**命令字" + Order.ToString()).Append("**任务号" + TaskIndex.ToString())
                                        .Append("**站台" + ArrowDeviceIndex.ToString()).Append("**托盘类型" + type.ToString());

                    CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "发送指令", devinfo.DeviceIndex.ToString(), sss.ToString());

                    return true;
                }
                #endregion


               
                    if (devinfo.DeviceKind == 7)
                    {
                        return true;
                    }
                    if (devinfo.DeviceKind == 1)
                    {//堆垛机不允许使用此方法
                        _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:堆垛机不允许使用此方法!";
                        return false;
                    }
                    //byte0,byte1,byte2,byte3,byte4
                    //      int1         int3       
                    //int0(byte0,byte1);int1(byte1,byte2);int2(byte2,byte3);int3(byte3,byte4)
                    sn = Convert.ToInt32(devinfo.Dbw1Address);
                    if (devinfo.DeviceKind == 31)
                    {
                        #region 高端输送
                        int reSendFlag = 0, HMISendDb1Address = 0;
                        GetHMISendInfo(out reSendFlag, out HMISendDb1Address, TaskIndex);//触摸屏申请重新发送20120220
                        int inworkbench = IfInworkBench(TaskIndex);
                        if (MessageIndex == 2)
                        {
                            barcode = "000000";
                            inworkbench = 0;
                        }
                        byte[] barbyte = new byte[6];
                        if (barcode.Length == 6)
                        {
                            barbyte = ASCIIEncoding.ASCII.GetBytes(barcode);
                        }
                        else
                        {
                            _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:高端工位输送机条码不合法!";
                            return false;
                        }
                        if (reSendFlag == 2)//触摸屏申请重新发送20120220devinfo.UseCommonDB == "1"
                        {
                            sn = HMISendDb1Address;
                            itemnames = new StringBuilder[10] 
                            { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), 
                                new StringBuilder(""), new StringBuilder(""), new StringBuilder(""),
                                new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder("") }; ;
                            itemvalues = new StringBuilder[10] 
                            { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""),
                                new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), 
                                new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder("") }; ;
                            itemnames[0].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 0)).Append(",b");
                            itemvalues[0].Append("0");

                            for (int i = 1; i <= 6; i++)
                            {

                                itemnames[i].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + i)).Append(",b");
                                itemvalues[i].Append(barbyte[i - 1]);
                            }

                            itemnames[7].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 7)).Append(",b");

                            itemvalues[7].Append(inworkbench);
                            itemnames[8].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 8)).Append(",i");
                            //20120207
                            StringBuilder a1 = new StringBuilder(devinfo.DeviceIndex.ToString().Substring(0, 1));
                            if (devinfo.DeviceIndex > 0)
                            {//托盘所在的当前设备索引
                                StringBuilder a2 = new StringBuilder(devinfo.DeviceIndex.ToString().Substring(2));
                                a1.Append(a2);
                            }
                            itemvalues[8].Append(a1.ToString());//托盘所在的当前设备索引
                            itemnames[9].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 10)).Append(",i");
                            itemvalues[9].Append(ArrowDeviceIndex.ToString());

                        }
                        else
                        {
                            itemnames = new StringBuilder[9] 
                            { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), 
                                new StringBuilder(""), new StringBuilder(""), new StringBuilder(""),
                                new StringBuilder(""), new StringBuilder(""), new StringBuilder("")}; ;
                            itemvalues = new StringBuilder[9] 
                            { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""),
                                new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), 
                                new StringBuilder(""), new StringBuilder(""), new StringBuilder("") }; ;
                            itemnames[0].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 0)).Append(",b");
                            itemvalues[0].Append("0");

                            for (int i = 1; i <= 6; i++)
                            {

                                itemnames[i].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + i)).Append(",b");
                                itemvalues[i].Append(barbyte[i - 1]);
                            }

                            itemnames[7].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 7)).Append(",b");
                            itemvalues[7].Append(inworkbench);
                            itemnames[8].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 8)).Append(",i");
                            itemvalues[8].Append(ArrowDeviceIndex.ToString());



                        }

                        #endregion
                    }
                    #region 急停按钮发送,类型40
                    else if (devinfo.DeviceKind == 40)
                    {
                        itemnames = new StringBuilder[1] { new StringBuilder("") };
                        itemvalues = new StringBuilder[1] { new StringBuilder("") };
                        itemnames[0].Append(Model.CGeneralFunction.DBSend).Append(",").Append(Convert.ToString(sn+0)).Append(",b"); 
                        itemvalues[0].Append(Order.ToString());
                        sss.Clear();
                        sss.Append("上位机发送紧急停车").Append(DeviceIndex).Append("***指令").Append(Order);
                    }
                    #endregion
                    else
                    {
                        #region 物流输送机
                        
                        if (devinfo.UseCommonDB == "1")
                        {
                            itemnames = new StringBuilder[5] { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder("") }; ;
                            itemvalues = new StringBuilder[5] { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder("") }; ;
                            itemnames[0].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 0)).Append(",b");
                            itemvalues[0].Append("0");
                            itemnames[1].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 1)).Append(",b");
                            itemvalues[1].Append(Order.ToString());
                            itemnames[2].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 2)).Append(",i");
                            itemvalues[2].Append(TaskIndex.ToString());
                            itemnames[3].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 4)).Append(",i");
                            itemvalues[3].Append(DeviceIndex.ToString());//起始设备编号(当前设备编号)
                            itemnames[4].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 6)).Append(",i");
                            itemvalues[4].Append(ArrowDeviceIndex.ToString());

                        }
                        else
                        {
                            
                            if (devinfo.IfCorrelDoubleFork == "1")
                            {//多叉关联站台任务
                                
                                devinfo = Model.CGetInfo.GetDeviceInfo(DeviceIndex);
                                sn = Convert.ToInt32(devinfo.Dbw1Address);
                                itemnames = new StringBuilder[6] { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder("") }; ;
                                itemvalues = new StringBuilder[6] { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder("") }; ;
                                itemnames[0].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 0)).Append(",b");
                                itemvalues[0].Append("0");
                                itemnames[1].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 1)).Append(",b");
                                itemvalues[1].Append(Order.ToString());
                                itemnames[2].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 2)).Append(",i");
                                itemvalues[2].Append(TaskIndex);
                                itemnames[3].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 4)).Append(",i");
                                itemvalues[3].Append(0);
                                itemnames[4].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 6)).Append(",i");
                                itemvalues[4].Append(0);
                                itemnames[5].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 8)).Append(",i");
                                itemvalues[5].Append(0);

                            }
                            else
                            {//普通输送机,双鹿增加备用1字节20200919,不需要默认0

                                itemnames = new StringBuilder[6] { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder("") }; ;
                                itemvalues = new StringBuilder[6] { new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder(""), new StringBuilder("") }; ;
                                itemnames[0].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 0)).Append(",b");
                                itemvalues[0].Append("0");
                                itemnames[1].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 1)).Append(",b");
                                itemvalues[1].Append(Order.ToString());
                                if (Order == 0 && TaskIndex >0)
                                {
                                    TaskIndex = 0; 
                                }
                                itemnames[2].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 2)).Append(",i");
                                itemvalues[2].Append(TaskIndex.ToString());
                                //itemnames[3].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 4)).Append(",i");
                                itemnames[3].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 4)).Append(",di"); // 新协议 目标位4byte
                                itemvalues[3].Append(ArrowDeviceIndex.ToString());
                                #region 需要使用备用字节的输送线数据
                                if (DeviceIndex == 22556 || DeviceIndex == 32536)
                                {
                                    // 20201027 增加得到GetPALLET_SIZE字段方法,管理任务得到 PALLET_SIZE 字段
                                    iRemark = GetManageInfo(TaskIndex, "PALLET_SIZE");
                                    if (iRemark < 0)
                                    {
                                        _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + DeviceIndex + "找不到子盘尺寸";
                                        return false;
                                    }
                                }
                                if (DeviceIndex == 42830 || DeviceIndex == 42840)
                                {
                                    // 20201027 双鹿 增加得到STACK_TYPE\STACK_QTY字段方法, 发送给机械手
                                    iRemark = GetManageInfo(TaskIndex, "STACK_TYPE");
                                    iRemark2 = GetManageInfo(TaskIndex, "STACK_QTY");
                                    if (iRemark < 0 || iRemark2 < 0)
                                    {
                                        if (Order == 0)
                                        {
                                            iRemark = 0;
                                            iRemark2 = 0;

                                        }
                                        else
                                        {
                                            _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + DeviceIndex + "找不到拆盘信息";
                                            return false;
                                        }
                                    }
                                }

                                itemnames[4].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 8)).Append(",b"); // 新协议 备用字节8、9 byte
                                itemvalues[4].Append(iRemark.ToString());
                                itemnames[5].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 9)).Append(",b"); // 新协议 备用字节8、9 byte
                                itemvalues[5].Append(iRemark2.ToString());

                                #endregion

                            }
                        }

                        #endregion


                    }
                }
                
                CCommonOPCClient.Hostname = CommonClassLib.AppSettings.GetValue("HostName");//20090922 devinfo.RemoteIP;
                CCommonOPCClient.ProgID = CommonClassLib.AppSettings.GetValue("OPCProgID");
                CCommonOPCClient.PlcConnectionID = devinfo.S7Connection;//20110216
                
                if (CCommonOPCClient.SyncWriteAllItemValue(itemnames, itemvalues) == false)
                {
                    _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + CCommonOPCClient.OpcError;
                    return false;
                }
                itemnames[0].Remove(0, itemnames[0].Length);
                itemnames[0].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 0)).Append(",b");
                itemvalues[0].Remove(0, itemvalues[0].Length);
                itemvalues[0].Append(MessageIndex);
                if (CCommonOPCClient.SyncWriteAllItemValue(itemnames, itemvalues) == false)
                {
                    _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + CCommonOPCClient.OpcError;
                    return false;
                }

                sss.Remove(0, sss.Length);
                sss.Append("条码:").Append(barcode).Append("**写标志").Append(MessageIndex.ToString()).Append("**命令字" + Order.ToString()).Append("**任务号" + TaskIndex.ToString())
                                    .Append("**目标位置" + ArrowDeviceIndex.ToString()).Append("**备注1:" + iRemark.ToString()).Append("**备注2:" + iRemark2.ToString());

                CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "发送指令", devinfo.DeviceIndex.ToString(), sss.ToString());
                //if (MessageIndex == 1)
                //{
                //    if (WriteBarcode(DeviceIndex, TaskIndex) == false)
                //    {
                //        return false;
                //    }
                //}
                return true;
            }
            catch (Exception ex)
            {
                _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + ex.Message;
                return false;
            }
            finally
            {
                devinfo = null;
                itemnames = null;
                itemvalues = null;
            }

        }

        private void GetHMISendInfo(out int reSendFlag, out int HMISendDb1Address, int taskindex)
        {//20120220
            reSendFlag = 0;
            HMISendDb1Address = 0;
            try
            {
                DataView dv = dbo.ExceSQL(string.Format("SELECT F_NumParam2, F_SendFlag  FROM  T_Monitor_Task where F_MonitorIndex={0}", taskindex)).Tables[0].DefaultView;
                if (dv.Count > 0)
                {
                    reSendFlag = Convert.ToInt32(dv[0]["F_SendFlag"]);
                    HMISendDb1Address = Convert.ToInt32(dv[0]["F_NumParam2"]);//触摸屏F_DBW1Address
                }
            }
            catch (Exception ex)
            {
                _commLayerError = "OPCClient.CSendDeviceOrder.GetHMISendInfo发生错误:" + ex.Message;

            }
        }

        /// <summary>
        /// 上位机给下位机发送烟箱按品牌码分道信息共15字节,有数据时写入实际数据,否则全部写零
        /// </summary>
        /// <param name="DeviceIndex">码垛位设备号索引</param>
        /// <param name="TobaccoCode">第3--15字节,烟箱码</param>
        /// <param name="HaveFirstProjectCode">第1字节,1-有一号工程码,0-无一号工程码</param>
        /// <param name="IfSmallTobacco">第2字节,1-异型烟箱,0-正常烟箱</param>
        /// <returns>发送烟箱按品牌码分道信息是否成功</returns>
        public bool SendDeviceOrder(int DeviceIndex, string TobaccoCode, bool HaveFirstProjectCode, bool IfSmallTobacco, int Count)
        {
            StringBuilder[] itemnames = new StringBuilder[16];
            StringBuilder[] itemvalues = new StringBuilder[16];
            devinfo = Model.CGetInfo.GetDeviceInfo(DeviceIndex);
            try
            {

                int sn = 0;

                if (devinfo == null)
                {
                    _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:设备所引不存在!";
                    return false;
                }
                else
                {
                    sn = Convert.ToInt32(devinfo.Dbw1Address);

                    itemnames[0].Append(Model.CGeneralFunction.DBSend).Append(".").Append((sn + 0).ToString()).Append(",b");
                    if (HaveFirstProjectCode == true)
                    {
                        itemvalues[0].Append("1");
                    }
                    else
                    {
                        itemvalues[0].Append("0");
                    }
                    itemnames[1].Append(Model.CGeneralFunction.DBSend).Append(".").Append((sn + 1).ToString()).Append(",b");
                    if (IfSmallTobacco == true)
                    {
                        itemvalues[1].Append("1");
                    }
                    else
                    {
                        itemvalues[1].Append("0");
                    }
                    for (int i = 2; i <= 14; i++)
                    {
                        itemnames[i].Append(Model.CGeneralFunction.DBSend).Append(".").Append((sn + i).ToString()).Append(",b");
                        itemvalues[i].Append(Strings.Asc(TobaccoCode.Substring(i - 2, 1)).ToString());
                    }
                    itemnames[15].Append(Model.CGeneralFunction.DBSend).Append(".").Append((sn + 15).ToString()).Append(",b");
                    itemvalues[15].Append(Count.ToString());

                    CCommonOPCClient.Hostname = CommonClassLib.AppSettings.GetValue("HostName");//20090922 devinfo.RemoteIP;
                    CCommonOPCClient.ProgID = CommonClassLib.AppSettings.GetValue("OPCProgID");
                    CCommonOPCClient.PlcConnectionID = devinfo.S7Connection;//20110216
                    if (CCommonOPCClient.SyncWriteAllItemValue(itemnames, itemvalues) == false)
                    {
                        return false;
                    }
                }
                return true;
            }
            catch (Exception ex)
            {
                _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:" + ex.Message;
                return false;
            }
            finally
            {
                devinfo = null;
                itemnames = null;
                itemvalues = null;
            }
        }

        public bool WriteBarcode(int deviceindex, int taskindex)
        {
            Model.MDevice devinfo;
            StringBuilder[] itemnames = new StringBuilder[11];
            StringBuilder[] itemvalues = new StringBuilder[11];

            int sn = 0;
            try
            {
                devinfo = Model.CGetInfo.GetDeviceInfo(deviceindex);
                sss.Remove(0, sss.Length);
                sss.Append("SELECT F_MonitorIndex, F_TxtParam FROM T_Monitor_Task WHERE (F_MonitorIndex = ").Append(taskindex).Append(")");
                DataView dvb = dbo.ExceSQL(sss.ToString()).Tables[0].DefaultView;
                if (dvb.Count > 0)
                {
                    sss.Remove(0, sss.Length);
                    sss.Append(dvb[0]["F_TxtParam"].ToString());

                    if ((sss.ToString() == "-") || (sss.ToString() == "")) return true;
                }
                else
                {
                    _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:写入附加条码时在调度任务表内没找到条码!";
                    return false;
                }

                if (devinfo.AppendBarcode > 0)
                {
                    Model.MDevice devinfo1 = Model.CGetInfo.GetDeviceInfo(devinfo.AppendBarcode);
                    if (devinfo1.DeviceIndex == 0)
                    {
                        _commLayerError = "OPCClient.CSendDeviceOrder.SendDeviceOrder发生错误:写入附加条码时设备索引不存在!";
                        return false;
                    }
                    else
                    {

                        //byte0,byte1,byte2,byte3,byte4
                        //      int1         int3       
                        //int0(byte0,byte1);int1(byte1,byte2);int2(byte2,byte3);int3(byte3,byte4)
                        sn = Convert.ToInt32(devinfo1.Dbw1Address);
                        devinfo1 = null;
                        for (int i = 0; i <= 9; i++)
                        {
                            itemnames[i].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + i + 1)).Append(",b");
                            itemvalues[i].Append(Strings.Asc(sss.ToString().Substring((i), 1)).ToString());
                        }
                        itemnames[10].Append(Model.CGeneralFunction.DBSend).Append(".").Append(Convert.ToString(sn + 0)).Append(",b");
                        itemvalues[10].Append("1");
                        CCommonOPCClient.Hostname = CommonClassLib.AppSettings.GetValue("HostName");//20090922 devinfo.RemoteIP;
                        CCommonOPCClient.ProgID = CommonClassLib.AppSettings.GetValue("OPCProgID");
                        CCommonOPCClient.PlcConnectionID = devinfo.S7Connection;//20110216
                        if (CCommonOPCClient.SyncWriteAllItemValue(itemnames, itemvalues) == false)
                        {
                            return false;
                        }

                        CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "SendDeviceOrder", deviceindex.ToString(), sss.ToString());
                    }

                    return true;
                }
                else
                {
                    return true; ;
                }
            }
            catch (Exception ex)
            {
                _commLayerError = "OPCClient.CSendDeviceOrder.WriteBarcode发生错误:" + ex.Message;
                return false;
            }
            finally
            {
                devinfo = null;
                itemnames = null;
                itemvalues = null;

            }
        }

        /// <summary>
        /// 向PLC的DB区写入数据
        /// </summary>
        /// <param name="ItemNames">标签变量名称数组</param>
        /// <param name="ItemValues">标签值数组</param>
        /// <returns></returns>
        public bool WriteDBData(StringBuilder[] ItemNames, StringBuilder[] ItemValues)
        {
            try
            {
                if (CCommonOPCClient.SyncWriteAllItemValue(ItemNames, ItemValues) == false)
                {
                    return false;
                }
                else
                {
                    sss.Remove(0, sss.Length);
                    sss.Append("**" + ItemNames[0].ToString() + "**" + ItemValues[0].ToString());

                    CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "发送应答标志", "----", sss.ToString());
                    return true;
                }
            }
            catch (Exception ex)
            {
                _commLayerError = "OPCClient.CSendDeviceOrder.WriteDBData发生错误:" + ex.Message;
                return false;
            }
            finally
            {
                ItemNames = null;
                ItemValues = null;
            }
        }
        public bool WriteDBData(StringBuilder[] ItemNames, StringBuilder[] ItemValues, string PLCconnectionID)
        {
            try
            {
                CCommonOPCClient.Hostname = CommonClassLib.AppSettings.GetValue("HostName");//20090922 devinfo.RemoteIP;
                CCommonOPCClient.ProgID = CommonClassLib.AppSettings.GetValue("OPCProgID");
                CCommonOPCClient.PlcConnectionID = PLCconnectionID;
                // 20220518  改成异步写入数据
                if (CCommonOPCClient.ASyncWriteAllItemValue(ItemNames, ItemValues) == false)
                {
                    return false;
                }
                else
                {
                    sss.Remove(0, sss.Length);
                    for (int i = 0; i < ItemNames.Length; i++)
                    {
                        sss.Append("**" + ItemNames[i].ToString() + "**" + ItemValues[i].ToString());
                    }
                    if (PLCconnectionID == "S7 connection_CP2" && ItemNames.Length == 234)// 双鹿成品分拣线点灯
                    {
                        CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "异步发送点灯信号", "----", ItemNames.Length.ToString() + "个信号"); 
                    }
                    else
                    {
                        CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "异步发送应答标志", "----", sss.ToString());
                    }
                    return true;
                }
            }
            catch (Exception ex)
            {
                _commLayerError = "OPCClient.CSendDeviceOrder.WriteDBData发生错误:" + ex.Message;
                return false;
            }
            finally
            {
                ItemNames = null;
                ItemValues = null;
            }
        }
        string GetBarcodeFromMonitorIndex(int taskindex)
        {
            sss.Remove(0, sss.Length);
            sss.Append("SELECT  F_TxtParam FROM T_Monitor_Task WHERE (F_MonitorIndex = ").Append(taskindex).Append(")");
            DataView dvb = dbo.ExceSQL(sss.ToString()).Tables[0].DefaultView;
            if (dvb.Count > 0)
            {
                return dvb[0]["F_TxtParam"].ToString();
            }
            else
            {
                return "-";
            }
        }
        int GetF_NumParam4FromMonitor(int taskindex)
        {
            // 手动任务得到F_TxtParam 自动任务 F_NumParam4

            sss.Remove(0, sss.Length);
            sss.Append("SELECT  F_ManageTASKKINDINDEX,F_NumParam1,F_NumParam4,F_TxtParam FROM T_Monitor_Task WHERE (F_MonitorIndex = ").Append(taskindex).Append(")");
            DataView dvb = dbo.ExceSQL(sss.ToString()).Tables[0].DefaultView;
            if (dvb.Count > 0)
            {
                if (Convert.ToInt32(dvb[0]["F_ManageTASKKINDINDEX"]) == 4)
                {
                    return Convert.ToInt32(dvb[0]["F_TxtParam"]);
                }
                else
                {
                    return Convert.ToInt32(dvb[0]["F_NumParam4"]);
                }
            }
            else
            {
                return 0;
            }
        }
        int GetNowDevice(int taskindex)
        {
            sss.Remove(0, sss.Length);
            sss.Append("SELECT  F_NumParam1 FROM T_Monitor_Task WHERE (F_MonitorIndex = ").Append(taskindex).Append(")");
            DataView dvb = dbo.ExceSQL(sss.ToString()).Tables[0].DefaultView;
            if (dvb.Count > 0)
            {
                return Convert.ToInt32(dvb[0]["F_NumParam1"]);
            }
            else
            {
                return 0;
            }
        }
        int IfInworkBench(int taskindex)
        {
            int fid = Model.CGeneralFunction.GetManageTaskIndexfromMonitor(taskindex);
            int mti = Model.CGeneralFunction.GetManageTaskKindIndexFromMonitor(taskindex);
            object ob = dbo.GetSingle(string.Format("SELECT WORK_MODE FROM T_Manage_Task WHERE (F_ManageTaskKindIndex = {0}) AND (FID = {1})", mti, fid));
            if (ob != null)
            {
                return Convert.ToInt32(ob);
            }
            else
            {
                return 2;
            }

        }
        List<int> GetNextDevice(int CurRouteIDSub, int CurSerialNumber)
        {
            List<int> keyDevice = new List<int>(); DataView dvRoute;
            try
            {
                //然后依次判断后续设备最近的设备
                sql.Remove(0, sql.Length);
                sql.Append("SELECT T_Base_Route_Device.F_DeviceIndex,F_DeviceOrder, T_Base_Route_Device.F_SerialNumber, ").Append(
                        "T_Base_Device_Command.F_DeviceCommandIndex,T_Base_Device.F_DeviceKindIndex FROM T_Base_Device_Command ").Append(
                        ",T_Base_Device,T_Base_Route_Device where T_Base_Device_Command.F_DeviceKindIndex = T_Base_Device.F_DeviceKindIndex").Append(
                        " and T_Base_Device.F_DeviceIndex = T_Base_Route_Device.F_DeviceIndex and F_RouteIDSub=").Append(
                        CurRouteIDSub).Append(" and F_SerialNumber > ").Append(CurSerialNumber).Append("  order by F_SerialNumber asc ");
                dvRoute = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                if (dvRoute.Count > 0)
                {
                    keyDevice.Add(Convert.ToInt32(dvRoute[0]["F_DeviceIndex"]));
                    keyDevice.Add(Convert.ToInt32(dvRoute[0]["F_DeviceKindIndex"]));
                    keyDevice.Add(Convert.ToInt32(dvRoute[0]["F_SerialNumber"]));
                    keyDevice.Add(Convert.ToInt32(dvRoute[0]["F_DeviceOrder"]));

                }
                return keyDevice;
            }
            catch (Exception ex)
            {
                _commLayerError = "OPCClient.CSendDeviceOrder.GetNextDevice:" + ex.Message;
                return null;
            }
            finally
            {
                keyDevice = null;
                dvRoute = null;

            }
        }

        int GetNextDeviceFromTaskDevice(int TaskIndex, int DeviceIndex)
        {//20111226
            int RouteIDSub = 0; int sn = 0;
            DataView dv = dbo.ExceSQL(string.Format("SELECT F_RouteID FROM T_Monitor_Task WHERE (F_MonitorIndex = {0})", TaskIndex)).Tables[0].DefaultView;
            if (dv.Count > 0)
            {
                RouteIDSub = Convert.ToInt32(dv[0][0]);
            }
            else
            {
                return -1;
            }
            try
            {
                //20101124
                sql.Remove(0, sql.Length);
                sql.Append("SELECT F_SerialNumber FROM T_Base_Route_Device WHERE (F_RouteIDSub = ").Append(RouteIDSub).Append(") AND (F_DeviceIndex = ").Append(DeviceIndex).Append(")");
                dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                if (dv.Count > 0)
                {
                    sn = (int)dv[0]["F_SerialNumber"];
                    List<int> nd = GetNextDevice(RouteIDSub, sn);
                    if (nd != null)
                    {
                        return nd[0];
                    }
                    else
                    {
                        return -1;
                    }
                }
                else
                {
                    return -1;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dv = null;
            }
        }
        /// <summary>
        /// 根据堆垛机坐标获得(是双叉对等关联站台的)站台设备索引
        /// </summary>
        /// <param name="stackdeviceindex"></param>
        /// <param name="stackzxy"></param>
        /// <returns></returns>
        int GetDeviceLaneGateInfoFromStackCoor(int stackdeviceindex, string stackzxy, out int useawayfork)
        {
            devinfo = Model.CGetInfo.GetDeviceInfo(stackdeviceindex);
            if (devinfo != null)
            {
                if (devinfo.VirtualStack > 0)
                {
                    stackdeviceindex = devinfo.VirtualStack;
                }

            }
            int laneway = 0; useawayfork = 0;
            DataView dvl = dbo.ExceSQL(string.Format("SELECT F_LaneDeviceIndex FROM T_Base_LaneInfo WHERE  (F_StackIndex = {0})", stackdeviceindex)).Tables[0].DefaultView;
            if (dvl.Count > 0)
            {
                laneway = Convert.ToInt32(dvl[0][0]);
            }
            else
            {
                return -1;
            }

            sql.Remove(0, sql.Length);
            sql.Append("SELECT F_LaneGateDeviceIndex,F_UseAwayFork FROM T_Base_Lane_Gate where F_CorrelDeviceIndex<>'' and (F_LaneIndex=").Append(laneway).Append(" and T_Base_Lane_Gate.F_ZXY = '").Append(stackzxy).Append("')");
            DataView dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
            if (dv.Count > 0)
            {
                useawayfork = Convert.ToInt32(dv[0]["F_UseAwayFork"]);
                return Convert.ToInt32(dv[0]["F_LaneGateDeviceIndex"]);

            }


            return -1;
        }
        bool SetLaneGateReplace(int mti, int fid, int DeviceIndex, int TaskIndex, int UseAwayFork)
        {//20120820
            //201112231同时考虑调整路径所选站台和提前检测有问题
            if (UseAwayFork > 0)
            {

                int[] zxy = GetCoordinatesFromMonitorTask(TaskIndex);
                StringBuilder zxystr = new StringBuilder();
                if (zxy != null)
                {
                    zxystr.Append((zxy[3].ToString().Length == 1 ? "0" + zxy[3].ToString() : zxy[3].ToString())).Append("-").Append(
                        ((zxy[4].ToString().Length == 1) ? ("0" + zxy[4].ToString()) : (zxy[4].ToString()))).Append("-").Append(
                        ((zxy[5].ToString().Length == 1) ? ("0" + zxy[5].ToString()) : (zxy[5].ToString())));
                }
                int LaneGateDevice = 0; int oldawayfork = 0;
                int oNextDevice = GetDeviceLaneGateInfoFromStackCoor(DeviceIndex, zxystr.ToString(), out oldawayfork);

                if (oNextDevice > 0)
                {
                    int n5 = zxy[4]; //Convert.ToInt32(sp[1]);

                    if (UseAwayFork == oldawayfork)
                    {
                        //不调整
                        return false;//20120217
                    }
                    else
                    {
                        //堆垛机的原点属性
                        char[] cc = new char[1] { ',' };
                        string[] lc = devinfo.StackZeroColLayer.Split(cc);
                        if (Convert.ToInt32(lc[0]) < n5)//正常情况,货叉顺序号和列顺序号相同
                        {
                            n5 = n5 + (UseAwayFork - oldawayfork);
                        }
                        else
                        {//双堆垛机的原点在最大列的货叉顺序号和列顺序号相反
                            n5 = n5 - (UseAwayFork - oldawayfork);
                        }
                        zxystr.Clear();
                        zxystr.Append((zxy[3].ToString().Length == 1 ? "0" + zxy[3].ToString() : zxy[3].ToString())).Append("-").Append(
                        ((n5.ToString().Length == 1) ? ("0" + n5.ToString()) : (n5.ToString()))).Append("-").Append(
                        ((zxy[5].ToString().Length == 1) ? ("0" + zxy[5].ToString()) : (zxy[5].ToString())));
                        LaneGateDevice = GetDeviceLaneGateInfoFromStackCoor(DeviceIndex, zxystr.ToString(), out oldawayfork);

                        //替换路径

                        //修改堆垛机提前检测,RunLock
                        sql.Clear();
                        sql.Append("UPDATE T_Monitor_Task SET  F_RunningLock='").Append(LaneGateDevice).Append("', F_AheadDetect=Replace(F_AheadDetect,'").Append(oNextDevice).Append("','").Append(LaneGateDevice).Append("') WHERE (F_ManageTaskIndex = ")
                            .Append(fid).Append(") AND (F_ManageTASKKINDINDEX = ")
                            .Append(mti).Append(") AND F_DeviceIndex = ").Append(DeviceIndex);
                        dbo.ExecuteSql(sql.ToString());
                        //修改堆垛机送货坐标
                        sql.Clear();
                        sql.Append("UPDATE T_Monitor_Task SET F_NumParam5=").Append(n5).Append("  WHERE (F_ManageTaskIndex = ")
                            .Append(fid).Append(") AND (F_ManageTASKKINDINDEX = ")
                            .Append(mti).Append(")").Append(" AND F_DeviceIndex = ").Append(DeviceIndex);
                        dbo.ExecuteSql(sql.ToString());
                        //修改输送机,提前检测,RunLock,F_NumParam1
                        sql.Clear();
                        sql.Append("UPDATE T_Monitor_Task SET F_RouteID=").Append(GetRouteIDsub(LaneGateDevice)).Append(",F_DeviceIndex=").Append(LaneGateDevice).Append(", F_NumParam1=").Append(LaneGateDevice).Append(", F_RunningLock='").Append(LaneGateDevice).Append("', F_AheadDetect=Replace(F_AheadDetect,'").Append(oNextDevice).Append("','").Append(LaneGateDevice).Append("') WHERE (F_ManageTaskIndex = ")
                            .Append(fid).Append(") AND (F_ManageTASKKINDINDEX = ")
                            .Append(mti).Append(") AND F_DeviceIndex = ").Append(oNextDevice);
                        dbo.ExecuteSql(sql.ToString());
                        return true;//20120217
                    }
                }
                else
                {
                    return false;

                }

            }
            else
            {
                return false;//20120217
            }
        }
        int GetGoodsHigh(int taskindex)
        {
            DataView dv = dbo.ExceSQL(string.Format("SELECT CELL_MODEL FROM T_Manage_Task WHERE (F_ManageTaskKindIndex = {0}) AND (FID = {1})", Model.CGeneralFunction.GetManageTaskKindIndexFromMonitor(taskindex), Model.CGeneralFunction.GetManageTaskIndexfromMonitor(taskindex))).Tables[0].DefaultView;
            if (dv.Count > 0)
            {
                #region
                //int gh = 1;
                ////P工装板,B标准,G高货位,D大货位
                //switch (dv[0][0].ToString().ToUpper())
                //{
                //    case "P":
                //        gh = 3;
                //        break;
                //    case "B":
                //        gh = 2;
                //        break;
                //    case "G":
                //        gh = 1;
                //        break;
                //    //case "D":
                //    //    gh = 4;
                //    //    break;
                //    default:
                //        gh = 1;
                //        break;
                //}
                #endregion

                int gh = 0;
                //P工装板,B标准,G高货位,D大货位
                switch (dv[0][0].ToString().ToUpper())
                {
                    case "1":
                        gh = 1;
                        break;
                    case "2":
                        gh = 2;
                        break;
                   
                    default:
                        gh = 0;
                        break;
                }
                return gh;
            }
            else
            {
                return 0;
            }
        }
        int MinRouteID(int startdevice, int enddevice, int nowdevice, object useAwayfork)
        {
            try
            {
                StringBuilder dff = new StringBuilder();
                if (useAwayfork.ToString() == "-")
                {
                    dff.Append("F_UseAwayFork<>'n'");
                }
                else
                {
                    dff.Append("(F_UseAwayFork='").Append(useAwayfork).Append("' or F_UseAwayFork='-' )");//20101028
                }
                //选择最短调度路径并且判断此路径上是否有设备发生故障
                //20101124
                sql.Remove(0, sql.Length);
                sql.Append("SELECT distinct(T_Base_Route_Device.F_RouteIDSub) FROM T_Base_Device,T_Base_Route_Device,").Append(
                    "T_Base_Route where T_Base_Route_Device.F_RouteID = T_Base_Route.F_RouteID and ").Append(
                    " T_Base_Route_Device.F_DeviceIndex = T_Base_Device.F_DeviceIndex and ").Append(
                    " F_StartDevice=").Append(startdevice).Append(" and F_EndDevice=").Append(enddevice).Append(" and F_Status=1 and T_Base_Device.F_DeviceIndex =").Append(nowdevice).Append(" and ").Append(dff.ToString());
                DataView dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                List<double> minroute = new List<double>();//0,routIDSub;1,路径最小值
                if (dv.Count == 0)
                {
                    //RefreshMonitorEventArgs rme = new RefreshMonitorEventArgs("tsStatus", "起点设备:" + startdevice + "和终点设备:" + enddevice + "之间路径不可用!");
                    //OnRefreshMonitor(rme);
                    return -1;
                }
                for (int i = 0; i < dv.Count; i++)
                {
                    //20101124
                    sql.Remove(0, sql.Length);
                    sql.Append("SELECT F_RouteIDSub, F_LockedState FROM T_Base_Device,T_Base_Route_Device WHERE ").Append(
                        " T_Base_Device.F_DeviceIndex = T_Base_Route_Device.F_DeviceIndex  and (T_Base_Route_Device.F_RouteIDSub = ").Append(
                        dv[i]["F_RouteIDSub"]).Append(") AND  (T_Base_Device.F_LockedState = - 1)");
                    DataView dvd = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                    if (dvd.Count > 0)
                    {
                        continue;
                    }

                    List<double> route = new List<double>();//0,routIDSub;1,步长;2,路径使用频率;3,路径设备任务数
                    //路径步长(设备总数)最短(权重0.3),路径使用频率最小(权重0.3)的路径,路径设备任务数(权重0.3)

                    route.Add(Convert.ToDouble(dv[i]["F_RouteIDSub"]));//RouteIDSub
                    //20101124
                    sql.Remove(0, sql.Length);
                    sql.Append("select count(F_DeviceIndex) as steps from T_Base_Route_Device where F_RouteIDSub="
                        ).Append(dv[i]["F_RouteIDSub"]);
                    DataView dv1 = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                    if (dv1.Count > 0)
                    {
                        route.Add(Convert.ToDouble(dv1[0]["steps"]));//步长
                        //route.Add(0);
                    }
                    else
                    {
                        continue;
                    }
                    //路径使用频率:路径执行调度任务的数量

                    //20101124
                    sql.Remove(0, sql.Length);
                    sql.Append("SELECT COUNT(DISTINCT F_ManageTaskIndex) AS ManCount FROM T_Monitor_Task GROUP BY F_RouteID HAVING (F_RouteID = ").Append(dv[i]["F_RouteIDSub"]).Append(")");
                    DataView dv2 = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                    if (dv2.Count > 0)
                    {
                        double a = 0;
                        if (double.TryParse(dv2[0]["ManCount"].ToString(), out a) == true)
                        {
                            route.Add(Convert.ToDouble(dv2[0]["ManCount"]));//路径使用频率
                        }
                        else
                        {
                            route.Add(0);//路径使用频率
                        }
                    }
                    else
                    {
                        route.Add(0);//路径使用频率
                    }
                    //路径设备任务数
                    //20101124
                    sql.Remove(0, sql.Length);
                    sql.Append("SELECT COUNT(T_Monitor_Task.F_MonitorIndex) AS mtask FROM T_Monitor_Task ,T_Base_Route_Device where  (T_Monitor_Task.F_DeviceIndex = T_Base_Route_Device.F_DeviceIndex) and  (T_Base_Route_Device.F_RouteIDSub = ").Append(dv[i]["F_RouteIDSub"]).Append(")");
                    dv2 = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                    if (dv2.Count > 0)
                    {
                        double a = 0;
                        if (double.TryParse(dv2[0]["mtask"].ToString(), out a) == true)
                        {
                            route.Add(Convert.ToDouble(dv2[0]["mtask"]));//路径设备任务数
                        }
                        else
                        {
                            route.Add(0);//路径设备任务数
                        }
                    }
                    else
                    {
                        route.Add(0);//路径设备任务数
                    }

                    //求最短路径((路径步长*0.3+路径使用频率*0.3+设备占有数*0.3)的最小值)
                    if (minroute.Count == 0)
                    {
                        minroute.Add(route[0]);
                        minroute.Add(route[1] * 0.3 + route[2] * 0.3 + route[3] * 0.3);
                    }
                    else
                    {
                        if (minroute[1] > (route[1] * 0.3 + route[2] * 0.3 + route[3] * 0.3))
                        {
                            minroute[0] = route[0];
                            minroute[1] = (route[1] * 0.3 + route[2] * 0.3 + route[3] * 0.3);
                        }
                    }
                }
                if (minroute.Count > 0)
                {
                    return Convert.ToInt32(minroute[0]);
                }
                else
                {

                    return -1;
                }
            }
            catch (Exception ex)
            {

                _commLayerError = "OPCClient.CSendDeviceOrder.MinRouteID时发生错误:" + ex.Message;
                return -1;
            }

        }
        int GetRouteIDsub(int device)
        {
            DataView dv = dbo.ExceSQL("SELECT F_RouteIDSub, F_DeviceIndex, F_RouteID FROM T_Base_Route_Device where F_DeviceIndex=" + device + "").Tables[0].DefaultView;
            if (dv.Count > 0)
            {
                return Convert.ToInt32(dv[0]["F_RouteIDSub"]);
            }
            else
            {
                return -1;
            }
        }
        int[] GetCoordinatesFromMonitorTask(int TaskIdx)
        {
            //20100108
            DataView dv;
            int[] gc;
            try
            {
                //20101124
                sql.Remove(0, sql.Length);
                sql.Append("select F_NumParam1,F_NumParam2,F_NumParam3,F_NumParam4,F_NumParam5,F_NumParam6 from T_Monitor_Task where F_MonitorIndex=").Append(TaskIdx);
                dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
                gc = new int[6];


                //F_NumParam1--z,x--2,y--3;F_NumParam4--z,5--x,6--y
                if (dv.Count > 0)
                {
                    gc[0] = Convert.ToInt32(dv[0]["F_NumParam1"]);
                    gc[1] = Convert.ToInt32(dv[0]["F_NumParam2"]);
                    gc[2] = Convert.ToInt32(dv[0]["F_NumParam3"]);
                    gc[3] = Convert.ToInt32(dv[0]["F_NumParam4"]);
                    gc[4] = Convert.ToInt32(dv[0]["F_NumParam5"]);
                    gc[5] = Convert.ToInt32(dv[0]["F_NumParam6"]);
                    return gc;
                }
                return null;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dv = null;
                gc = null;
            }
        }
        string GetUseAwayForkFromLaneGate(int device)
        {
            DataView dv = dbo.ExceSQL(string.Format("SELECT F_UseAwayFork FROM T_Base_Lane_Gate where F_LaneGateDeviceIndex={0}", device)).Tables[0].DefaultView;
            if (dv.Count > 0)
            {
                return dv[0][0].ToString();
            }
            else
            {
                return "-";
            }
        }
    }
}