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与是否已计费标记映射 /// 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; public void FeeCal() { } public void GetTerminalState() { } private object SearchPaymentScheme() { return null; } private void UpdateParkingRecords(int Object) { } /// /// 从终端结构体中获得车牌号 /// /// /// 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 { reader = Monitor.Monitor.remoteDBOper.Query(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 { list.Add(updateRemoteVehicleState); Monitor.Monitor.remoteDBOper.UpdateTransaction(list); } } 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) { TerminalStru tsFromCentral = new TerminalStru { terminalID = (short)id, parkingFee = (short)32767, receiptNum = (short)-1 }; TerminalStru tsFromTerminal = new TerminalStru { terminalID = (short)id, btnStatus = (short)0, receiptNum = (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; 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) { 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 = 2;//验证失败 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 { ts.licVerification = 1;//网络异常,跳过验证 Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central); status = 1; Log.WriteLog(LogType.process, LogFile.ERROR, "网络异常,无法验证号牌"); } try { readerTest.Close(); readerTest.Dispose(); } catch { } } } /// /// 查询停车记录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) { int numReceivedStatus = 0;//1获得,2终止 TerminalStru term = terminalInfo[i]; if (term.terminalStatus == (short)1) { string license = ""; //判断之前是否已拍摄号牌 if (!idLicMap.ContainsKey(term.terminalID)) { license = "桂K88888";//Monitor.Monitor.numMachineLinker.GetLicensePlate(term.terminalID); Monitor.Monitor.SetNotification("启动" + term.terminalID + "号号牌机,号牌:" + license, parkMonitor.model.TextColor.Info); } else { idLicMap.TryGetValue(term.terminalID, out license); } //无论号牌有无,皆记录或更新当前号牌,若无则填入默认号牌 lock (idLicMap) { string currentLic = license == "" ? Monitor.Monitor.defaultLic : 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 (license == "") { 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)2 }; Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central); 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) { 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); } //无论是否注册,皆告知PLC,已获取号牌或比对异常、终止流程 MainBlockStru mbst = new MainBlockStru { centralHearbeat = -1, bookFetchCmd = -1, bookParkCmd = -1, processCompleted = (short)-1, licenseReceived = (short)numReceivedStatus }; Monitor.Monitor.PLC.WriteToPLC(mbst, PLCDataType.central); //号牌获取结果被清零才跳出 Monitor.Monitor.SetNotification("已写入号牌获取结果,等待号牌机启动指令清零", 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); } } } } } #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; //等待完成信号 if (Monitor.Monitor.mainBlockInfo.parkingRunning != 1 || Monitor.Monitor.mainBlockInfo.processCompleted != 1) { if (Monitor.Monitor.mainBlockInfo.processStopped == 1) { Log.WriteLog(LogType.process,LogFile.ERROR,"停车流程中断"); Thread.Sleep(500); ClearTerminal(term.terminalID); ResetCompleteSignal(); } return; } //找到终端号,判断是否注册用户 //拿到号牌 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(1000); parkingSpaceID = Monitor.Monitor.mainBlockInfo.currentParkingSpaceID; //找到停车位置 //for (int s = 0; s < Monitor.Monitor.parkingSpaceInfo.Count; s++) //{ // //Console.WriteLine(Monitor.Monitor.parkingSpaceInfo[s].receiptNum + "," + term.receiptNum); // if (Monitor.Monitor.parkingSpaceInfo[s].receiptNum == term.receiptNum) // { // parkingSpaceID = Monitor.Monitor.parkingSpaceInfo[s].parkingSpace; // break; // } //} //无车位信息则跳出当前循环 if (parkingSpaceID == 0 || term.receiptNum == 0) { try { idLicMap.Remove(currentTerm); ClearTerminal(term.terminalID); } catch { } Monitor.Monitor.SetNotification("无车位或凭证号", parkMonitor.model.TextColor.Warning); return; } 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") + "','" + term.receiptNum + "',NULL);"; } else { parkingRecordsSql = "INSERT INTO parkingrecords (userID, numberPlate,parkingSpaceID,garageID,parkingRecordsState,realParkTime,receiptNum,parkingPrice)" + "values ('" + 1 + "','" + license + "','" + parkingSpaceID + "','" + Monitor.Monitor.garageID + "',3,'" + DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss") + "','" + term.receiptNum + "',NULL);"; } List list = new List(); list.Add(parkingRecordsSql); int parkingRecordsID = 0; int remoteParkingRecordsID = 0; Monitor.Monitor.localDBOper.Insert(list, out parkingRecordsID); Monitor.Monitor.remoteDBOper.Insert(list, out remoteParkingRecordsID); Log.WriteLog(LogType.process, LogFile.INFO, "停车记录已插入," + license + "停在" + parkingSpaceID + ",凭证号:" + term.receiptNum); Monitor.Monitor.SetNotification("停车记录已插入", parkMonitor.model.TextColor.Info); //查询记录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); //} //中控清除车牌、凭证号、号牌验证等信息 ClearTerminal(term.terminalID); //停车流程确保已清除中控块完成信号 Thread.Sleep(500); ResetCompleteSignal(); try { idLicMap.Remove(currentTerm); } catch { } Monitor.Monitor.SetNotification(license + " 数据库已更新,停车流程结束", parkMonitor.model.TextColor.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); } } } private static void ReservedOper(int index) { Task.Factory.StartNew(() => { string license = ""; int countdown = 2; short registered = 4; while (license == "" && countdown-- > 0) { license = "桂K88888";// Monitor.Monitor.numMachineLinker.GetLicensePlate(terminalInfo[index].terminalID); } Monitor.Monitor.SetNotification(terminalInfo[index].terminalID + "号车位收到地感,拍到" + license, parkMonitor.model.TextColor.Log); if (license != "") { //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); Thread.Sleep(1000); } else { Thread.Sleep(200); } lockList[index] = false; }); } /// /// 停车相关操作 /// 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(() => { while (!isClosing) { ReservedCarCheck(); 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 + ";"; MySqlDataReader reader = Monitor.Monitor.remoteDBOper.Query(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) { //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 != "") { FindVipInfo(license, ref orderRecordsID, ref monthCardType, ref monthCardTimeLength, ref orderTimeLength); } 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 termIndex = -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) { termIndex = i; break; } } if (fetchCompleteMap.ContainsKey(terminalInfo[termIndex].terminalID) && fetchCompleteMap[terminalInfo[termIndex].terminalID]) { fetchCompleteMap[terminalInfo[termIndex].terminalID] = false; Task.Factory.StartNew(() => { //4.等待终端获得收费完成信号且将凭证号清除后,清除收费完成信号并将信息写入数据库 int count = 0; while (!isClosing && termIndex != -1) { if (Monitor.Monitor.mainBlockInfo.processStopped == 1) { Log.WriteLog(LogType.process, LogFile.INFO, "检测到流程中断"); ClearTerminal(terminalInfo[termIndex].terminalID); //停车流程确保已清除中控块完成信号 Thread.Sleep(500); ResetCompleteSignal(); break; } if (Monitor.Monitor.mainBlockInfo.processCompleted == 1) { 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; UpdateAllParkingSpace(false); ClearTerminal(terminalInfo[termIndex].terminalID); //停车流程确保已清除中控块完成信号 Thread.Sleep(500); ResetCompleteSignal(); if (fetchInfoMap.ContainsKey(terminalInfo[termIndex].terminalID)) { fi = fetchInfoMap[terminalInfo[termIndex].terminalID]; } else { Monitor.Monitor.SetNotification("未查询到该取车终端存在计费操作", parkMonitor.model.TextColor.Error); Log.WriteLog(LogType.process, LogFile.ERROR, "终端" + terminalInfo[termIndex].terminalID + "无计费操作"); 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) { Monitor.Monitor.remoteDBOper.UpdateTransaction(list); UpdateVehicle(fi.license, 0, fi.remoteParkingRecordsID, false, true, 0); } Monitor.Monitor.SetNotification(fi.license + " 取车流程结束", parkMonitor.model.TextColor.Info); break; } Thread.Sleep(200); } termCalcMap[terminalInfo[termIndex].terminalID] = false; fetchInfoMap.Remove(terminalInfo[termIndex].terminalID); fetchCompleteMap.Remove(terminalInfo[termIndex].terminalID); }); } } } 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); } 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; } } } }