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 termUsedMap = new Dictionary(); private static Dictionary fetchMap = 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 + ";"; 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; } /// /// 更新所有车位信息 /// private static void UpdateAllParkingSpace() { string findParkingSpace = "select parkingSpaceID from parkingspace;"; HashSet recordsIDSet = new HashSet(); lock (Monitor.Monitor.localDBOper) { //object[] result = Monitor.Monitor.localDBOper.Query(findParkingSpace); //if(result!=null && result.Length > 0) //{ // for (int i = 0; i < result.Length; i++) // { // recordsIDSet.Add((int)result[i]); // } //} MySqlDataReader reader = Monitor.Monitor.localDBOper.Query(findParkingSpace); if (reader != null) { try { while (reader.Read()) { if (reader.HasRows) { recordsIDSet.Add(reader.GetInt32("parkingSpaceID")); } } } catch { } 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 { 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); } } try { lock (Monitor.Monitor.localDBOper) { Monitor.Monitor.localDBOper.UpdateTransaction(updateSpaceList); Monitor.Monitor.localDBOper.Insert(insertSpaceList); } } 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); if (!remote) { Monitor.Monitor.localDBOper.Insert(list); } else { Monitor.Monitor.remoteDBOper.Insert(list); } } try { reader.Close(); reader.Dispose(); } catch { } } } } /// /// 流程结束清除终端相关信息 /// /// private static void ClearTerminal(int id) { TerminalStru tsFromCentral = new TerminalStru { terminalID = (short)id, parkingFee = (short)32767, }; TerminalStru tsFromTerminal = new TerminalStru { terminalID = (short)id, btnStatus = (short)0, }; Monitor.Monitor.PLC.WriteToPLC(tsFromCentral, PLCDataType.central); Monitor.Monitor.PLC.WriteToPLC(tsFromTerminal, PLCDataType.terminal); } /// /// 验证会员信息 /// /// /// /// /// 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("注册用户,号牌验证成功"); } else { ts.licVerification = 2;//验证失败 Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central); status = 2; Log.WriteLog(LogType.process, LogFile.WARNING, "号牌验证失败"); Monitor.Monitor.SetNotification("注册用户,号牌验证失败"); } 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 { if (reader.Read()) { 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(terminalInfo[i].terminalID)) { license = Monitor.Monitor.numMachineLinker.GetLicensePlate(terminalInfo[i].terminalID); Monitor.Monitor.SetNotification("启动" + terminalInfo[i].terminalID + "号号牌机,号牌:" + license); } else { idLicMap.TryGetValue(terminalInfo[i].terminalID, out license); } //未获得号牌,告知PLC终止,告诉终端提示用户重新操作 if (license == "") { MainBlockStru mb = new MainBlockStru { centralHearbeat = (short)-1, bookParkCmd = -1, bookFetchCmd = -1, licenseReceived = (short)2 }; Monitor.Monitor.PLC.WriteToPLC(mb, PLCDataType.central); TerminalStru ts = new TerminalStru { terminalID = (short)terminalInfo[i].terminalID, paymentStatus = -1, parkingFee = -1, userType = -1, licVerification = (short)2 }; Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central); Log.WriteLog(LogType.process, LogFile.ERROR, "未获得号牌"); } else { //记录或更新当前号牌 lock (idLicMap) { try { if (idLicMap.ContainsKey(terminalInfo[i].terminalID)) { if (!idLicMap[terminalInfo[i].terminalID].Equals(license)) idLicMap[terminalInfo[i].terminalID] = license; } else { idLicMap.Add(terminalInfo[i].terminalID, license); } } catch(Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "号牌" + license + "记录号牌异常\n"+e.StackTrace); } } Log.WriteLog(LogType.process, LogFile.ERROR, "号牌" + license + "已记录"); TerminalStru ts = new TerminalStru { terminalID = (short)terminalInfo[i].terminalID, paymentStatus = -1, parkingFee = -1, userType = -1 }; //注册用户 if (term.btnStatus == (short)2) { int userID = term.licenseCodeA; string userLicense = GetLicenseFromTerm(term); //与云端数据比对 ValidateUserInfo(ts, userID, userLicense, out numReceivedStatus); if (numReceivedStatus == 2) { idLicMap.Remove(terminalInfo[i].terminalID); } } //非注册用户 else if (term.btnStatus == (short)1) { numReceivedStatus = 1; ts.licVerification = 1; Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central); } //无论是否注册,皆告知PLC,已获取号牌或比对异常、终止流程 MainBlockStru mb = new MainBlockStru { centralHearbeat = -1, bookFetchCmd = -1, bookParkCmd = -1, licenseReceived = (short)numReceivedStatus }; Monitor.Monitor.PLC.WriteToPLC(mb, PLCDataType.central); //号牌获取结果被清零才跳出 Monitor.Monitor.SetNotification("已写入号牌获取结果,等待号牌机启动指令清零"); } int countdown = 5; while (countdown-- > 0) { if (term.numMachineLaunch == 0) { Monitor.Monitor.SetNotification("号牌机启动指令已被清零"); break; } else Thread.Sleep(1000); } } } } } #endregion //private static void ParkNumSubProcess() //{ //} /// /// 停车流程,收到PLC停车完成信号后操作过程 /// private static void ParkCompleteSubProcess() { 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; string license; //等待完成信号 while (Monitor.Monitor.mainBlockInfo.processCompleted != 1) { Thread.Sleep(200); if (Monitor.Monitor.mainBlockInfo.processStopped == 1) return; Thread.Sleep(200); } //找到终端号,判断是否注册用户 //拿到号牌 if (/*terminalInfo[i].terminalID == currentTerm && */idLicMap.TryGetValue(currentTerm, out license) && license != "") { term = terminalInfo[currentTerm - 1]; Thread.Sleep(1500); //找到停车位置 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); } catch { } Monitor.Monitor.SetNotification("无车位或凭证号"); 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); Monitor.Monitor.localDBOper.Insert(list); Monitor.Monitor.remoteDBOper.Insert(list); Log.WriteLog(LogType.process, LogFile.INFO, "停车记录已插入," + license + "停在" + parkingSpaceID + ",凭证号:" + term.receiptNum); Monitor.Monitor.SetNotification("停车记录已插入"); ////注册用户记录插入云端 //if (term.btnStatus == 0) //{ //Monitor.Monitor.remoteDBOper.Insert(list); //} //查询记录ID号 string findRecordSql = "select parkingRecordsID from parkingrecords where receiptNum = " + term.receiptNum + ";"; int parkingRecordsID = 0; int remoteParkingRecordsID = 0; 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(); //Monitor.Monitor.AddNotification("停车数据库已更新,等待流程结束状态清零。"); //while (Monitor.Monitor.mainBlockInfo.processCompleted != 0) //{ // Thread.Sleep(1000); //} //中控清除车牌、凭证号、号牌验证等信息 ClearTerminal(term.terminalID); try { idLicMap.Remove(currentTerm); } catch { } Monitor.Monitor.SetNotification(license + " 数据库已更新,停车流程结束"); } } } /// /// 预约车辆检测 /// 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 = Monitor.Monitor.numMachineLinker.GetLicensePlate(terminalInfo[index].terminalID); } Monitor.Monitor.SetNotification(terminalInfo[index].terminalID + "号车位收到地感,拍到" + license); 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; } #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); 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, "根据凭证号查询停车记录失败"); Monitor.Monitor.SetNotification("取车流程, 根据凭证号查询停车记录失败"); result = false; } //if (reader != null) //{ // reader.Close(); // reader.Dispose(); //} } catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "根据凭证号查询停车记录失败"); Console.WriteLine(e.Message); result = false; } try { if (reader != null) { reader.Close(); reader.Dispose(); } } catch { } 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 } 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)); if (termIndex != -1 && termUsedMap.Count >= termIndex && termUsedMap.TryGetValue(termIndex, out bool value) && !value && ts.cmd == 2 && receiptNum != 0) { //fetchState = Monitor.Monitor.mainBlockInfo.fetchingRunning; Monitor.Monitor.SetNotification(termIndex + "号终端准备计算费用"); termUsedMap[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.Parse(realParkTime); DateTime currentTime = DateTime.Now; int fee = 32767; if (failed) { monthCardType = -2; } 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 + ",等待凭证号被清除且流程结束后更新车辆状态"); FetchInfo fetchInfo = new FetchInfo(license, parkingRecordsID, remoteParkingRecordsID, fee, receiptNum); if (!fetchMap.ContainsKey(termIndex)) fetchMap.Add(termIndex, fetchInfo); else fetchMap[termIndex] = fetchInfo; } } } private static void FetchCompleteProcess() { int fetchState = Monitor.Monitor.mainBlockInfo.fetchingRunning; int termIndex = -1; TerminalStru ts = new TerminalStru(); if (fetchState == 1) { //找到当前取车终端 for (int i = 0; i < terminalInfo.Count; i++) { if (terminalInfo[i].terminalID == Monitor.Monitor.mainBlockInfo.terminalID) { ts = terminalInfo[i]; termIndex = ts.terminalID; break; } } //4.等待终端获得收费完成信号且将凭证号清除后,清除收费完成信号并将信息写入数据库 int count = 0; while (!isClosing && termIndex != -1) { if (Monitor.Monitor.mainBlockInfo.processCompleted == 1) { while (terminalInfo[termIndex - 1].receiptNum != 0) { count++; if (count == 1) Monitor.Monitor.SetNotification("等待凭证号清除"); 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; if (fetchMap.ContainsKey(termIndex)) { fi = fetchMap[termIndex]; } else { Monitor.Monitor.SetNotification("未查询到该取车终端存在计费操作"); 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); ClearTerminal(termIndex); //更新停车记录与车辆状态 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 + " 取车流程结束"); break; } Thread.Sleep(1000); } termUsedMap[termIndex] = false; fetchMap.Remove(termIndex); } } /// /// 取车相关操作 /// /// 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(); } 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; } } } }