using Terminal; using db; using System.Collections.Generic; using System.Threading.Tasks; using PLCS7; using System; using System.Text; using MySql.Data.MySqlClient; using System.Threading; using BroadcastModule; using parkMonitor.LOG; using centralController.model; namespace Terminal { public class Terminal { public static List terminalInfo = new List(); /// /// 记录地面停车位id与获取号牌映射 /// private static Dictionary idLicMap = new Dictionary(); /// /// 记录地面停车位id与凭证号映射 /// private static Dictionary idReceiptMap = new Dictionary(); /// /// 取车地面位id与是否已计费标记映射 /// public static Dictionary termCalcMap = new Dictionary(); /// /// 终端ID与取车完成标志映射 /// public static Dictionary fetchCompleteMap = new Dictionary(); /// /// 终端ID与取车信息映射 /// private static Dictionary fetchInfoMap = new Dictionary(); private static List lockList = new List(); public static bool isClosing = false; /// /// 从终端结构体中获得车牌号 /// /// /// private static string GetLicenseFromTerm(TerminalStru ts) { string header = Encoding.ASCII.GetString(BitConverter.GetBytes(ts.licenseCodeB)); string identityA = Encoding.ASCII.GetString(BitConverter.GetBytes(ts.licenseCodeC)); byte[] bytes = BitConverter.GetBytes(ts.licenseCodeD); List newBytes = new List(); for (int i = 0; i < bytes.Length; i++) { if (bytes[i] != 0x00) { newBytes.Add(bytes[i]); } } string identityB = Encoding.ASCII.GetString(newBytes.ToArray()); Log.WriteLog(LogType.process, LogFile.INFO, "已从终端" + ts.terminalID + "获得号牌:" + header + identityA + identityB); //根据省份对应的两位数字查找汉字 string province = header.Substring(0, 2); string provinceIndex = header.Substring(2); string provinceQuerySql = "select NumberPlateHeader from numberplatemapping where mappedString = " + province + ";"; if (province != "/0/0") { lock (Monitor.Monitor.localDBOper) { //object[] result = Monitor.Monitor.localDBOper.Query(provinceQuerySql); MySqlDataReader reader = Monitor.Monitor.localDBOper.Query(provinceQuerySql); try { if (reader != null && reader.Read() && reader.HasRows) { province = reader.GetString("NumberPlateHeader"); //Console.WriteLine(province); } } catch { } try { //if (result!=null && result.Length > 0) { province = (string)result[0]; } if (reader != null) { reader.Close(); reader.Dispose(); } } catch { } } return province + provinceIndex + identityA + identityB; } else return ""; } /// /// 更新所有车位信息 /// private static void UpdateAllParkingSpace(bool remote) { string findParkingSpace = "select parkingSpaceID from parkingspace;"; HashSet recordsIDSet = new HashSet(); DBOperation dbHandle = null; if (!remote) { dbHandle = Monitor.Monitor.localDBOper; } else { dbHandle = Monitor.Monitor.remoteDBOper; } lock (dbHandle) { MySqlDataReader reader = dbHandle.Query(findParkingSpace); if (reader != null) { try { while (reader.Read()) { if (reader.HasRows) { recordsIDSet.Add(reader.GetInt32("parkingSpaceID")); } } } catch { Log.WriteLog(LogType.process, LogFile.INFO, "数据库车位查询异常"); } try { reader.Close(); reader.Dispose(); } catch { } } } List updateSpaceList = new List(); List insertSpaceList = new List(); string updateParkingSpace = ""; string insertParkingSpace = ""; for (int i = 0; i < Monitor.Monitor.parkingSpaceInfo.Count; i++) { if (recordsIDSet.Contains(Monitor.Monitor.parkingSpaceInfo[i].parkingSpace)) { updateParkingSpace = "update parkingspace set parkingSpaceX = " + Monitor.Monitor.parkingSpaceInfo[i].coordX + ",parkingSpaceY = " + Monitor.Monitor.parkingSpaceInfo[i].coordY + ",parkingSpaceZ = " + Monitor.Monitor.parkingSpaceInfo[i].floorNo + ",parkingSpaceState = " + Monitor.Monitor.parkingSpaceInfo[i].spaceStatus + " where (parkingSpaceID = " + Monitor.Monitor.parkingSpaceInfo[i].parkingSpace + ");"; updateSpaceList.Add(updateParkingSpace); } else { if (!remote) { insertParkingSpace = "insert into parkingspace (parkingSpaceID,parkingSpaceX,parkingSpaceY,parkingSpaceZ,parkingSpaceState) values (" + Monitor.Monitor.parkingSpaceInfo[i].parkingSpace + "," + Monitor.Monitor.parkingSpaceInfo[i].coordX + "," + Monitor.Monitor.parkingSpaceInfo[i].coordY + "," + Monitor.Monitor.parkingSpaceInfo[i].floorNo + "," + Monitor.Monitor.parkingSpaceInfo[i].spaceStatus + ");"; insertSpaceList.Add(insertParkingSpace); } else { insertParkingSpace = "insert into parkingspace (parkingSpaceID,parkingSpaceX,parkingSpaceY,parkingSpaceZ,parkingSpaceState,garageID,parkingSpaceName) values (" + Monitor.Monitor.parkingSpaceInfo[i].parkingSpace + "," + Monitor.Monitor.parkingSpaceInfo[i].coordX + "," + Monitor.Monitor.parkingSpaceInfo[i].coordY + "," + Monitor.Monitor.parkingSpaceInfo[i].floorNo + "," + Monitor.Monitor.parkingSpaceInfo[i].spaceStatus + "," + Monitor.Monitor.garageID + ",'默认');"; insertSpaceList.Add(insertParkingSpace); } } } try { lock (dbHandle) { int id = 0; dbHandle.UpdateTransaction(updateSpaceList); dbHandle.Insert(insertSpaceList, out id); } } catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "更新本地所有车位异常"); Console.WriteLine("更新本地所有车位异常" + e.Message); } } /// /// 更新车辆状态 /// /// /// private static void UpdateVehicle(string lic, int state, int parkingRecordsID, bool park, bool remote, int parkingSpaceID) { if (lic != "") { MySqlDataReader reader; //查询车辆是否在车辆表中 string checkVehicleState = "select * from vehicle where numberPlate = '" + lic + "';"; if (!remote) { reader = Monitor.Monitor.localDBOper.Query(checkVehicleState); } else { //Log.WriteLog(LogType.database, "update, query: \n"); reader = Monitor.Monitor.remoteDBOper.Query(checkVehicleState); //Log.WriteLog(LogType.database, "update, query: \n" + checkVehicleState); } if (reader != null) { if (reader.Read() && reader.HasRows) { //更新车辆状态 string updateVehicleState = ""; string updateRemoteVehicleState = ""; if (park) { if (parkingRecordsID > 0) { if (parkingSpaceID == 0) { updateVehicleState = "update vehicle set vehiclepParkState = " + state + " ,parkingRecordsID = " + parkingRecordsID + " where numberPlate = '" + lic + "';"; updateRemoteVehicleState = "update vehicle set vehiclepParkState = " + state + " ,parkingRecordsID = " + parkingRecordsID + ",garageID = " + Monitor.Monitor.garageID + " where numberPlate = '" + lic + "';"; } else { updateVehicleState = "update vehicle set vehiclepParkState = " + state + " ,parkingRecordsID = " + parkingRecordsID + ",parkingSpaceID = " + parkingSpaceID + " where numberPlate = '" + lic + "';"; updateRemoteVehicleState = "update vehicle set vehiclepParkState = " + state + " ,parkingRecordsID = " + parkingRecordsID + ",parkingSpaceID = " + parkingSpaceID + ",garageID = " + Monitor.Monitor.garageID + " where numberPlate = '" + lic + "';"; } } else { updateVehicleState = "update vehicle set vehiclepParkState = " + state + " where numberPlate = '" + lic + "';"; updateRemoteVehicleState = updateVehicleState; } } else { updateVehicleState = "update vehicle set vehiclepParkState = " + state + " where numberPlate = '" + lic + "';"; updateRemoteVehicleState = updateVehicleState; } List list = new List(); if (!remote) { list.Add(updateVehicleState); Monitor.Monitor.localDBOper.UpdateTransaction(list); } else { //Log.WriteLog(LogType.database, "update, update: \n"); list.Add(updateRemoteVehicleState); Monitor.Monitor.remoteDBOper.UpdateTransaction(list); //Log.WriteLog(LogType.database, "update, update: \n" + updateRemoteVehicleState); } } else { //插入车辆 string insertVehicleWithState = ""; if (park) { if (parkingRecordsID > 0) insertVehicleWithState = "insert into vehicle (numberPlate,vehicleTypeID,vehiclepParkState,parkingRecordsID) values " + "('" + lic + "',NULL,'" + state + "'," + parkingRecordsID + ");"; else insertVehicleWithState = "insert into vehicle (numberPlate,vehicleTypeID,vehiclepParkState) values " + "('" + lic + "',NULL,'" + state + "');"; } else { Log.WriteLog(LogType.process, LogFile.ERROR, "取车无法获得车辆信息"); Console.WriteLine("明显异常,取车发现无车辆"); try { reader.Close(); reader.Dispose(); } catch { } return; } List list = new List(); list.Add(insertVehicleWithState); int id = 0; if (!remote) { Monitor.Monitor.localDBOper.Insert(list, out id); } else { Monitor.Monitor.remoteDBOper.Insert(list, out id); } } try { reader.Close(); reader.Dispose(); } catch { } } } } /// /// 流程结束清除终端相关信息,同时允许再次根据地感拍号牌 /// /// private static void ClearTerminal(int id, bool removeReceipt) { for (int i = 0; i < terminalInfo.Count; i++) { if (terminalInfo[i].terminalID == id) { Log.WriteLog(LogType.process, LogFile.WARNING, "即将删除终端" + id + "数据:" + terminalInfo[i].ToString()); lockList[i] = false; } } TerminalStru tsFromCentral = new TerminalStru { terminalID = (short)id, parkingFee = (short)32767, receiptNum = removeReceipt ? 0 : (short)-1 }; TerminalStru tsFromTerminal = new TerminalStru { terminalID = (short)id, btnStatus = (short)0, receiptNum = removeReceipt ? 0 : (short)-1 }; Monitor.Monitor.PLC.WriteToPLC(tsFromCentral, PLCDataType.central); Thread.Sleep(300); Monitor.Monitor.PLC.WriteToPLC(tsFromTerminal, PLCDataType.terminal); } /// /// 清除流程完成标记 /// private static void ResetCompleteSignal() { MainBlockStru mbs = new MainBlockStru { centralHearbeat = (short)-1, bookParkCmd = -1, bookFetchCmd = -1, processCompleted = (short)0, licenseReceived = (short)-1 }; Monitor.Monitor.PLC.WriteToPLC(mbs, PLCDataType.central); } /// /// 更新PLC提供的特定车位状态 /// /// private static void UpdateSpecificParkingSpace() { try { lock (Monitor.Monitor.PLCReadLock) { //获取当前车位ID int parkingSpaceID = Monitor.Monitor.mainBlockInfo.currentParkingSpaceID; //获取车位状态 List received = Monitor.Monitor.PLC.ReadFromPLC(PLCDataType.parkingSpace, parkingSpaceID); //本地车位更新 for (int i = 0; i < Monitor.Monitor.parkingSpaceInfo.Count; i++) { if (Monitor.Monitor.parkingSpaceInfo[i].parkingSpace == parkingSpaceID) { ParkingSpaceStru ps = Monitor.Monitor.parkingSpaceInfo[i]; ps.spaceStatus = (short)((ParkingSpaceStru)received[0]).spaceStatus; ps.receiptNum = ((ParkingSpaceStru)received[0]).receiptNum; ps.length = (short)((ParkingSpaceStru)received[0]).length; ps.width = (short)((ParkingSpaceStru)received[0]).width; ps.height = (short)((ParkingSpaceStru)received[0]).height; Monitor.Monitor.parkingSpaceInfo[i] = ps; break; } } } } catch { Console.WriteLine("更新此车位异常"); } } /// /// 验证会员信息 /// /// /// /// /// private static void ValidateUserInfo(TerminalStru ts, int userID, string license, out int status) { status = 0; //与云端数据比对 string checkNetSql = "select * from user where userID = 1;"; MySqlDataReader readerTest = Monitor.Monitor.remoteDBOper.Query(checkNetSql); if (readerTest != null) { if (readerTest.Read() && readerTest.HasRows) { try { readerTest.Close(); readerTest.Dispose(); } catch { } string userInfoCheckSql = "select * from usercarrelation where userID = '" + userID + "' and numberPlate = '" + license + "';"; MySqlDataReader reader = Monitor.Monitor.remoteDBOper.Query(userInfoCheckSql); if (reader != null && reader.Read() && reader.HasRows && userID != 0 && license != "") { ts.licVerification = 1;//验证成功 Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central); status = 1; Log.WriteLog(LogType.process, LogFile.INFO, "号牌验证成功"); Monitor.Monitor.SetNotification("注册用户,号牌验证成功", parkMonitor.model.TextColor.Info); } else { ts.licVerification = 1;//验证失败 Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central); status = 2; Log.WriteLog(LogType.process, LogFile.WARNING, "号牌验证失败"); Monitor.Monitor.SetNotification("注册用户,号牌验证失败", parkMonitor.model.TextColor.Error); } try { reader.Close(); reader.Dispose(); } catch { } } else { try { readerTest.Close(); readerTest.Dispose(); } catch { } ts.licVerification = 1;//网络异常,跳过验证 Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central); status = 1; Log.WriteLog(LogType.process, LogFile.ERROR, "网络异常,无法验证号牌"); } } } /// /// 查询停车记录id /// /// /// /// private static void QueryParkingRecordsID(string querySql, out int recordsID, bool remote) { recordsID = 0; MySqlDataReader reader = null; if (!remote) { reader = Monitor.Monitor.localDBOper.Query(querySql); } else { reader = Monitor.Monitor.remoteDBOper.Query(querySql); } if (reader != null) { try { while (reader.Read()) { if (reader.HasRows) recordsID = reader.GetInt32("parkingRecordsID"); } } catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "查询停车记录id失败"); Console.WriteLine(e.Message); }; try { reader.Close(); reader.Dispose(); } catch { } } } //private static void BookedCarProcess() //{ // for (int i = 0; i < terminalInfo.Count; i++) // { // if (terminalInfo[i].groundStatus == 1 && terminalInfo[i].btnStatus == 0) // { // string license = Monitor.Monitor.numMachineLinker.GetLicensePlate(terminalInfo[i].terminalID); // if (license == "") { break; } // else // { // } // } // } //} #region 获取号牌方法,已调整 /// /// 停车流程,收到号牌机启动后操作过程 /// private static void ParkNumSubProcess() { for (int i = 0; i < terminalInfo.Count; i++) { //启动指令与终端id匹配 //if (numMachineLaunch == terminalInfo[i].terminalID) if (terminalInfo[i].numMachineLaunch == 1 && terminalInfo[i].licVerification == 0) { if (!Monitor.Monitor.globalStatus) { Monitor.Monitor.SetNotification("号牌系统已暂停,将清除终端数据", parkMonitor.model.TextColor.Warning); ClearTerminal(i, true); Thread.Sleep(5000); return; } int numReceivedStatus = 0;//1获得,2终止 TerminalStru term = terminalInfo[i]; if (term.terminalStatus == (short)1) { string license = ""; license = Monitor.Monitor.numMachineLinker.GetLicensePlate(term.terminalID); //判断之前是否已拍摄号牌 if (!idLicMap.ContainsKey(term.terminalID)) { Monitor.Monitor.SetNotification("启动" + term.terminalID + "号号牌机,号牌:[" + license + "]", parkMonitor.model.TextColor.Info); } else { string lic = ""; idLicMap.TryGetValue(term.terminalID, out lic); if (license != lic && lic != "") { Monitor.Monitor.SetNotification("与地感获得号牌[" + lic + "]不一致,启动" + term.terminalID + "号号牌机,号牌:[" + license + "],最终使用[" + lic + "]停车", parkMonitor.model.TextColor.Warning); license = lic; } } //记录或更新当前号牌,若无则填入默认号牌 string currentLic = ""; lock (idLicMap) { if (license == "") { currentLic = Monitor.Monitor.defaultLic; Monitor.Monitor.SetNotification("使用默认号牌,凭证号" + term.receiptNum, parkMonitor.model.TextColor.Error); Log.WriteLog(LogType.process, LogFile.ERROR, term.terminalID + "号号牌机未获得号牌,使用默认号牌,凭证号:" + term.receiptNum); } else { currentLic = license; } try { if (idLicMap.ContainsKey(term.terminalID)) { if (!idLicMap[term.terminalID].Equals(currentLic)) idLicMap[term.terminalID] = currentLic; } else { idLicMap.Add(term.terminalID, currentLic); } } catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "号牌" + license + "记录号牌异常\n" + e.StackTrace); } } Log.WriteLog(LogType.process, LogFile.INFO, "号牌" + license + "已记录"); ////未获得号牌,告知PLC终止,告诉终端提示用户重新操作 //if (currentLic == "") //{ // MainBlockStru mbs = new MainBlockStru // { // centralHearbeat = (short)-1, // bookParkCmd = -1, // bookFetchCmd = -1, // processCompleted = (short)-1, // licenseReceived = (short)2 // }; // Monitor.Monitor.PLC.WriteToPLC(mbs, PLCDataType.central); // TerminalStru ts = new TerminalStru // { // terminalID = (short)term.terminalID, // paymentStatus = -1, // parkingFee = -1, // userType = -1, // licVerification = (short)1 // }; // Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central); // Thread.Sleep(500); // ClearTerminal(term.terminalID, false); // ResetCompleteSignal(); // Log.WriteLog(LogType.process, LogFile.ERROR, "未获得号牌"); //} //else //{ TerminalStru ts = new TerminalStru { terminalID = (short)term.terminalID, paymentStatus = -1, parkingFee = -1, userType = -1 }; //注册用户 if (term.btnStatus == (short)2 || term.btnStatus == (short)3) { int userID = term.licenseCodeA; string userLicense = GetLicenseFromTerm(term); //注册用户缺ID信息,转为普通用户停车,终端将限制该情况发生 if (userID == 0) { term.btnStatus = 1; } else { //与云端数据比对,比对失败转普通用户停车 ValidateUserInfo(ts, userID, userLicense, out numReceivedStatus); if (numReceivedStatus == 2) { term.btnStatus = 1; //idLicMap.Remove(term.terminalID); } } } //非注册用户 if (term.btnStatus == (short)1 || term.btnStatus == (short)4) { numReceivedStatus = 1; ts.licVerification = 1; Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central); } if (term.btnStatus == (short)0) { ts.licVerification = 1; Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central); Log.WriteLog(LogType.process, LogFile.ERROR, "空按钮状态拍号牌"); } //无论是否注册,皆告知PLC,已获取号牌或比对异常、终止流程 MainBlockStru mbst = new MainBlockStru { centralHearbeat = -1, bookFetchCmd = -1, bookParkCmd = -1, processCompleted = (short)-1, licenseReceived = (short)numReceivedStatus }; Monitor.Monitor.PLC.WriteToPLC(mbst, PLCDataType.central); int receiptCount = 6; while (receiptCount-- > 0) { term = terminalInfo[i]; try { if (idReceiptMap.ContainsKey(term.terminalID)) { if (!idReceiptMap[term.terminalID].Equals(term.receiptNum)) idReceiptMap[term.terminalID] = term.receiptNum; } else { idReceiptMap.Add(term.terminalID, term.receiptNum); } Log.WriteLog(LogType.process, LogFile.INFO, "记录凭证号:" + term.receiptNum + "\n"); if (term.receiptNum != 0) break; } catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "凭证号" + term.receiptNum + "记录凭证号异常\n" + e.StackTrace); } Thread.Sleep(1000); } //号牌获取结果被清零才跳出 Monitor.Monitor.SetNotification("已写入号牌获取结果" + numReceivedStatus + ",等待号牌机启动指令清零", parkMonitor.model.TextColor.Info); //} int countdown = 10; while (countdown-- > 0) { if (terminalInfo[i].numMachineLaunch == 0) { Monitor.Monitor.SetNotification("号牌机启动指令已被清零", parkMonitor.model.TextColor.Info); break; } else Thread.Sleep(500); } if (countdown == 0) Monitor.Monitor.SetNotification("提醒:未检测到号牌机启动指令被清零", parkMonitor.model.TextColor.Warning); } } } } #endregion /// /// 停车流程,收到PLC停车完成信号后操作过程 /// private static void ParkCompleteSubProcess() { //Console.WriteLine(Monitor.Monitor.mainBlockInfo.parkingRunning+","+ Monitor.Monitor.mainBlockInfo.processCompleted); int processAttrib = Monitor.Monitor.mainBlockInfo.parkingRunning; //int processCompleted = Monitor.Monitor.mainBlockInfo.processCompleted; int currentTerm = Monitor.Monitor.mainBlockInfo.terminalID; int parkingSpaceID = 0; if (processAttrib == 1) { TerminalStru term = new TerminalStru(); string license; //等待完成信号 while (true) { if (Monitor.Monitor.mainBlockInfo.processStopped == 1 || !Monitor.Monitor.globalStatus) { Log.WriteLog(LogType.process, LogFile.ERROR, "停车流程中断"); Monitor.Monitor.SetNotification("停车流程中断", parkMonitor.model.TextColor.Warning); Thread.Sleep(500); ClearTerminal(currentTerm, false); ResetCompleteSignal(); //流程终端清除记录的号牌 try { idLicMap.Remove(currentTerm); } catch { } return; } if (Monitor.Monitor.mainBlockInfo.processCompleted == 1) { if (!idLicMap.ContainsKey(currentTerm)) { Thread.Sleep(500); ClearTerminal(currentTerm, false); ResetCompleteSignal(); Log.WriteLog(LogType.process, LogFile.ERROR, "停车结束时未找到号牌"); } break; } Thread.Sleep(200); } //找到终端号,判断是否注册用户 //拿到号牌 if (/*terminalInfo[i].terminalID == currentTerm && */idLicMap.TryGetValue(currentTerm, out license) && license != "") { UpdateSpecificParkingSpace(); for (int i = 0; i < terminalInfo.Count; i++) { if (terminalInfo[i].terminalID == currentTerm) term = terminalInfo[i]; } //term = terminalInfo[currentTerm - 1]; Thread.Sleep(500); parkingSpaceID = Monitor.Monitor.mainBlockInfo.currentParkingSpaceID; int receipt = 0; idReceiptMap.TryGetValue(term.terminalID, out receipt); //无车位信息则跳出当前循环 if (parkingSpaceID == 0 || receipt == 0) { try { idLicMap.Remove(currentTerm); ClearTerminal(term.terminalID, false); } catch { } Monitor.Monitor.SetNotification("无车位或凭证号,车位:" + parkingSpaceID + ",凭证号:" + receipt, parkMonitor.model.TextColor.Warning); bool getReceiptFromParkingSpace = false; if (parkingSpaceID != 0) { for (int i = 0; i < Monitor.Monitor.parkingSpaceInfo.Count; i++) { if (Monitor.Monitor.parkingSpaceInfo[i].parkingSpace == parkingSpaceID) { int myReceipt = Monitor.Monitor.parkingSpaceInfo[i].receiptNum; if(myReceipt != 0) { receipt = myReceipt; getReceiptFromParkingSpace = true; } break; } } } if (!getReceiptFromParkingSpace) { //中控清除车牌、凭证号、号牌验证等信息 ClearTerminal(term.terminalID, false); //停车流程确保已清除中控块完成信号 ResetCompleteSignal(); return; } else { Monitor.Monitor.SetNotification("从车位获取凭证号,车位:" + parkingSpaceID + ",凭证号:" + receipt, parkMonitor.model.TextColor.Warning); } } //中控清除车牌、凭证号、号牌验证等信息 ClearTerminal(term.terminalID, false); //停车流程确保已清除中控块完成信号 ResetCompleteSignal(); // LED屏显示,停车完成可能不提示 //if (Monitor.Monitor.allInOneMachine.boardList.Count >= currentTerm) //{ // Monitor.Monitor.allInOneMachine.boardList[currentTerm - 1].UpdateText("停车完成", 60, 2); // Monitor.Monitor.allInOneMachine.boardList[currentTerm - 1].UpdateArrow(-1, 2, 0); //} UpdateVehicle(license, 0, 0, true, false, 0); UpdateVehicle(license, 0, 0, true, true, 0); //插入停车记录 string parkingRecordsSql = ""; if (term.licenseCodeA != 0) { parkingRecordsSql = "INSERT INTO parkingrecords (userID, numberPlate,parkingSpaceID,garageID,parkingRecordsState,realParkTime,receiptNum,parkingPrice)" + "values ('" + term.licenseCodeA + "','" + license + "','" + parkingSpaceID + "','" + Monitor.Monitor.garageID + "',3,'" + DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss") + "','" + receipt + "',NULL);"; Monitor.Monitor.SetNotification("用户" + term.licenseCodeA + "插入停车记录", parkMonitor.model.TextColor.Info); Log.WriteLog(LogType.process, LogFile.INFO, "用户" + term.licenseCodeA + "插入停车记录," + license + "停在" + parkingSpaceID + ",凭证号:" + receipt); } else { parkingRecordsSql = "INSERT INTO parkingrecords (userID, numberPlate,parkingSpaceID,garageID,parkingRecordsState,realParkTime,receiptNum,parkingPrice)" + "values ('" + 28 + "','" + license + "','" + parkingSpaceID + "','" + Monitor.Monitor.garageID + "',3,'" + DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss") + "','" + receipt + "',NULL);"; Monitor.Monitor.SetNotification("管理员用户,插入停车记录," + license + "停在" + parkingSpaceID, parkMonitor.model.TextColor.Info); Log.WriteLog(LogType.process, LogFile.INFO, "管理员用户,插入停车记录,凭证号: " + receipt + ",终端块数据:" + term.ToString()); } List list = new List(); list.Add(parkingRecordsSql); int parkingRecordsID = 0; int remoteParkingRecordsID = 0; Monitor.Monitor.localDBOper.Insert(list, out parkingRecordsID); bool remote_insert_record = Monitor.Monitor.remoteDBOper.Insert(list, out remoteParkingRecordsID); //Log.WriteLog(LogType.database, "insert, record: \n" + parkingRecordsSql); //查询记录ID号 //string findRecordSql = "select parkingRecordsID from parkingrecords where receiptNum = " + term.receiptNum + ";"; //QueryParkingRecordsID(findRecordSql, out parkingRecordsID, false); //QueryParkingRecordsID(findRecordSql, out remoteParkingRecordsID, true); //更新车辆表 if (parkingRecordsID != 0) { UpdateVehicle(license, 1, parkingRecordsID, true, false, parkingSpaceID); } if (remoteParkingRecordsID != 0) { UpdateVehicle(license, 1, remoteParkingRecordsID, true, true, parkingSpaceID); } Log.WriteLog(LogType.process, LogFile.INFO, "停车记录表已更新"); //更新车位 UpdateAllParkingSpace(false); //Monitor.Monitor.AddNotification("停车数据库已更新,等待流程结束状态清零。"); //while (Monitor.Monitor.mainBlockInfo.processCompleted != 0) //{ // Thread.Sleep(1000); //} Thread.Sleep(500); try { idLicMap.Remove(currentTerm); } catch { } Monitor.Monitor.SetNotification(license + " 数据库已更新,停车流程结束", parkMonitor.model.TextColor.Info); Log.WriteLog(LogType.process, LogFile.INFO, license + " 停车流程结束"); Log.WriteLog(LogType.process, LogFile.INFO, "--------------------------------"); } } } /// /// 预约车辆检测 /// private static void ReservedCarCheck() { if (lockList.Count != terminalInfo.Count) { lockList.Clear(); for (int i = 0; i < terminalInfo.Count; i++) { lockList.Add(false); } } for (int i = 0; i < terminalInfo.Count; i++) { //Console.WriteLine(i); //找到停车终端,且有地感无按钮数据,拍摄号牌 if (terminalInfo[i].terminalStatus == 1 && terminalInfo[i].groundStatus == 1 && terminalInfo[i].btnStatus == 0 && !lockList[i]) { lockList[i] = true; Action reserveAction = new Action(ReservedOper); reserveAction(i); //找到停车终端,且无地感有按钮数据,空闲状态,清除按钮状态 } else if (terminalInfo[i].terminalStatus == 1 && terminalInfo[i].groundStatus == 0 && terminalInfo[i].btnStatus != 0 && terminalInfo[i].cmd == 0) { TerminalStru ts = new TerminalStru { terminalID = terminalInfo[i].terminalID, paymentStatus = (short)-1, btnStatus = 0, cmd = (short)-1, licenseCodeA = -1, licenseCodeB = -1, licenseCodeC = -1, licenseCodeD = -1, receiptNum = -1 }; Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.terminal); Log.WriteLog(LogType.process, LogFile.INFO, "清除按钮状态,写入PLC:" + ts.btnStatus); lockList[i] = false; } //else if (lockList[i] && terminalInfo[i].terminalID == 1) //{ // Log.WriteLog(LogType.process, LogFile.INFO, "停车终端,根据地感号牌获取中......"); //} } } private static void ReservedOper(int index) { Task.Factory.StartNew(() => { string license = ""; int countdown = 5; short registered = 4; while (license == "" && countdown-- > 0) { license = Monitor.Monitor.numMachineLinker.GetLicensePlate(terminalInfo[index].terminalID); } if (license != "") { Monitor.Monitor.SetNotification(terminalInfo[index].terminalID + "号车位收到地感,拍到" + license, parkMonitor.model.TextColor.Log); //map中加入或更新号牌,供完成时写入数据库用 if (idLicMap.ContainsKey(terminalInfo[index].terminalID)) { idLicMap[terminalInfo[index].terminalID] = license; } else { idLicMap.Add(terminalInfo[index].terminalID, license); } if (Monitor.Monitor.webServer.ReservedCarCheck(license)) { registered = 3; Monitor.Monitor.SetNotification("预约车辆入场", parkMonitor.model.TextColor.Info); } #region 通过数据库查询是否预约车,方法待定 //int vehicleState = -1; //string vehicleStateCheckSql = "select vehiclepParkState from vehicle where numberPlate = '" + license + "';"; //MySqlDataReader reader = Monitor.Monitor.localDBOper.Query(vehicleStateCheckSql); //if (reader != null) //{ // try // { // if (reader.Read()) // { // vehicleState = reader.GetInt32("vehiclepParkState"); // } // } // catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "预约检测,查询车辆状态异常"); ; Console.WriteLine(e.Message); }; // try // { // reader.Close(); // reader.Dispose(); // } // catch { } //} //已预约车辆入场 //if (vehicleState == 4) //{ // registered = 3; //} #endregion TerminalStru ts = new TerminalStru { terminalID = terminalInfo[index].terminalID, paymentStatus = (short)-1, btnStatus = registered, cmd = (short)-1, licenseCodeA = -1, licenseCodeB = -1, licenseCodeC = -1, licenseCodeD = -1, receiptNum = -1 }; Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.terminal); Monitor.Monitor.SetNotification("指令写入PLC:" + ts.btnStatus, parkMonitor.model.TextColor.Log); Log.WriteLog(LogType.process, LogFile.INFO, "指令写入PLC:" + ts.btnStatus); Thread.Sleep(1000); lockList[index] = false; } else { Monitor.Monitor.SetNotification("收到地感后,尝试5次未拍到号牌。", parkMonitor.model.TextColor.Log); Log.WriteLog(LogType.process, LogFile.ERROR, "收到地感后,尝试5次未拍到号牌。"); Thread.Sleep(10000); lockList[index] = false; } }); } private static void UpdateLedForBarrier() { for (int i = 0; i < terminalInfo.Count; i++) { // 停车终端,收到地感,尚无停车指令,提示扫描结果 bool condition = terminalInfo[i].terminalStatus == (short)1 && terminalInfo[i].groundStatus == (short)1 && terminalInfo[i].cmd != 1; int scanState = -1; switch (terminalInfo[i].terminalID) { case 1: scanState = Monitor.Monitor.PLCScanInfo.scanStateTerm1; break; case 2: scanState = Monitor.Monitor.PLCScanInfo.scanStateTerm2; break; case 3: scanState = Monitor.Monitor.PLCScanInfo.scanStateTerm3; break; case 4: scanState = Monitor.Monitor.PLCScanInfo.scanStateTerm4; break; case 5: scanState = Monitor.Monitor.PLCScanInfo.scanStateTerm5; break; case 6: scanState = Monitor.Monitor.PLCScanInfo.scanStateTerm6; break; } if (scanState != -1) { LedDisplay(terminalInfo[i].terminalID, scanState, condition); } } } private static void LedDisplay(int termID, int state, bool condition) { if (Monitor.Monitor.allInOneMachine.boardList.Count >= termID) { if (state != Monitor.Monitor.allInOneMachine.boardList[termID - 1].ledScanState) { if (state == 0) { Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateText("欢迎光临智象停车", 60, 0, 5); Monitor.Monitor.allInOneMachine.boardList[termID - 1].ledScanState = state; } else if (condition) { Monitor.Monitor.allInOneMachine.boardList[termID - 1].ledScanState = state; switch (state) { //case 0: // Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateText("欢迎光临", 60, 2); // //Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateArrow(-1, 2, 0); // break; case 1: Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateText("车辆位置正常", 60, 2, 5); //Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateArrow(-1, 2, 0); break; case 2: Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateText("前超界,请向后移动", 30, 2, 5); Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateArrow(1, 30, 2); break; case 3: Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateText("后超界,请向前移动", 30, 2, 5); Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateArrow(0, 30, 2); break; case 4: Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateText("左超界,请向右移动", 30, 2, 5); Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateArrow(3, 30, 2); break; case 5: Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateText("右超界,请向左移动", 30, 2, 5); Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateArrow(2, 30, 2); break; case 6: Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateText("检测中,请稍候", 30, 2, 5); Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateArrow(-1, 2, 0); break; } } } } } /// /// 停车相关操作 /// 0.观测到地感信号,且按钮状态不为3,则启动号牌机获取号牌,并判断是否预约车 /// 1.读取到号牌机启动指令,启动号牌机并根据是否注册用户进行操作 /// 非注册拿到号牌后记录并告知plc /// 注册用户,核对号牌与用户关联信息 /// 2.停车流程结束,写数据库 /// /// private static void ParkProcess() { Task.Factory.StartNew(() => { while (!isClosing) { ParkNumSubProcess(); Thread.Sleep(Monitor.Monitor.plcRefreshInterval * 5); } }); Task.Factory.StartNew(() => { while (!isClosing) { ParkCompleteSubProcess(); Thread.Sleep(Monitor.Monitor.plcRefreshInterval * 5); } }); Task.Factory.StartNew(() => { try { while (!isClosing) { ReservedCarCheck(); Thread.Sleep(Monitor.Monitor.plcRefreshInterval * 5); } } catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "预约异常," + e.Message + ", " + e.StackTrace); } Log.WriteLog(LogType.process, LogFile.ERROR, "预约线程退出"); }); Task.Factory.StartNew(() => { while (!isClosing) { UpdateLedForBarrier(); Thread.Sleep(Monitor.Monitor.plcRefreshInterval * 5); } }); } /// /// 根据凭证号查询停车记录 /// /// /// /// /// /// private static bool FindLocalParkingRecord(int receipt, out int recordID, out int userID, out string license, out string realParkTime) { recordID = 0; userID = 0; license = ""; realParkTime = ""; bool result = false; string parkRecordsSql = "select parkingRecordsID,userID,numberPlate,realParkTime from parkingrecords where receiptNum = " + receipt + ";"; MySqlDataReader reader = Monitor.Monitor.localDBOper.Query(parkRecordsSql); try { if (reader != null && reader.Read()) { object[] receiver = new object[4]; reader.GetValues(receiver); recordID = (int)receiver[0]; userID = (int)receiver[1]; license = (string)receiver[2]; realParkTime = (string)receiver[3]; result = true; } else { Log.WriteLog(LogType.process, LogFile.ERROR, "根据凭证号" + receipt + "查询停车记录失败"); Monitor.Monitor.SetNotification("取车流程, 根据凭证号查询停车记录失败", parkMonitor.model.TextColor.Error); result = false; } //if (reader != null) //{ // reader.Close(); // reader.Dispose(); //} } catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "根据凭证号" + receipt + "查询停车记录失败"); Console.WriteLine(e.Message); result = false; } try { if (reader != null) { reader.Close(); reader.Dispose(); } } catch { } if (result) Log.WriteLog(LogType.process, LogFile.INFO, "根据凭证号查询停车记录成功"); return result; } private static bool FindRemoteParkingRecord(int receipt, out int recordID) { recordID = 0; bool result = false; string remoteParkRecordsSql = "select parkingRecordsID from parkingrecords where receiptNum = " + receipt + ";"; //Log.WriteLog(LogType.database, "find record: \n"); MySqlDataReader reader = Monitor.Monitor.remoteDBOper.Query(remoteParkRecordsSql); //Log.WriteLog(LogType.database, "find record: \n" + remoteParkRecordsSql); try { if (reader != null && reader.Read()) { object[] receiver = new object[1]; reader.GetValues(receiver); recordID = (int)receiver[0]; result = true; } } catch (Exception e) { Console.WriteLine(e.Message); result = false; } try { if (reader != null) { reader.Close(); reader.Dispose(); } } catch (Exception e) { Console.WriteLine(e.Message); result = false; } return result; } /// /// 根据号牌获取本地与远端用户VIP月卡及预约信息 /// /// /// /// /// /// /// private static bool FindVipInfo(string license, ref int orderRecordsID, ref int monthCardType, ref TimeSpan monthCardTimeLength, ref TimeSpan orderTimeLength) { bool result = true; string monthCardTime = ""; //本地VIP信息 string vipInfoSql = "select orderRecordsID,monthCardType,monthCardTime from vehicle where numberPlate = '" + license + "';"; MySqlDataReader reader = null; try { reader = Monitor.Monitor.localDBOper.Query(vipInfoSql); if (reader != null && reader.Read()) { object[] receiver = new object[3]; reader.GetValues(receiver); Console.WriteLine(receiver[2].GetType()); if (!receiver[0].GetType().Equals(typeof(DBNull))) { orderRecordsID = (int)receiver[0]; } if (!receiver[1].GetType().Equals(typeof(DBNull))) { monthCardType = (int)(UInt32)receiver[1]; } if (!receiver[2].GetType().Equals(typeof(DBNull))) { monthCardTime = (string)receiver[2]; } //orderRecordsID = (Int32)receiver[0]; //monthCardType = (Int32)receiver[1]; //monthCardTime = (string)receiver[2]; monthCardTimeLength = DateTime.Parse(monthCardTime) - DateTime.Now; if (monthCardTimeLength.TotalHours <= 0) { monthCardType = 0; } Log.WriteLog(LogType.process, LogFile.INFO, "已获取本地预约与月卡信息"); } } catch (Exception e) { Console.WriteLine(e.Message); result = false; } try { if (reader != null) { reader.Close(); reader.Dispose(); } } catch (Exception e) { Console.WriteLine(e.Message); result = false; } //云端VIP信息 try { reader = Monitor.Monitor.remoteDBOper.Query(vipInfoSql); if (reader != null && reader.Read()) { object[] receiver = new object[3]; reader.GetValues(receiver); int cardType = (int)(UInt32)receiver[1]; string CardTime = (string)receiver[2]; TimeSpan t = DateTime.Parse(CardTime) - DateTime.Now; //云端 if (t.TotalHours > 0 && cardType > monthCardType) { monthCardType = cardType; monthCardTimeLength = t; } Log.WriteLog(LogType.process, LogFile.INFO, "已获取云端预约与月卡信息"); } } catch (Exception e) { Console.WriteLine(e.Message); result = false; } try { if (reader != null) { reader.Close(); reader.Dispose(); } } catch (Exception e) { Console.WriteLine(e.Message); result = false; } //有预约记录,判断记录有效性,有效则获取预约时长 if (orderRecordsID != 0) { //修改orderTimeLength string orderInfoSql = "select bookHour from orderrecords where orderRecordsID = '" + orderRecordsID + "';"; try { reader = Monitor.Monitor.localDBOper.Query(vipInfoSql); if (reader != null && reader.Read()) { orderTimeLength = new TimeSpan(reader.GetInt32("bookHour"), 0, 0); } } catch { } } try { if (reader != null) { reader.Close(); reader.Dispose(); } } catch (Exception e) { Console.WriteLine(e.Message); } return result; } /// /// 预约与停车费用计算 /// /// /// /// /// private static int FeeCalc(PaymentScheme scheme, DateTime parkTime, TimeSpan orderTimeLength) { try { int orderFee = scheme.bookCharge * (int)orderTimeLength.TotalHours; int parkFee = 0; int hours = (int)(DateTime.Now - parkTime).TotalHours; switch (scheme.schemeType) { //按时计费 case 1: if (hours > scheme.firstChargeTime + scheme.freeTime) { if (hours > 24) { parkFee = hours / 24 * scheme.upperBound + Math.Min(scheme.intervalCharge * (hours % 24) / scheme.chargeInterval, scheme.upperBound); } else { parkFee = Math.Min(scheme.firstCharge + scheme.intervalCharge * hours / scheme.chargeInterval, scheme.upperBound); } } else if (hours > scheme.freeTime) { parkFee = scheme.firstCharge; } else { parkFee = 0; } break; //按次计费 case 2: //Console.WriteLine(DateTime.Now.Date.ToString()+","+ parkTime.Date.ToString()); int overnightCount = (DateTime.Now.Date - parkTime.Date).Days; parkFee = scheme.eachCharge + overnightCount * scheme.overnightCharge; break; //按时间段计费 case 3: TimeSpan currentTimeOfDay = DateTime.Now.TimeOfDay; TimeSpan parkTimeOfDay = parkTime.TimeOfDay; TimeSpan startTimeOfDay = DateTime.Parse(scheme.startChargeTime).TimeOfDay; TimeSpan endTimeOfDay = DateTime.Parse(scheme.endChargeTime).TimeOfDay; double countingHoursOfDay = endTimeOfDay.TotalHours - startTimeOfDay.TotalHours; int days = (int)((DateTime.Now - parkTime).TotalHours - currentTimeOfDay.TotalHours + parkTimeOfDay.TotalHours); int previousOffset = (int)(-(Math.Max(0, parkTimeOfDay.TotalHours - startTimeOfDay.TotalHours))); int currentOffset = (int)Math.Min((currentTimeOfDay.TotalHours - startTimeOfDay.TotalHours), countingHoursOfDay); int peakTimeLength = days * (int)countingHoursOfDay + previousOffset + currentOffset; parkFee = peakTimeLength * scheme.chargeStandard + ((int)((DateTime.Now - parkTime).TotalHours) - peakTimeLength) * scheme.intervalCharge; break; } Log.WriteLog(LogType.process, LogFile.INFO, "停车费用" + parkFee); return parkFee; } catch (Exception e) { Console.WriteLine("费用计算异常"); return -1; } } /// /// 取车计费子操作 /// private static void FetchFeeCalcSubProcess() { int receiptNum = 0; int termIndex = -1; bool failed = false; TerminalStru ts = new TerminalStru(); for (int i = 0; i < terminalInfo.Count; i++) { ts = terminalInfo[i]; termIndex = ts.terminalID; receiptNum = ts.receiptNum; //取车状态、凭证号不为空,查询数据库计费 //Console.WriteLine((termIndex != -1) + "," + (termUsedMap.Count >= termIndex) + "," + termUsedMap.TryGetValue(termIndex, out bool valuee) + "," + (!valuee) + "," + (fetchState == 1) + "," + (receiptNum != 0)); bool value = false; if (termIndex != -1 && termCalcMap.Count >= termIndex && termCalcMap.TryGetValue(termIndex, out value) && !value && ts.cmd == 2 && receiptNum != 0) { if (!Monitor.Monitor.globalStatus) { Monitor.Monitor.SetNotification("取车计费系统已暂停,请检查无误后手动开启", parkMonitor.model.TextColor.Warning); ClearTerminal(termIndex, true); Thread.Sleep(5000); return; } //fetchState = Monitor.Monitor.mainBlockInfo.fetchingRunning; Monitor.Monitor.SetNotification(termIndex + "号终端准备计算费用", parkMonitor.model.TextColor.Log); termCalcMap[termIndex] = true; //Console.WriteLine("终端编号" + termIndex); int parkingRecordsID = 0; int remoteParkingRecordsID = 0; int userID = 0; string license = ""; string realParkTime = ""; //1.根据凭证号查询停车记录 if (!FindLocalParkingRecord(receiptNum, out parkingRecordsID, out userID, out license, out realParkTime)) { failed = true; //return; } else { FindRemoteParkingRecord(receiptNum, out remoteParkingRecordsID); } //本地存在号牌,后续操作 //2.根据号牌查询车辆月卡信息与预约记录 int orderRecordsID = 0; int monthCardType = -1; string monthCardTime = ""; TimeSpan monthCardTimeLength = new TimeSpan(0); TimeSpan orderTimeLength = new TimeSpan(0); if (license != "") { bool getVIP = FindVipInfo(license, ref orderRecordsID, ref monthCardType, ref monthCardTimeLength, ref orderTimeLength); //Log.WriteLog(LogType.database, "get vip: " + getVIP); } if (monthCardType == -1) monthCardType = 0; //3.获取停车时刻,根据用户类型计费发送给PLC,暂认为无预约 DateTime parkTime = DateTime.Now, currentTime = DateTime.Now; try { parkTime = DateTime.Parse(realParkTime); } catch { failed = true; } int fee = 32767; if (failed) { monthCardType = 0; } if (PaymentScheme.ins != null) { if (monthCardTimeLength.TotalHours > 0) { fee = 0; } else if (failed) { fee = 0; } else { fee = FeeCalc(PaymentScheme.ins, parkTime, orderTimeLength); } try { if (Monitor.Monitor.PLC != null) { TerminalStru FeeMsg = new TerminalStru(); FeeMsg.terminalID = (short)termIndex; FeeMsg.paymentStatus = (short)-1; FeeMsg.licVerification = (short)-1; FeeMsg.parkingFee = (short)fee; FeeMsg.userType = (short)(monthCardType + 1); Console.WriteLine(FeeMsg); Monitor.Monitor.PLC.WriteToPLC(FeeMsg, PLCDataType.central); Log.WriteLog(LogType.process, LogFile.INFO, "停车费用已发送至PLC"); } } catch { Console.WriteLine("error"); } } Monitor.Monitor.SetNotification("用户类型:" + (monthCardType + 1) + ",费用:" + fee + ",等待凭证号被清除且流程结束后更新车辆状态", parkMonitor.model.TextColor.Log); FetchInfo fetchInfo = new FetchInfo(license, parkingRecordsID, remoteParkingRecordsID, fee, receiptNum); if (!fetchInfoMap.ContainsKey(termIndex)) { fetchInfoMap.Add(termIndex, fetchInfo); fetchCompleteMap.Add(termIndex, true); } else { fetchInfoMap[termIndex] = fetchInfo; fetchCompleteMap[termIndex] = true; } } } } private static void FetchCompleteProcess() { int fetchState = Monitor.Monitor.mainBlockInfo.fetchingRunning; int termID = -1; try { if (fetchState == 1) { //找到当前取车终端 for (int i = 0; i < terminalInfo.Count; i++) { if (terminalInfo[i].terminalID == Monitor.Monitor.mainBlockInfo.terminalID && Monitor.Monitor.mainBlockInfo.terminalID != 0) { termID = terminalInfo[i].terminalID; break; } } if (fetchCompleteMap.ContainsKey(termID) && fetchCompleteMap[termID]) { fetchCompleteMap[termID] = false; Task.Factory.StartNew(() => { //4.等待终端获得收费完成信号且将凭证号清除后,清除收费完成信号并将信息写入数据库 int count = 0; while (!isClosing && termID != -1) { if (Monitor.Monitor.mainBlockInfo.processStopped == 1 || !Monitor.Monitor.globalStatus) { Log.WriteLog(LogType.process, LogFile.INFO, "取车流程中断"); Monitor.Monitor.SetNotification("取车流程中断", parkMonitor.model.TextColor.Warning); ClearTerminal(termID, false); //停车流程确保已清除中控块完成信号 Thread.Sleep(500); ResetCompleteSignal(); break; } if (Monitor.Monitor.mainBlockInfo.processCompleted == 1) { if (Monitor.Monitor.allInOneMachine.boardList.Count >= termID) { Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateText("取车完成,请将车辆驶离车库,智象停车祝您一路顺风。", 60, 2); Monitor.Monitor.allInOneMachine.boardList[termID - 1].UpdateArrow(-1, 2, 0); } UpdateSpecificParkingSpace(); //while (terminalInfo[termIndex].receiptNum != 0) //{ // count++; // if (count == 1) // Monitor.Monitor.SetNotification("等待凭证号清除", parkMonitor.model.TextColor.Log); // if (count > 10000)//避免int型数据溢出 // count = 2; // Thread.Sleep(200); //} int paymentStatus = 0; for (int i = 0; i < terminalInfo.Count; i++) { if (terminalInfo[i].terminalID == Monitor.Monitor.mainBlockInfo.terminalID) { paymentStatus = terminalInfo[i].paymentStatus; break; } } //Log.WriteLog(LogType.process, LogFile.INFO, "检测到凭证号已被清除"); FetchInfo fi = null; ClearTerminal(termID, false); //停车流程确保已清除中控块完成信号 Thread.Sleep(500); ResetCompleteSignal(); UpdateAllParkingSpace(false); if (fetchInfoMap.ContainsKey(termID)) { fi = fetchInfoMap[termID]; } else { Monitor.Monitor.SetNotification("未查询到该取车终端存在计费操作", parkMonitor.model.TextColor.Error); Log.WriteLog(LogType.process, LogFile.ERROR, "终端" + termID + "无计费操作"); return; } //TerminalStru fetchReset = new TerminalStru //{ // terminalID = (short)termIndex, // paymentStatus = (short)0, // licVerification = (short)0, // parkingFee = (short)32767, // userType = (short)0 //}; //Monitor.Monitor.PLC.WriteToPLC(fetchReset, PLCDataType.central); //更新停车记录与车辆状态 string updateParkingRecordsSql = "update parkingrecords set parkingRecordsState = 6,realGetTime = '" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "',parkingPrice = " + fi.fee + ",paymentStatus = " + paymentStatus + " where receiptNum = '" + fi.receiptNum + "';"; List list = new List(); list.Add(updateParkingRecordsSql); lock (Monitor.Monitor.localDBOper) { Monitor.Monitor.localDBOper.UpdateTransaction(list); UpdateVehicle(fi.license, 0, fi.parkingRecordsID, false, false, 0); } lock (Monitor.Monitor.remoteDBOper) { //Log.WriteLog(LogType.database, "update fetch record: " + updateParkingRecordsSql); Monitor.Monitor.remoteDBOper.UpdateTransaction(list); UpdateVehicle(fi.license, 0, fi.remoteParkingRecordsID, false, true, 0); } Monitor.Monitor.SetNotification(fi.license + " 取车流程结束", parkMonitor.model.TextColor.Info); Log.WriteLog(LogType.process, LogFile.INFO, fi.license + " 取车流程结束"); Log.WriteLog(LogType.process, LogFile.INFO, "--------------------------------"); break; } Thread.Sleep(200); } termCalcMap[termID] = false; fetchInfoMap.Remove(termID); fetchCompleteMap.Remove(termID); }); } } } catch (Exception ex) { Log.WriteLog(LogType.process, LogFile.ERROR, "取车完成流程异常," + ex.StackTrace); } } /// /// 取车相关操作 /// /// private static void FetchProcess() { Task.Factory.StartNew(() => { while (!isClosing) { FetchFeeCalcSubProcess(); Thread.Sleep(Monitor.Monitor.plcRefreshInterval); } }); Task.Factory.StartNew(() => { while (!isClosing) { FetchCompleteProcess(); Thread.Sleep(Monitor.Monitor.plcRefreshInterval); } }); } public static void Start() { for (int i = 0; i < Monitor.Monitor.plcTerminalCount; i++) { lockList.Add(false); } ResetCompleteSignal(); ParkProcess(); FetchProcess(); //定时更新云端车位,5min Task.Factory.StartNew(() => { while (!isClosing) { UpdateAllParkingSpace(true); Thread.Sleep(300000); } }); } public static void Stop() { isClosing = true; } public class FetchInfo { public string license; public int parkingRecordsID; public int remoteParkingRecordsID; public int fee; public int receiptNum; public FetchInfo(string license, int parkingRecordsID, int remoteParkingRecordsID, int fee, int receiptNum) { this.license = license; this.parkingRecordsID = parkingRecordsID; this.remoteParkingRecordsID = remoteParkingRecordsID; this.fee = fee; this.receiptNum = receiptNum; } } } }