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;
namespace parkMonitor.server.CoreThread
{
///
/// 核心对命令处理父类
///
public abstract class AbstractCmd
{
public static bool isClosing { get; set; }
///
/// 设备总状态PLC地址
///
public int equipmentStatus_address { set; get; }
///
/// 停车完成PLC地址
///
public int park_completed_address { set; get; }
///
/// 停车入口X坐标
///
public int parkingEntX { set; get; }
///
/// 停车入口Y坐标
///
public int parkingEntY { set; get; }
///
/// 停车入口Z坐标
///
public int parkingEntZ { set; get; }
///
/// 取车完成PLC地址
///
public int fetch_completed_address { set; get; }
///
/// 轮距测量状态PLC地址
///
public int wheelbase_status_address { get; set; }
///
/// 停车启动机械手PLC地址
///
public int parking_startRobot_address { get; set; }
///
/// 取车启动机械手PLC地址
///
public int fetching_startRobot_address { get; set; }
///
/// 前轮距PLC地址
///
public int frontWheelbase_address { get; set; }
///
/// 后轮距PLC地址
///
public int rearWheelbase_address { get; set; }
///
/// PLC句柄
///
public IEquipments PLC { set; get; }
///
/// 队列线程句柄
///
public IEquipments queuingThread { set; get; }
///
/// 数据库操作句柄
///
public DBOperation oper { set; get; }
///
/// 号牌机线程句柄
///
public IEquipments NumMachine { set; get; }
///
/// 车库中心
///
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);
///
/// 等待机械手空闲资源
///
///
///
public bool WaitForRobotResource(int robotID)
{
PLCMessage PLCMsg = null;
MyTimer mt = new MyTimer();
mt.StartTiming();
lock (Robot.robot1)
{
while (!isClosing)
{
PLCMsg = (PLCMessage)PLC.GetMessage();
bool occupied = true;
if (PLCMsg != null)
{
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;
}
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;
}
Thread.Sleep(100);
}
}
}
return true;
}
/// ///
/// 流程回滚函数
///
///
///
///
///
public void Rollback(Command queueCmd, int parkingSpaceID, bool robotAllocated, bool isParking, LaserMessage lm)
{
//命令回退
queueCmd.returnedCount += 1;
queuingThread.SetMessage(queueCmd);
//线程计数调整
if (robotAllocated)
{
Robot.robot1.occupied = false;
}
Robot.robot1.waitCount -= 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;
}
}
else
{
//复原已释放的车位
if (!ParkingSpaceManager.ins.SetParkingSpace(parkingSpaceID, 1))
{
EntityForCore.ins.globalStatus = false;
Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "车位分配出现异常,需要重启");
return;
}
}
}
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);
}
}
}
}
}
///
/// 停车命令处理类
///
public class StopCmd : AbstractCmd
{
///
/// 停车数据库事务
///
private void StopParkingSubmit()
{
}
///
/// 命令中号牌与对应号牌机中当前号牌比对,确认车辆
///
private bool NumValidation(Command queueCmd, int countdown, float ratio)
{
List 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;
}
///
/// 号牌复位
///
private void NumReset(Command queueCmd)
{
NumberMachineMessage numberMachineMessage = new NumberMachineMessage();
numberMachineMessage.aNode = new NumberMachineNode();
numberMachineMessage.aNode.ip = "";
numberMachineMessage.aNode.LicenseNum = queueCmd.LicenseNum;
queuingThread.SetMessage(numberMachineMessage);
}
///
/// 车位资源
///
///
///
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(200);
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(100);
}
}
return ppp;
}
///
/// 等待激光数据
///
/// 传入的命令
/// 车辆是否已驶离
///
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)
{
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(100);
}
}
return data;
}
///
/// 停车完成
///
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)
{
Thread.Sleep(1000);
PLCMsg = (PLCMessage)PLC.GetMessage();
int storeStatus = Convert.ToInt32(PLCMsg.originalPlcList[park_completed_address].Value);
//停车完成信号
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;
}
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(100);
}
}
return true;
}
///
/// 等待轮距信息
///
/// 前轮距
/// 后轮距
private bool WaitWheelbase(ref int frontWheelbase, ref int rearWheelbase)
{
PLCMessage PLCMsg = null;
MyTimer mt = new MyTimer();
mt.StartTiming();
while (!isClosing)
{
PLCMsg = (PLCMessage)PLC.GetMessage();
int 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(100);
}
}
return true;
}
///
/// 停车流程
///
///
public override void executeCmd(Command queueCmd)
{
//UILogServer.ins.info("停车流程:" + queueCmd.LicenseNum + "开始");
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.laserID = queueCmd.id / 6 + 1;
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)
{
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 numValidationResult = new Func(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;//启动对应机械手
//激光数据
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.waitCount -= 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 (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 strs = new List();
strs.Add(insertRecordSql);
parkingRecordsID = DBOperation.InsertParkingRecords(EntityForCore.remoteBQ, strs);
}
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 strs = new List();
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);
DBOperation.UpdateTransaction(EntityForCore.remoteBQ, strs);
}
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 strs = new List();
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 strs = new List();
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);
object result = DBOperation.UpdateTransaction(EntityForCore.localBQ, strs);
if (!(bool)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);
//异常情况处理有待讨论
}
}
}
///
/// 取车命令处理类
///
public class FetchCmd : AbstractCmd
{
///
/// 等待取车完成信号
///
///
///
///
///
///
private bool waitForFetchCompletionSignal(Command queueCmd, int parkingSpaceID, ref bool robotError, int status)
{
string connectionStr = null;
PLCMessage PLCMsg = null;
MyTimer mt = new MyTimer();
mt.StartTiming();
while (!isClosing)
{
Thread.Sleep(2000);
PLCMsg = (PLCMessage)PLC.GetMessage();
int fetchingStatus = Convert.ToInt32(PLCMsg.originalPlcList[fetch_completed_address].Value);
//取车完成信号
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;
}
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(100);
}
}
return true;
}
public override void executeCmd(Command queueCmd)
{
//UILogServer.ins.info("取车流程:" + queueCmd.LicenseNum + "开始");
Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "取车流程:" + queueCmd.LicenseNum + "开始");
string connectionStr = null; //数据库连接字符串
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);
}
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);
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.waitCount -= 1;
//释放缓冲位与车位,缓冲位ID暂用车位X代替
if (ParkingSpaceManager.ins == null || !ParkingSpaceManager.ins.SetParkingSpace(ps.parkingSpaceID, 0) || ParkingBufferManager.ins == null || !ParkingBufferManager.ins.ReleaseParkingBuffer(ps.parkingSpaceX))
{
Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "车位异常,请检查"); UILogServer.ins.error("车位异常,请检查");
}
Log.WriteLog(LogType.NOT_DATABASE, "取车流程:号牌:" + 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)));
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 strs = new List();
updateParkingSpaceStateSql = "update parkingspace set parkingSpaceState = 1 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);
object result = DBOperation.UpdateTransaction(EntityForCore.remoteBQ, strs);
if (!(bool)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 strs = new List();
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);
}
}
}
///
/// 异常命令处理类
///
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;
}
}
}
///
/// 简单命令工厂
///
public class SimpleCMDFactory
{
//DBOperation oper = new DBOperation();
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;
}
}
}