using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using parkMonitor.LOG;
using parkMonitor.entity;
using parkMonitor.model;
using System.Configuration;
using System.Threading;
using parkMonitor.server.uiLogServer;
using parkMonitor.tools;
using parkMonitor.Database2;
using MySql.Data.MySqlClient;
using parkMonitor.server.NumMachine;
using parkMonitor.server.broadcastModule;
using BroadcastModule;

namespace parkMonitor.server.CoreThread
{
    /// <summary>
    /// 核心对命令处理父类
    /// </summary>
    public abstract class AbstractCmd
    {
        public static bool isClosing { get; set; }
        /// <summary>
        /// 设备总状态PLC地址
        /// </summary>
        public int equipmentStatus_address { set; get; }
        /// <summary>
        /// 停车完成PLC地址
        /// </summary>
        public int park_completed_address { set; get; }
        /// <summary>
        /// 停车入口X坐标
        /// </summary>
        public int parkingEntX { set; get; }
        /// <summary>
        /// 停车入口Y坐标
        /// </summary>
        public int parkingEntY { set; get; }
        /// <summary>
        /// 停车入口Z坐标
        /// </summary>
        public int parkingEntZ { set; get; }
        /// <summary>
        /// 取车完成PLC地址
        /// </summary>
        public int fetch_completed_address { set; get; }
        /// <summary>
        /// 轮距测量状态PLC地址
        /// </summary>
        public int wheelbase_status_address { get; set; }
        /// <summary>
        /// 停车启动机械手PLC地址
        /// </summary>
        public int parking_startRobot_address { get; set; }
        /// <summary>
        /// 取车启动机械手PLC地址
        /// </summary>
        public int fetching_startRobot_address { get; set; }
        /// <summary>
        /// 前轮距PLC地址
        /// </summary>
        public int frontWheelbase_address { get; set; }
        /// <summary>
        /// 后轮距PLC地址
        /// </summary>
        public int rearWheelbase_address { get; set; }

        /// <summary>
        /// PLC句柄
        /// </summary>
        public IEquipments PLC { set; get; }
        /// <summary>
        /// 队列线程句柄
        /// </summary>
        public IEquipments queuingThread { set; get; }
        /// <summary>
        /// 数据库操作句柄
        /// </summary>
        public DBOperation oper { set; get; }
        /// <summary>
        /// 号牌机线程句柄
        /// </summary>
        public IEquipments NumMachine { set; get; }
        /// <summary>
        /// 车库中心
        /// </summary>
        public CEntrance cEntrance { set; get; }

        public AbstractCmd()
        {
            parking_startRobot_address = EntityForCore.ins.parking_startRobot_address;
            fetching_startRobot_address = EntityForCore.ins.fetching_startRobot_address;
            equipmentStatus_address = EntityForCore.ins.equipmentStatus_address;
            park_completed_address = EntityForCore.ins.park_completed_address;
            parkingEntX = EntityForCore.ins.parkingEntX;
            parkingEntY = EntityForCore.ins.parkingEntY;
            parkingEntZ = EntityForCore.ins.parkingEntZ;
            //轮距
            frontWheelbase_address = EntityForCore.ins.frontWheelbase_address;
            rearWheelbase_address = EntityForCore.ins.rearWheelbase_address;
            wheelbase_status_address = EntityForCore.ins.wheelbase_status_address;
            //取车完成
            fetch_completed_address = EntityForCore.ins.fetch_completed_address;
            //获取PLC句柄
            PLC = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.PLC);
            //获取队列句柄
            queuingThread = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.Queue);
            //获取号牌机线程句柄
            NumMachine = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.NumMachine);
            //数据库
            oper = new DBOperation();
            //车位分配
            cEntrance = new CEntrance();
            Robot.robot1.parking_start_addr = parking_startRobot_address;
            Robot.robot1.fetching_start_addr = fetching_startRobot_address;
            //locationOper = new DBLocationOperator();
        }
        public abstract void executeCmd(Command queueCmd);
        /// <summary>
        /// 等待机械手空闲资源
        /// </summary>
        /// <param name="robotID"></param>
        /// <returns></returns>
        public bool WaitForRobotResource(int robotID)
        {
            PLCMessage PLCMsg = null;
            MyTimer mt = new MyTimer();
            mt.StartTiming();
            lock (Robot.robot1)
            {
                while (!isClosing)
                {
                    if (PLC != null)
                    {
                        PLCMsg = (PLCMessage)PLC.GetMessage();
                    }
                    bool occupied = true;
                    if (PLCMsg != null && PLCMsg.originalPlcList.Count != 0)
                    {
                        if (robotID == 1)
                        {
                            try
                            {
                                Robot.robot1.parking_start_value = Convert.ToInt32(PLCMsg.originalPlcList[parking_startRobot_address].Value);
                                Robot.robot1.fetching_start_value = Convert.ToInt32(PLCMsg.originalPlcList[fetching_startRobot_address].Value);
                                //刷新机械手资源状态值
                                if (Robot.robot1.parking_start_value == 0 && Robot.robot1.fetching_start_value == 0 && !Robot.robot1.occupied)
                                {
                                    occupied = false;
                                }
                                else
                                {
                                    occupied = true;
                                }
                            }
                            catch { }
                        }
                    }
                    if (occupied)
                    {
                        Thread.Sleep(3000);
                    }
                    else
                    {
                        Robot.robot1.occupied = true;
                        //UILogServer.ins.log("获得机械手资源");
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "获得机械手资源");
                        break;
                    }
                    Thread.Sleep(1000);
                    mt.EndTiming();
                    int activationCount = 0;
                    if (mt.IsLonger(60, 1, false, out activationCount))
                    {
                        if (activationCount == 1)
                        {
                            UILogServer.ins.info("无空闲机械手资源，继续等待");
                        }
                        if (MyTimer.restart && !mt.rolledBack)
                        {
                            mt.rolledBack = true;
                            Robot.robot1.occupied = false;
                            UILogServer.ins.error("启动机械手资源超时，已启动回滚");
                            Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "启动机械手资源超时，已启动回滚");
                            return false;
                        }
                    }
                }
            }
            return true;
        }

        /// /// <summary>
        /// 流程回滚函数
        /// </summary>
        /// <param name="queueCmd"></param>
        /// <param name="parkingSpaceID"></param>
        /// <param name="robotAllocated"></param>
        /// <param name="isParking"></param>
        public void Rollback(Command queueCmd, int parkingSpaceID, bool robotAllocated, bool isParking, LaserMessage lm)
        {
            if (queueCmd.id == 1)
            {
                BroadcastLinker.dispForAWhile(0, "流程中止", 8, false);
            }
            Console.WriteLine("回滚");
            NumReset(queueCmd);
            ////命令回退
            //queueCmd.returnedCount += 1;
            //queuingThread.SetMessage(queueCmd);
            //机械手释放
            if (robotAllocated)
            {
                Robot.robot1.occupied = false;
            }
            //线程计数调整，复位PLC指令
            if (!queueCmd.manual)
            {
                if (isParking)
                {
                    Robot.robot1.parkWaitCount -= 1;
                    ControlMessage cMsg = new ControlMessage
                    {
                        status = 6,
                        RobotID = 1
                    };
                    PLC.SetMessage(cMsg);
                    oper.UpdateVehicleParkState(EntityForCore.remoteBQ, queueCmd.LicenseNum, 0);
                }
                else
                {
                    Robot.robot1.fetchWaitCount -= 1;
                    ControlMessage cMsg = new ControlMessage
                    {
                        status = 7,
                        RobotID = 1
                    };
                    PLC.SetMessage(cMsg);
                    oper.UpdateVehicleParkState(EntityForCore.remoteBQ, queueCmd.LicenseNum, 1);
                }
            }
            //释放激光
            if (lm != null)
            {
                lm.occupied = false;
            }
            if (parkingSpaceID == 0)
            {
                return;
            }

            //复位车辆状态；若已更新过车位则还需复位总车位数，车位状态
            if (!queueCmd.manual)
            {
                if (isParking)
                {
                    //释放已分配车位
                    if (!ParkingSpaceManager.ins.SetParkingSpace(parkingSpaceID, 0))
                    {
                        EntityForCore.ins.globalStatus = false;
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "车位分配出现异常，需要重启");
                        return;
                    }
                    if (robotAllocated)
                    {
                        oper.UpdateParkingSpaceState(EntityForCore.remoteBQ, parkingSpaceID, 0);
                    }
                }
                else
                {
                    //复原已释放的车位
                    if (!ParkingSpaceManager.ins.SetParkingSpace(parkingSpaceID, 1))
                    {
                        EntityForCore.ins.globalStatus = false;
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "车位分配出现异常，需要重启");
                        return;
                    }
                    if (robotAllocated)
                    {
                        oper.UpdateParkingSpaceState(EntityForCore.remoteBQ, parkingSpaceID, 1);
                    }
                }
            }
            else
            {
                //if (isParking)
                //{
                //    oper.UpdateVehicleParkState(EntityForCore.remoteBQ, queueCmd.LicenseNum, 0);
                //    if (robotAllocated)
                //    {
                //        oper.UpdateParkingSpaceState(EntityForCore.remoteBQ, parkingSpaceID, 0);
                //    }
                //}
                //else
                //{
                //    oper.UpdateVehicleParkState(EntityForCore.remoteBQ, queueCmd.LicenseNum, 1);
                //    if (robotAllocated)
                //    {
                //        oper.UpdateParkingSpaceState(EntityForCore.remoteBQ, parkingSpaceID, 1);
                //    }
                //}
            }
        }

        /// <summary>
        /// 号牌复位
        /// </summary>
        public void NumReset(Command queueCmd)
        {
            NumberMachineMessage numberMachineMessage = new NumberMachineMessage();
            numberMachineMessage.aNode = new NumberMachineNode();
            numberMachineMessage.aNode.ip = "";
            numberMachineMessage.aNode.LicenseNum = queueCmd.LicenseNum;
            queuingThread.SetMessage(numberMachineMessage);
        }
    }

    /// <summary>
    /// 停车命令处理类
    /// </summary>
    public class StopCmd : AbstractCmd
    {
        private bool RangeValidation(Data data)
        {
            int temp = 0;
            Console.WriteLine(data.centerX + "," + data.centerY + "," + data.angleA);
            lock (EntityForCore.ins)
            {
                if (data.centerX > EntityForCore.ins.centerXLimit)
                {
                    Console.WriteLine(EntityForCore.ins.centerXLimit);
                    BroadcastLinker.dispForAWhile(1, "x轴超限", 6, false);
                    //BroadcastLinker.ins.DispString(1, "x轴超限", 6);
                    if (BroadcastLinker.ins != null)
                    {
                        BroadcastLinker.ins.Play(0, BroadcastBoard.PlayMode.audio, "请注意");
                    }
                    temp += 1;
                }
                if (data.centerY > EntityForCore.ins.centerYLimit)
                {
                    Console.WriteLine(EntityForCore.ins.centerYLimit);
                    BroadcastLinker.dispForAWhile(2, "y轴超限", 6, false);
                    //BroadcastLinker.ins.DispString(2, "y轴超限", 6);
                    if (BroadcastLinker.ins != null)
                    {
                        BroadcastLinker.ins.Play(0, BroadcastBoard.PlayMode.audio, "请注意");
                    }
                    temp += 2;
                }
                if (data.angleA > EntityForCore.ins.angleALimit)
                {
                    Console.WriteLine(EntityForCore.ins.angleALimit);
                    BroadcastLinker.dispForAWhile(3, "角度超限", 6, false);
                    //BroadcastLinker.ins.DispString(3, "角度超限", 6);
                    if (BroadcastLinker.ins != null)
                    {
                        BroadcastLinker.ins.Play(0, BroadcastBoard.PlayMode.audio, "请注意");
                    }
                    temp += 4;
                }
            }
            //Thread.Sleep(10000);
            //for (int i = 0; i < 3; i++)
            //{
            //    if ((state & 0x01) == 1)
            //    {
            //        BroadcastLinker.ins.DispDownStr(i + 1, 0);
            //        state = state >> 1;
            //    }
            //}
            //BroadcastLinker.ins.DispDownStr(1, 0);
            //BroadcastLinker.ins.DispDownStr(2, 0);
            //BroadcastLinker.ins.DispDownStr(3, 0);
            if (temp > 0) return false;
            else return true;
            //return temp > 0 ? false : true;
        }
        /// <summary>
        /// 命令中号牌与对应号牌机中当前号牌比对，确认车辆
        /// </summary>
        private bool NumValidation(Command queueCmd, int countdown, float ratio)
        {
            List<NumberMachineNode> numList = ((NumberMachineMessage)NumMachine.GetMessage()).data;
            bool result = false;
            Task numberCheck = Task.Factory.StartNew(() =>
            {
                int myCountdown = countdown, count = 0;
                while (myCountdown-- > 0)
                {
                    foreach (NumberMachineNode node in numList)
                    {
                        if (queueCmd.ip.Equals(node.ip) && queueCmd.LicenseNum.Equals(node.LicenseNum))
                        {
                            count += 1;
                        }
                    }
                    Thread.Sleep(500);
                }
                if (count >= (int)(countdown * ratio))
                {
                    result = true;
                }
                else
                {
                    result = false;
                }
            });
            numberCheck.Wait();
            return result;
        }

        /// <summary>
        /// 车位资源
        /// </summary>
        /// <param name="queueCmd"></param>
        /// <returns></returns>
        private Parking_Space WaitForParkingSpaceResource(Command queueCmd, out int count)
        {
            //中心点
            cEntrance.parkingEntX = parkingEntX;
            cEntrance.parkingEntY = parkingEntY;
            cEntrance.parkingEntZ = parkingEntZ;
            Parking_Space ppp = new Parking_Space();
            MyTimer mt = new MyTimer();
            mt.StartTiming();
            count = 0;
            while (!isClosing && ParkingSpaceManager.ins != null)
            {
                if (!queueCmd.manual)
                {
                    ppp = ParkingSpaceManager.ins.MallocParkingSpace(cEntrance, queueCmd, false, out count);//自动 
                }
                else
                {
                    ppp = ParkingSpaceManager.ins.MallocParkingSpace(cEntrance, queueCmd, false, out count);//手动
                }
                if (ppp != null)
                {
                    Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "停车流程：" + queueCmd.LicenseNum + "已分配车位");
                    break;
                }
                Thread.Sleep(1000);
                mt.EndTiming();
                int activationCount = 0;
                if (mt.IsLonger(5, 1, false, out activationCount))
                {
                    if (activationCount == 1)
                    {
                        UILogServer.ins.info("停车流程：" + queueCmd.LicenseNum + "未获得车位");
                    }
                    if (MyTimer.restart && !mt.rolledBack)
                    {
                        mt.rolledBack = true;
                        UILogServer.ins.error(queueCmd.LicenseNum + "超时未获得车位，指令退回");
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, queueCmd.LicenseNum + "超时未获得车位，指令退回");
                        return null;
                    }
                    //Thread.Sleep(1000);
                }
            }
            return ppp;
        }
        /// <summary>
        /// 等待激光数据
        /// </summary>
        /// <param name="queueCmd">传入的命令</param>
        /// <param name="disappeared">车辆是否已驶离</param>
        /// <returns></returns>
        private Data WaitForLaserResource(Command queueCmd, bool disappeared, out LaserMessage lmRelease)
        {
            //激光数据
            Data data = new Data();
            bool jumpOut = false;
            int disconnectionCount = 0;
            int laserID = queueCmd.id / 6 + 1;
            PLCMessage PLCMsg = null;
            jumpOut = false;
            lmRelease = null;
            MyTimer mt = new MyTimer();
            mt.StartTiming();
            while (!isClosing)
            {
                if (PLC != null)
                {
                    PLCMsg = (PLCMessage)PLC.GetMessage();
                }
                if (PLCMsg != null)
                {
                    foreach (LaserMessage lm in PLCMsg.laserMsgList)
                    {
                        if (lm.id == laserID && lm.data != null)
                        {
                            lock (lm)
                            {
                                //判断车辆检测结果,
                                if (disappeared)
                                {
                                    lm.abort_rescan = true;
                                    jumpOut = true;
                                    break;
                                }
                                //存储相应激光数据
                                if (lm.recorded && lm.licenseNum == queueCmd.LicenseNum)
                                {
                                    data.angleA = lm.data.angleA;
                                    data.centerX = lm.data.centerX;
                                    data.centerY = lm.data.centerY;
                                    data.length = lm.data.length;
                                    data.width = lm.data.width;
                                    data.height = lm.data.height;
                                    jumpOut = true;
                                    lm.recorded = false;
                                    //lm.occupied = false;
                                    lmRelease = lm;
                                    lm.licenseNum = "";
                                    break;
                                }
                                else if (lm.status == 5)
                                {
                                    disconnectionCount += 1;
                                    if (disconnectionCount == 1)
                                    {
                                        UILogServer.ins.error("激光" + lm.id + "连接异常");
                                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "激光" + lm.id + "连接异常");
                                    }
                                    Thread.Sleep(10000);
                                }
                            }
                        }
                        Thread.Sleep(500);
                    }
                    if (jumpOut)
                    {
                        //UILogServer.ins.log("停车流程：" + queueCmd.LicenseNum + "激光数据已获得");
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "停车流程：" + queueCmd.LicenseNum + "激光数据已获得");
                        break;
                    }
                }
                Thread.Sleep(1000);
                mt.EndTiming();
                int activationCount = 0;
                if (mt.IsLonger(30, 1, false, out activationCount))
                {
                    if (activationCount == 1)
                    {
                        UILogServer.ins.info("停车流程：" + queueCmd.LicenseNum + "未获取激光数据，继续等待");
                    }
                    if (MyTimer.restart && !mt.rolledBack)
                    {
                        mt.rolledBack = true;
                        UILogServer.ins.error(queueCmd.LicenseNum + "超时未获取激光数据，指令退回");
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, queueCmd.LicenseNum + "超时未获取激光数据，指令退回");
                        return null;
                    }
                    //Thread.Sleep(1000);
                }
            }
            return data;
        }
        /// <summary>
        /// 停车完成
        /// </summary>
        private bool WaitForStoreCompletionSignal(Command queueCmd, int parkingSpaceID, ref bool robotError, int status)
        {
            string connectionStr = null;
            PLCMessage PLCMsg = null;
            MyTimer mt = new MyTimer();
            mt.StartTiming();
            while (!isClosing)
            {
                int storeStatus = 0;
                if (PLC != null)
                {
                    PLCMsg = (PLCMessage)PLC.GetMessage();
                    //storeStatus = Convert.ToInt32(PLCMsg.originalPlcList[park_completed_address].Value);
                    if (PLCMsg.originalPlcList.Count != 0)
                    {
                        storeStatus = Convert.ToInt32(PLCMsg.originalPlcList[park_completed_address].Value);
                    }
                    else
                    {
                        storeStatus = -1;
                    }
                }
                //停车完成信号
                if (storeStatus == status)
                {
                    //UILogServer.ins.log("停车流程：" + queueCmd.LicenseNum + "已获得停车完成信号" + status);
                    Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "停车流程：" + queueCmd.LicenseNum + "已获得停车完成信号" + status);
                    break;
                }
                else if (1 == 2)//机械手异常，则退指令，写数据库归位，判断条件需之后补充
                {
                    robotError = true;
                    queueCmd.returnedCount += 1;
                    queuingThread.SetMessage(queueCmd);
                    if (!queueCmd.manual)
                    {
                        oper.UpdateParkingSpaceState(EntityForCore.remoteBQ, parkingSpaceID, 0);
                    }
                    else
                    {
                        connectionStr = "SqlConnectionLocation";
                        oper.UpdateParkingSpaceState(EntityForCore.localBQ, parkingSpaceID, 0);
                    }
                    break;
                }
                Thread.Sleep(1000);
                mt.EndTiming();
                int activationCount = 0;
                if (mt.IsLonger(120, 1, false, out activationCount))
                {
                    if (activationCount == 1)
                    {
                        UILogServer.ins.info("停车流程：" + queueCmd.LicenseNum + "未获得停车完成信号" + status + "，继续等待");
                    }
                    if (MyTimer.restart && !mt.rolledBack)
                    {
                        mt.rolledBack = true;
                        UILogServer.ins.error(queueCmd.LicenseNum + "等待停车完成信号" + status + "超时，流程回滚");
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, queueCmd.LicenseNum + "等待停车完成信号" + status + "超时，流程回滚");
                        return false;
                    }
                    //Thread.Sleep(1000);
                }
            }
            return true;
        }
        /// <summary>
        /// 等待轮距信息
        /// </summary>
        /// <param name="frontWheelbase">前轮距</param>
        /// <param name="rearWheelbase">后轮距</param>
        private bool WaitWheelbase(ref int frontWheelbase, ref int rearWheelbase)
        {
            PLCMessage PLCMsg = null;
            int wheelbaseStatus = 0;
            MyTimer mt = new MyTimer();
            mt.StartTiming();
            while (!isClosing)
            {
                PLCMsg = (PLCMessage)PLC.GetMessage();
                //wheelbaseStatus = Convert.ToInt32(PLCMsg.originalPlcList[wheelbase_status_address].Value);
                if (PLCMsg.originalPlcList.Count != 0)
                {
                    wheelbaseStatus = Convert.ToInt32(PLCMsg.originalPlcList[wheelbase_status_address].Value);
                }
                //停车完成信号
                if (wheelbaseStatus == 3)
                {
                    frontWheelbase = Convert.ToInt32(PLCMsg.originalPlcList[frontWheelbase_address].Value);
                    rearWheelbase = Convert.ToInt32(PLCMsg.originalPlcList[rearWheelbase_address].Value);
                    //UILogServer.ins.log("轮距雷达完成状态已获取");
                    Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "轮距雷达完成状态已获取");
                    break;
                }
                Thread.Sleep(1000);
                mt.EndTiming();
                int activationCount = 0;
                if (mt.IsLonger(60, 1, false, out activationCount))
                {
                    if (activationCount == 1)
                    {
                        UILogServer.ins.info("未获取轮距雷达完成状态，继续等待");
                    }
                    if (MyTimer.restart && !mt.rolledBack)
                    {
                        mt.rolledBack = true;
                        UILogServer.ins.error("超时未获取轮距雷达数据，流程回滚");
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "超时未获取轮距雷达数据，流程回滚");
                        return false;
                    }
                    //Thread.Sleep(1000);
                }
            }
            return true;
        }
        /// <summary>
        /// 停车流程
        /// </summary>
        /// <param name="queueCmd"></param>
        public override void executeCmd(Command queueCmd)
        {
            //UILogServer.ins.info("停车流程:" + queueCmd.LicenseNum + "开始");
            if (queueCmd.id == 1)
            {
                BroadcastLinker.dispForAWhile(0, "开始停车", 6, false);
            }
            Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "停车流程:" + queueCmd.LicenseNum + "开始");
            string connectionStr = null;                                          //数据库连接字符串
            bool disappeared = false;                                             //车辆检测结果
            bool stopChecking = false;                                          //是否停止检测
            bool robotError = false;                                               //机械手是否异常
            int userID = 0;                                                            //用户ID

            //第一步，激光与车位：
            int status = 1;//停车
            ControlMessage cm = new ControlMessage();
            cm.status = status;
            //根据号牌机id启动对应激光
            cm.posID = queueCmd.id;
            cm.LicenseNum = queueCmd.LicenseNum;
            PLC.SetMessage(cm);
            Log.WriteLog(LogType.NOT_DATABASE, "停车流程：车牌号为" + queueCmd.LicenseNum + "的车辆准备开启激光");
            //UILogServer.ins.info("停车流程：车牌号为" + queueCmd.LicenseNum + "的车辆准备开启激光");

            //车位分配数据库操作加锁，直到启动机械手
            Parking_Space ppp = new Parking_Space();
            ParkingBuffer pb = null;
            Data dataReal = new Data();
            int garageID;                                      //车库ID（Web发送）
            string realParkTime;                            //停车时间（可执行队列）
            LaserMessage lmToBeReleased;          //激光
            int freeSpaceCount = 0;                    //剩余空闲车位
            dataReal = WaitForLaserResource(queueCmd, disappeared, out lmToBeReleased);
            //判断激光资源有效性,无效代表超时且已点击回滚按钮
            //*****核对摆扫数据是否达标，未达标则将指令丢出，让用户重发指令
            if (dataReal == null || !RangeValidation(dataReal))
            {
                Rollback(queueCmd, 0, false, true, lmToBeReleased);
                return;
            }
            //车位分配锁
            lock (Parking_Space.spaceLock)
            {
                bool displayed = false;
                //等待获取缓冲位资源


                //获取车位资源
                ppp = WaitForParkingSpaceResource(queueCmd, out freeSpaceCount);

                //过期号牌判断
                if (queueCmd.userID != "")
                {
                    userID = Convert.ToInt32(queueCmd.userID);
                }
                garageID = queueCmd.garageID;
                realParkTime = queueCmd.TimeRecord;
                //定义号牌验证与机械手异常标志
                //Task checkNum = Task.Factory.StartNew(() =>
                //{
                //    DateTime startTime = DateTime.Now;
                //    DateTime endTime = DateTime.Now;
                //    TimeSpan t = startTime - endTime;
                //    while (!stopChecking && t.TotalSeconds <= 600)
                //    {
                //        //号牌验证,异常则退回队列
                //        Func<Command, int, float, bool> numValidationResult = new Func<Command, int, float, bool>(NumValidation);
                //        IAsyncResult result = numValidationResult.BeginInvoke(queueCmd, 10, 0.7f, null, null);
                //        bool checkResult = numValidationResult.EndInvoke(result);
                //        if (stopChecking)
                //        {
                //            return;
                //        }
                //        if (!checkResult)
                //        {
                //            UILogServer.ins.info("停车命令" + queueCmd.LicenseNum + " 与当前车辆不一致");
                //            disappeared = true;
                //            return;
                //            //未能停车，将车辆状态复位
                //            //oper.UpdateVehicleParkState(queueCmd.LicenseNum, 0);
                //        }
                //        endTime = DateTime.Now;
                //        t = startTime - endTime;
                //    }
                //});

                //判断车位资源有效性,无效则回滚
                if (ppp == null)
                {
                    Rollback(queueCmd, 0, false, true, lmToBeReleased);
                    return;
                }

                while (pb == null && !MyTimer.restart)
                {
                    //pb = ParkingBufferManager.ins.MallocParkingBuffer(queueCmd.id);
                    pb = new ParkingBuffer(ppp.parkingSpaceX, true);
                    ParkingBufferManager.ins.SetParkingBuffer(ppp.parkingSpaceX, true);
                    if (pb != null)
                    {
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.INFO, queueCmd.LicenseNum + "分配缓冲位：" + pb.bufferID);
                        break;
                    }
                    else if (!displayed)
                    {
                        UILogServer.ins.error(queueCmd.LicenseNum + "缓冲位已满");
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.WARNING, queueCmd.LicenseNum + "缓冲位分配失败");
                        displayed = true;
                    }
                    Thread.Sleep(2000);
                }
                if (pb == null)
                {
                    UILogServer.ins.error("缓冲位分配失败，流程已回滚");
                    Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "缓冲位分配失败，流程已回滚");
                    Rollback(queueCmd, 0, false, true, lmToBeReleased);
                    return;
                }

                //车位赋值与写数据库
                if (!queueCmd.manual)
                {
                }
                else
                {
                    //更新本地车位表车位状态
                    oper.UpdateParkingSpaceState(EntityForCore.localBQ, ppp.parkingSpaceID, 1);
                    //更新车库表剩余车位数
                    //int freeSpaceCount = oper.getGarageFreeSpace(connectionStr, garageID);
                    //freeSpaceCount = freeSpaceCount - 1;
                    //oper.UpdateGarageFreeSpace(CoreThreadTest2.localBQ, freeSpaceCount, garageID);
                }
                //号牌失效，数据库回滚
                if (disappeared)
                {
                    NumReset(queueCmd);
                    if (!queueCmd.manual)
                    {
                        oper.UpdateVehicleParkState(EntityForCore.remoteBQ, queueCmd.LicenseNum, 0);
                    }
                    else
                    {
                        oper.UpdateVehicleParkState(EntityForCore.localBQ, queueCmd.LicenseNum, 0);
                    }
                    return;
                }
            }
            //开始启动机械手，停止检测号牌
            stopChecking = true;
            //UILogServer.ins.log("停车流程：" + queueCmd.LicenseNum + "停止号牌核对，准备启动机械手");
            Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "停车流程：" + queueCmd.LicenseNum + "停止号牌核对，准备启动机械手");
            int robotID = 0;
            robotID = queueCmd.id / 6 + 1;
            int frontWheelbase = 0;
            int rearWheelbase = 0;

            //需要先遍历robot数组，根据id找到对应机械手
            if (!WaitForRobotResource(robotID))
            {
                Rollback(queueCmd, ppp.parkingSpaceID, false, true, lmToBeReleased);
                return;
            }

            //第二步，机械手：
            status = 2;
            cm.status = status;
            cm.RobotID = robotID;//启动对应机械手
            if (queueCmd.id == 1)
            {
                //Task.Factory.StartNew(() =>
                //{
                BroadcastLinker.dispForAWhile(0, "抓车到" + ppp.parkingSpaceX, 60, false);
                //BroadcastLinker.ins.DispString(0, "抓车到" + ppp.parkingSpaceX, 6);
                //Thread.Sleep(5000);
                //BroadcastLinker.ins.DispDownStr(0, 0);
                //});
            }
            //激光数据
            cm.centerX = Convert.ToString(dataReal.centerX);
            cm.centerY = Convert.ToString(dataReal.centerY);
            cm.angleA = Convert.ToString(dataReal.angleA);
            cm.length = Convert.ToString(dataReal.length);
            cm.width = Convert.ToString(dataReal.width);
            cm.height = Convert.ToString(dataReal.height);
            //分配的车位数据
            cm.parkingSpaceID = Convert.ToString(ppp.parkingSpaceID);
            //!!!之前把停车位X坐标当做缓冲位ID，现修改为被管理的缓冲位ID，之后PLC地址需调整!!!
            cm.parkingSpaceX = Convert.ToString(ppp.parkingSpaceX);
            //cm.parkingSpaceX = Convert.ToString(pb.bufferID);
            cm.parkingSpaceY = Convert.ToString(ppp.parkingSpaceY);
            cm.parkingSpaceZ = Convert.ToString(ppp.parkingSpaceZ);
            PLC.SetMessage(cm);
            Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "停车流程：抓车:" + queueCmd.LicenseNum + "\n车辆数据：" + cm.angleA + " ," + cm.centerX + " ," + cm.centerY + " ," + cm.length + " ," + cm.width + " ," + cm.height + " ," + cm.parkingSpaceID + " ," + cm.parkingSpaceX + " ," + cm.parkingSpaceY + " ," + cm.parkingSpaceZ);
            UILogServer.ins.info("停车流程：抓车:" + queueCmd.LicenseNum);

            if (!WaitWheelbase(ref frontWheelbase, ref rearWheelbase))
            {
                Rollback(queueCmd, ppp.parkingSpaceID, true, true, lmToBeReleased);
                return;
            }
            //机械手异常则回滚
            if (!WaitForStoreCompletionSignal(queueCmd, ppp.parkingSpaceID, ref robotError, 1))
            {
                Rollback(queueCmd, ppp.parkingSpaceID, true, true, lmToBeReleased);
                return;
            }

            //第三步，停车完成：
            status = 3;
            cm.status = status;
            PLC.SetMessage(cm);
            if (!WaitForStoreCompletionSignal(queueCmd, ppp.parkingSpaceID, ref robotError, 0))
            {
                Rollback(queueCmd, ppp.parkingSpaceID, true, true, lmToBeReleased);
                return;
            }

            //停车流程结束，将相应车牌复位,从号牌队列中出队
            NumReset(queueCmd);
            Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "停车流程：" + queueCmd.LicenseNum + "停车完成，状态复位");
            UILogServer.ins.info("停车流程：" + queueCmd.LicenseNum + "停车完成，状态复位");
            //释放机械手与激光
            if (lmToBeReleased != null)
            {
                lmToBeReleased.occupied = false;
            }
            Robot.robot1.occupied = false;
            Robot.robot1.parkWaitCount -= 1;
            //自动化测试用
            //ManualParkingSimul.ins.Update(Int32.Parse(queueCmd.LicenseNum.Substring(2, 1)));
            //ParkingSimul.ins.Update(Int32.Parse(queueCmd.LicenseNum.Substring(2, 1)));
            //根据号牌查找车型
            //int vehicleTypeID = oper.getVehicleTypeID(numberPlate);
            //判断测量数据是否准确
            //bool isDataRight = oper.IsDataRight(vehicleTypeLength, vehicleTypeWidth, vehicleTypeHeight, vehicleTypeWheelbase, vehicleTypeID);
            if (queueCmd.id == 1)
            {
                //Task.Factory.StartNew(() =>
                //{
                BroadcastLinker.dispForAWhile(0, "停车完成", 10, true);
                //BroadcastLinker.ins.DispString(0, "停车完成", 6);
                if (BroadcastLinker.ins != null)
                {
                    BroadcastLinker.ins.Play(0, BroadcastBoard.PlayMode.audio, "操作成功");
                }
                //    Thread.Sleep(5000);
                //BroadcastLinker.OriginState();
                //});
            }
            //正常写入数据库
            if (userID != 0)
            {
                lock (Parking_Space.RecordLock)
                {
                    if (!queueCmd.manual)
                    {
                        //事务，写入停车记录, 更新车辆信息
                        int parkingRecordsID = 0;
                        string insertRecordSql = "";
                        try
                        {
                            insertRecordSql = "insert into parkingrecords(userID,numberPlate,parkingSpaceID,garageID,parkingRecordsState,realParkTime) values('" + userID + "','" + queueCmd.LicenseNum + "','" + ppp.parkingSpaceID + "','" + garageID + "',3,'" + realParkTime + "')";
                            List<string> strs = new List<string>();
                            strs.Add(insertRecordSql);
                            parkingRecordsID = DBOperation.InsertParkingRecords(EntityForCore.remoteBQ, strs);
                            int i = 0;
                            while (parkingRecordsID == 0 && i < 2)
                            {
                                parkingRecordsID = DBOperation.InsertParkingRecords(EntityForCore.remoteBQ, strs);
                                i++;
                            }
                            if (parkingRecordsID == 0)
                            {
                                //数据库操作失败写日志
                                Log.WriteLog(LogType.DATABASE, "1", insertRecordSql);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message + "插入停车记录表失败");
                            //数据库操作失败写日志
                            Log.WriteLog(LogType.DATABASE, "1", insertRecordSql);
                        }
                        string updateParkingSpaceStateSql = "";
                        string updateFreeSpaceSql = "";
                        string updateVehicleSql = "";
                        try
                        {
                            int freeSpace = ParkingSpaceManager.ins.GetFreeSpaceCount();
                            List<string> strs = new List<string>();
                            updateParkingSpaceStateSql = "update parkingspace set parkingSpaceState = 1 where parkingSpaceID = '" + ppp.parkingSpaceID + "'";
                            updateFreeSpaceSql = "update garage set garageFreeSpace = '" + freeSpace + "' where garageID = '" + garageID + "'";
                            updateVehicleSql = "update vehicle set vehiclepParkState = 1,scanEntryTime = '" + queueCmd.TimeRecord + "',parkingRecordsID = '" + parkingRecordsID + "',parkingSpaceID = '" + ppp.parkingSpaceID + "',vehicleTypeConfirm = 1,frontwheelbase = '" + frontWheelbase + "',rearwheelbase = '" + rearWheelbase + "' where numberPlate = '" + queueCmd.LicenseNum + "'";
                            strs.Add(updateParkingSpaceStateSql);
                            strs.Add(updateFreeSpaceSql);
                            strs.Add(updateVehicleSql);
                            bool result = DBOperation.UpdateTransaction(EntityForCore.remoteBQ, strs);
                            int i = 0;
                            while (!result && i < 2)
                            {
                                result = DBOperation.UpdateTransaction(EntityForCore.remoteBQ, strs);
                                i++;
                            }
                            if (!result)
                            {
                                //数据库操作失败写日志
                                Log.WriteLog(LogType.DATABASE, "0", updateParkingSpaceStateSql);
                                Log.WriteLog(LogType.DATABASE, "0", updateFreeSpaceSql);
                                Log.WriteLog(LogType.DATABASE, "0", updateVehicleSql);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message + "停车事务处理失败");
                            //数据库操作失败写日志
                            Log.WriteLog(LogType.DATABASE, "0", updateParkingSpaceStateSql);
                            Log.WriteLog(LogType.DATABASE, "0", updateFreeSpaceSql);
                            Log.WriteLog(LogType.DATABASE, "0", updateVehicleSql);
                        }
                    }
                    else
                    {
                        //事务，写入停车记录, 更新车辆信息
                        int parkingRecordsID = 0;
                        string insertRecordSql = "";
                        try
                        {
                            insertRecordSql = "insert into parkingrecords(userID,numberPlate,parkingSpaceID,garageID,parkingRecordsState,realParkTime) values('" + userID + "','" + queueCmd.LicenseNum + "','" + ppp.parkingSpaceID + "','" + garageID + "',3,'" + realParkTime + "')";
                            List<string> strs = new List<string>();
                            strs.Add(insertRecordSql);
                            parkingRecordsID = DBOperation.InsertParkingRecords(EntityForCore.localBQ, strs);
                            if (parkingRecordsID == 0)
                            {
                                //数据库操作失败写日志
                                Log.WriteLog(LogType.DATABASE, "1", insertRecordSql);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message + "插入停车记录表失败");
                        }
                        string updateParkingSpaceStateSql = "";
                        string updateFreeSpaceSql = "";
                        string updateVehicleSql = "";
                        try
                        {
                            int freeSpace = ParkingSpaceManager.ins.GetFreeSpaceCount();
                            List<string> strs = new List<string>();
                            updateParkingSpaceStateSql = "update parkingspace set parkingSpaceState = 1 where parkingSpaceID = '" + ppp.parkingSpaceID + "'";
                            updateFreeSpaceSql = "update garage set garageFreeSpace = '" + freeSpace + "' where garageID = '" + garageID + "'";
                            updateVehicleSql = "update vehicle set vehiclepParkState = 1,scanEntryTime = '" + queueCmd.TimeRecord + "',parkingRecordsID = '" + parkingRecordsID + "',parkingSpaceID = '" + ppp.parkingSpaceID + "',vehicleTypeConfirm = 1,frontwheelbase = '" + frontWheelbase + "',rearwheelbase = '" + rearWheelbase + "' where numberPlate = '" + queueCmd.LicenseNum + "'";
                            strs.Add(updateParkingSpaceStateSql);
                            strs.Add(updateFreeSpaceSql);
                            strs.Add(updateVehicleSql);
                            bool result = DBOperation.UpdateTransaction(EntityForCore.localBQ, strs);
                            if (!result)
                            {
                                //数据库操作失败写日志
                                Log.WriteLog(LogType.DATABASE, "0", updateParkingSpaceStateSql);
                                Log.WriteLog(LogType.DATABASE, "0", updateFreeSpaceSql);
                                Log.WriteLog(LogType.DATABASE, "0", updateVehicleSql);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message + "停车事务处理失败");
                        }
                    }
                }
            }
            //异常写入日志文件
            else
            {
                LogFile logFile = LogFile.ERROR_NUMBERPLATE;
                Log.WriteLog(LogType.NOT_DATABASE, logFile, "号牌：" + queueCmd.LicenseNum);
                Log.WriteLog(LogType.NOT_DATABASE, logFile, "入库时间：" + realParkTime);
                Log.WriteLog(LogType.NOT_DATABASE, logFile, "车位id：" + ppp.parkingSpaceID);
                Log.WriteLog(LogType.NOT_DATABASE, logFile, "车位x：" + ppp.parkingSpaceX);
                Log.WriteLog(LogType.NOT_DATABASE, logFile, "车位y：" + ppp.parkingSpaceY);
                Log.WriteLog(LogType.NOT_DATABASE, logFile, "车位z：" + ppp.parkingSpaceZ);
                //异常情况处理有待讨论
            }
        }
    }

    /// <summary>
    /// 取车命令处理类
    /// </summary>
    public class FetchCmd : AbstractCmd
    {
        /// <summary>
        /// 等待取车完成信号
        /// </summary>
        /// <param name="queueCmd"></param>
        /// <param name="parkingSpaceID"></param>
        /// <param name="robotError"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        private bool waitForFetchCompletionSignal(Command queueCmd, int parkingSpaceID, ref bool robotError, int status)
        {
            string connectionStr = null;
            PLCMessage PLCMsg = null;
            MyTimer mt = new MyTimer();
            mt.StartTiming();
            int fetchingStatus = 0;
            while (!isClosing)
            {
                PLCMsg = (PLCMessage)PLC.GetMessage();
                //fetchingStatus = Convert.ToInt32(PLCMsg.originalPlcList[fetch_completed_address].Value);
                if (PLCMsg.originalPlcList.Count != 0)
                {
                    fetchingStatus = Convert.ToInt32(PLCMsg.originalPlcList[fetch_completed_address].Value);
                }
                else
                {
                    fetchingStatus = -1;
                }
                //取车完成信号
                if (fetchingStatus == status)
                {
                    //取车完成后或可归零
                    //UILogServer.ins.log("取车流程：" + queueCmd.LicenseNum + "获得取车完成信号" + status);
                    Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "取车流程：" + queueCmd.LicenseNum + "获得取车完成信号" + status);
                    break;
                }
                else if (1 == 2)//机械手异常，则退指令，写数据库归位，判断条件需之后补充
                {
                    robotError = true;
                    queueCmd.returnedCount += 1;
                    queuingThread.SetMessage(queueCmd);
                    if (!queueCmd.manual)
                    {
                        oper.UpdateParkingSpaceState(EntityForCore.remoteBQ, parkingSpaceID, 0);
                    }
                    else
                    {
                        oper.UpdateParkingSpaceState(EntityForCore.localBQ, parkingSpaceID, 0);
                    }
                    break;
                }
                Thread.Sleep(1000);
                mt.EndTiming();
                int activationCount = 0;
                if (mt.IsLonger(120, 1, false, out activationCount))
                {
                    if (activationCount == 1)
                    {
                        UILogServer.ins.info("取车流程：" + queueCmd.LicenseNum + "未获得取车完成信号" + status + "，继续等待");
                    }
                    if (MyTimer.restart && !mt.rolledBack)
                    {
                        mt.rolledBack = true;
                        UILogServer.ins.error(queueCmd.LicenseNum + "等待取车完成信号" + status + "超时，流程回滚");
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, queueCmd.LicenseNum + "等待取车完成信号" + status + "超时，流程回滚");
                        return false;
                    }
                }
            }
            return true;
        }

        public override void executeCmd(Command queueCmd)
        {
            //UILogServer.ins.info("取车流程:" + queueCmd.LicenseNum + "开始");
            BroadcastLinker.dispForAWhile(0, "取车开始", 10, false);
            BroadcastLinker.dispForAWhile(1, queueCmd.LicenseNum, 10, false);
            Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "取车流程:" + queueCmd.LicenseNum + "开始");
            Vehicle vehiclelist = null;                 //待取车辆信息
            ControlMessage cm = null;
            Parking_Space ps = null;                 //车位信息
            int frontwheelbase;                         //前轮距
            int rearwheelbase;                           //后轮距
            int garageID;                                   //车库ID
            bool robotError = false;                  //机械手是否异常
                                                      //获取车辆表中车辆相关信息
            if (queueCmd.manual)
            {
                //vehiclelist = oper.GetLocalVehicle(connectionStr, queueCmd.LicenseNum, queueCmd.garageID);
            }
            else
            {
                vehiclelist = oper.GetVehicle(EntityForCore.remoteBQ, queueCmd.LicenseNum);
                int i = 0;
                while (vehiclelist == null && i < 2)
                {
                    vehiclelist = oper.GetVehicle(EntityForCore.remoteBQ, queueCmd.LicenseNum);
                    i++;
                }
            }
            if (vehiclelist == null)
            {
                //无法获取车辆信息，流程中止
                EntityForCore.ins.globalStatus = false;
                int count = 0;
                while (!MyTimer.restart)
                {
                    count++;
                    if (count == 1)
                    {
                        UILogServer.ins.error("无法获取车辆信息,请回滚流程");
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "无法从数据库获取车辆信息，流程中止");
                    }
                    Thread.Sleep(5000);
                }
                Rollback(queueCmd, 0, false, false, null);
                return;
            }
            int parkingSpaceID = vehiclelist.parkingSpaceID;
            garageID = vehiclelist.garageID;
            frontwheelbase = vehiclelist.frontwheelbase;
            rearwheelbase = vehiclelist.rearwheelbase;
            queueCmd.parkingRecordsID = vehiclelist.parkingRecordsID;
            if (!ParkingSpaceManager.ins.parkingSpaceStatusMap.TryGetValue(parkingSpaceID, out ps) || ps == null)
            {
                EntityForCore.ins.globalStatus = false;
                int count = 0;
                while (!MyTimer.restart)
                {
                    count++;
                    if (count == 1)
                    {
                        UILogServer.ins.error("车位分配出现异常！！！请回滚流程并初始化系统");
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "车位分配出现异常！！！");
                    }
                    Thread.Sleep(5000);
                }
                Rollback(queueCmd, parkingSpaceID, false, false, null);
                return;
            }

            cm = new ControlMessage();
            //启动机械手
            int robotID = 0;
            robotID = parkingSpaceID / 50 + 1;
            if (!WaitForRobotResource(robotID))
            {
                Rollback(queueCmd, parkingSpaceID, false, false, null);
                return;
            }
            //取车
            int status = 4;
            cm.status = status;
            //先手动赋值
            cm.RobotID = 1;            //1号机械手
            cm.fetchPosition = 1;    //放置地址
            cm.parkingSpaceID = Convert.ToString(ps.parkingSpaceID);
            cm.parkingSpaceX = Convert.ToString(ps.parkingSpaceX);
            cm.parkingSpaceY = Convert.ToString(ps.parkingSpaceY);
            cm.parkingSpaceZ = Convert.ToString(ps.parkingSpaceZ);
            cm.frontWheelbase = frontwheelbase;
            cm.rearWheelbase = rearwheelbase;
            PLC.SetMessage(cm);


            BroadcastLinker.dispForAWhile(0, "放车到" + ps.parkingSpaceX, 60, false);
            //BroadcastLinker.ins.DispString(0, "放车到" + ps.parkingSpaceX, 6);
            //Thread.Sleep(5000);
            //BroadcastLinker.ins.DispDownStr(0, 0);

            Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "取车流程:" + queueCmd.LicenseNum + "取车");
            UILogServer.ins.info("取车流程:" + queueCmd.LicenseNum + "取车");
            //等待PLC取车完成信号
            if (!waitForFetchCompletionSignal(queueCmd, ps.parkingSpaceID, ref robotError, 1))
            {
                Rollback(queueCmd, ps.parkingSpaceID, true, false, null);
                return;
            }
            //取车完成
            status = 5;
            ControlMessage cm2 = new ControlMessage();
            cm2.status = status;
            //先手动赋值
            cm2.RobotID = 1;   //机械手复位
            PLC.SetMessage(cm2);
            if (!waitForFetchCompletionSignal(queueCmd, ps.parkingSpaceID, ref robotError, 0))
            {
                Rollback(queueCmd, ps.parkingSpaceID, true, false, null);
                return;
            }
            //释放机械手
            Robot.robot1.occupied = false;
            Robot.robot1.fetchWaitCount -= 1;

            //释放缓冲位与车位,缓冲位ID暂用车位X代替
            if (ParkingSpaceManager.ins == null || !ParkingSpaceManager.ins.SetParkingSpace(ps.parkingSpaceID, 0))
            {
                Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "车位重复释放，请检查"); UILogServer.ins.error("车位重复释放，请检查");
            }
            if (ParkingBufferManager.ins == null || !ParkingBufferManager.ins.ReleaseParkingBuffer(ps.parkingSpaceX))
            {
                Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "缓冲位编号" + ps.parkingSpaceX + "未找到，请检查"); UILogServer.ins.error("缓冲位编号" + ps.parkingSpaceX + "未找到，请检查");
            }
            Log.WriteLog(LogType.NOT_DATABASE, LogFile.INFO, "取车流程：号牌：" + queueCmd.LicenseNum + "取车完成");
            UILogServer.ins.info("取车流程：号牌：" + queueCmd.LicenseNum + "取车完成");

            //自动化测试用
            //ManualParkingSimul.ins.Update(Int32.Parse(queueCmd.LicenseNum.Substring(2, 1)));
            //ParkingSimul.ins.Update(Int32.Parse(queueCmd.LicenseNum.Substring(2, 1)));

            BroadcastLinker.dispForAWhile(0, "取车完成", 10, true);
            //BroadcastLinker.ins.DispString(0, "停车完成", 6);
            if (BroadcastLinker.ins != null)
            {
                BroadcastLinker.ins.Play(0, BroadcastBoard.PlayMode.audio, "谢谢惠顾，一路顺风");
            }
            //    Thread.Sleep(5000);
            //BroadcastLinker.OriginState();

            int freeSpaceCount = ParkingSpaceManager.ins.GetFreeSpaceCount();
            //数据库更新
            lock (Parking_Space.RecordLock)
            {
                lock (Parking_Space.spaceLock)
                {
                    if (!queueCmd.manual)
                    {
                        string updateParkingSpaceStateSql = "";
                        string updateFreeSpaceSql = "";
                        string updateVehicleStateSql = "";
                        string updateParkingRecordsSql = "";
                        //取车事务
                        try
                        {
                            List<string> strs = new List<string>();
                            updateParkingSpaceStateSql = "update parkingspace set parkingSpaceState = 0 where parkingSpaceID = '" + ps.parkingSpaceID + "'";
                            updateFreeSpaceSql = "update garage set garageFreeSpace = '" + freeSpaceCount + "' where garageID = '" + garageID + "'";
                            updateVehicleStateSql = "update vehicle set vehiclepParkState = 0 where numberPlate = '" + queueCmd.LicenseNum + "'";
                            updateParkingRecordsSql = "update parkingrecords set parkingRecordsState = 6,realGetTime = '" + queueCmd.TimeRecord + "'where parkingRecordsID = '" + queueCmd.parkingRecordsID + "'";
                            strs.Add(updateParkingSpaceStateSql);
                            strs.Add(updateFreeSpaceSql);
                            strs.Add(updateVehicleStateSql);
                            strs.Add(updateParkingRecordsSql);
                            bool result = DBOperation.UpdateTransaction(EntityForCore.remoteBQ, strs);
                            int i = 0;
                            while (!result && i < 2)
                            {
                                result = DBOperation.UpdateTransaction(EntityForCore.remoteBQ, strs);
                                i++;
                            }
                            if (!result)
                            {
                                //写日志记录sql，以待之后处理
                                Log.WriteLog(LogType.DATABASE, "0", updateParkingSpaceStateSql);
                                Log.WriteLog(LogType.DATABASE, "0", updateFreeSpaceSql);
                                Log.WriteLog(LogType.DATABASE, "0", updateVehicleStateSql);
                                Log.WriteLog(LogType.DATABASE, "0", updateParkingRecordsSql);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message + "取车事务处理失败");
                        }
                    }
                    else
                    {
                        string updateParkingSpaceStateSql = "";
                        string updateFreeSpaceSql = "";
                        string updateVehicleStateSql = "";
                        string updateParkingRecordsSql = "";
                        //取车事务
                        try
                        {
                            List<string> strs = new List<string>();
                            updateParkingSpaceStateSql = "update parkingspace set parkingSpaceState = 0 where parkingSpaceID = '" + ps.parkingSpaceID + "'";
                            updateFreeSpaceSql = "update garage set garageFreeSpace = '" + freeSpaceCount + "' where garageID = '" + garageID + "'";
                            updateVehicleStateSql = "update vehicle set vehiclepParkState = 0 where numberPlate = '" + queueCmd.LicenseNum + "'";
                            updateParkingRecordsSql = "update parkingrecords set parkingRecordsState = 6,realGetTime = '" + queueCmd.TimeRecord + "'where parkingRecordsID = '" + queueCmd.parkingRecordsID + "'";
                            strs.Add(updateParkingSpaceStateSql);
                            strs.Add(updateFreeSpaceSql);
                            strs.Add(updateVehicleStateSql);
                            strs.Add(updateParkingRecordsSql);
                            DBOperation.UpdateTransaction(EntityForCore.localBQ, strs);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message + "取车事务处理失败");
                            //写日志记录sql，以待之后处理
                            Log.WriteLog(LogType.DATABASE, "0", updateParkingSpaceStateSql);
                            Log.WriteLog(LogType.DATABASE, "0", updateFreeSpaceSql);
                            Log.WriteLog(LogType.DATABASE, "0", updateVehicleStateSql);
                            Log.WriteLog(LogType.DATABASE, "0", updateParkingRecordsSql);
                        }
                    }
                }
                Thread.Sleep(1000);
            }
        }
    }

    /// <summary>
    /// 异常命令处理类
    /// </summary>
    public class ExceptionCmd : AbstractCmd
    {
        public override void executeCmd(Command queueCmd)
        {
            if (queueCmd.commandType == 'e')
            {
                //int userId = Convert.ToInt32(queueCmd.userID);
                ////过期用户指令
                //oper.InsertToMessageQueue(DBConnection.remoteConf, userId, "停车异常，请联系管理员！", 2);
                ////未能停车，将车辆状态复位
                //oper.UpdateVehicleParkState(DBConnection.remoteConf, queueCmd.LicenseNum, 0);
                //Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "过期用户指令,车牌号：" + queueCmd.LicenseNum);
                //UILogServer.ins.error("过期用户指令,车牌号：" + queueCmd.LicenseNum);
                ////continue;
            }
        }
    }

    /// <summary>
    /// 简单命令工厂
    /// </summary>
    public class SimpleCMDFactory
    {
        public AbstractCmd createCmd(Command queueCmd)
        {
            AbstractCmd abstractCmd = null;

            if (queueCmd.commandType == 's')
            {
                abstractCmd = new StopCmd();
            }
            if (queueCmd.commandType == 'f')
            {
                abstractCmd = new FetchCmd();
            }
            if (queueCmd.commandType == 'e')
            {
                abstractCmd = new ExceptionCmd();
            }
            return abstractCmd;
        }
    }

}
