Terminal.cs 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316
  1. using Terminal;
  2. using db;
  3. using System.Collections.Generic;
  4. using System.Threading.Tasks;
  5. using PLCS7;
  6. using System;
  7. using System.Text;
  8. using MySql.Data.MySqlClient;
  9. using System.Threading;
  10. using BroadcastModule;
  11. using parkMonitor.LOG;
  12. using centralController.model;
  13. namespace Terminal
  14. {
  15. public class Terminal
  16. {
  17. public static List<TerminalStru> terminalInfo = new List<PLCS7.TerminalStru>();
  18. /// <summary>
  19. /// 记录地面停车位id与获取号牌映射
  20. /// </summary>
  21. private static Dictionary<int, string> idLicMap = new Dictionary<int, string>();
  22. /// <summary>
  23. /// 取车地面位id与是否已计费标记映射
  24. /// </summary>
  25. public static Dictionary<int, bool> termCalcMap = new Dictionary<int, bool>();
  26. /// <summary>
  27. /// 终端ID与取车完成标志映射
  28. /// </summary>
  29. public static Dictionary<int, bool> fetchCompleteMap = new Dictionary<int, bool>();
  30. /// <summary>
  31. /// 终端ID与取车信息映射
  32. /// </summary>
  33. private static Dictionary<int, FetchInfo> fetchInfoMap = new Dictionary<int, FetchInfo>();
  34. private static List<bool> lockList = new List<bool>();
  35. public static bool isClosing = false;
  36. public void FeeCal()
  37. {
  38. }
  39. public void GetTerminalState()
  40. {
  41. }
  42. private object SearchPaymentScheme()
  43. {
  44. return null;
  45. }
  46. private void UpdateParkingRecords(int Object)
  47. {
  48. }
  49. /// <summary>
  50. /// 从终端结构体中获得车牌号
  51. /// </summary>
  52. /// <param name="ts"></param>
  53. /// <returns></returns>
  54. private static string GetLicenseFromTerm(TerminalStru ts)
  55. {
  56. string header = Encoding.ASCII.GetString(BitConverter.GetBytes(ts.licenseCodeB));
  57. string identityA = Encoding.ASCII.GetString(BitConverter.GetBytes(ts.licenseCodeC));
  58. byte[] bytes = BitConverter.GetBytes(ts.licenseCodeD);
  59. List<byte> newBytes = new List<byte>();
  60. for (int i = 0; i < bytes.Length; i++)
  61. {
  62. if (bytes[i] != 0x00) { newBytes.Add(bytes[i]); }
  63. }
  64. string identityB = Encoding.ASCII.GetString(newBytes.ToArray());
  65. Log.WriteLog(LogType.process, LogFile.INFO, "已从终端" + ts.terminalID + "获得号牌:" + header + identityA + identityB);
  66. //根据省份对应的两位数字查找汉字
  67. string province = header.Substring(0, 2);
  68. string provinceIndex = header.Substring(2);
  69. string provinceQuerySql = "select NumberPlateHeader from numberplatemapping where mappedString = " + province + ";";
  70. lock (Monitor.Monitor.localDBOper)
  71. {
  72. //object[] result = Monitor.Monitor.localDBOper.Query(provinceQuerySql);
  73. MySqlDataReader reader = Monitor.Monitor.localDBOper.Query(provinceQuerySql);
  74. try
  75. {
  76. if (reader != null && reader.Read() && reader.HasRows)
  77. {
  78. province = reader.GetString("NumberPlateHeader");
  79. //Console.WriteLine(province);
  80. }
  81. }
  82. catch { }
  83. try
  84. {
  85. //if (result!=null && result.Length > 0) { province = (string)result[0]; }
  86. if (reader != null)
  87. {
  88. reader.Close();
  89. reader.Dispose();
  90. }
  91. }
  92. catch { }
  93. }
  94. return province + provinceIndex + identityA + identityB;
  95. }
  96. /// <summary>
  97. /// 更新所有车位信息
  98. /// </summary>
  99. private static void UpdateAllParkingSpace()
  100. {
  101. string findParkingSpace = "select parkingSpaceID from parkingspace;";
  102. HashSet<int> recordsIDSet = new HashSet<int>();
  103. lock (Monitor.Monitor.localDBOper)
  104. {
  105. //object[] result = Monitor.Monitor.localDBOper.Query(findParkingSpace);
  106. //if(result!=null && result.Length > 0)
  107. //{
  108. // for (int i = 0; i < result.Length; i++)
  109. // {
  110. // recordsIDSet.Add((int)result[i]);
  111. // }
  112. //}
  113. MySqlDataReader reader = Monitor.Monitor.localDBOper.Query(findParkingSpace);
  114. if (reader != null)
  115. {
  116. try
  117. {
  118. while (reader.Read())
  119. {
  120. if (reader.HasRows)
  121. {
  122. recordsIDSet.Add(reader.GetInt32("parkingSpaceID"));
  123. }
  124. }
  125. }
  126. catch { Log.WriteLog(LogType.process, LogFile.INFO, "数据库车位查询异常"); }
  127. try
  128. {
  129. reader.Close();
  130. reader.Dispose();
  131. }
  132. catch { }
  133. }
  134. }
  135. List<string> updateSpaceList = new List<string>();
  136. List<string> insertSpaceList = new List<string>();
  137. string updateParkingSpace = "";
  138. string insertParkingSpace = "";
  139. for (int i = 0; i < Monitor.Monitor.parkingSpaceInfo.Count; i++)
  140. {
  141. if (recordsIDSet.Contains(Monitor.Monitor.parkingSpaceInfo[i].parkingSpace))
  142. {
  143. updateParkingSpace = "update parkingspace set parkingSpaceX = " + Monitor.Monitor.parkingSpaceInfo[i].coordX +
  144. ",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 + ");";
  145. updateSpaceList.Add(updateParkingSpace);
  146. }
  147. else
  148. {
  149. insertParkingSpace = "insert into parkingspace (parkingSpaceID,parkingSpaceX,parkingSpaceY,parkingSpaceZ,parkingSpaceState) values (" + Monitor.Monitor.parkingSpaceInfo[i].parkingSpace + "," + Monitor.Monitor.parkingSpaceInfo[i].coordX +
  150. "," + Monitor.Monitor.parkingSpaceInfo[i].coordY + "," + Monitor.Monitor.parkingSpaceInfo[i].floorNo + "," + Monitor.Monitor.parkingSpaceInfo[i].spaceStatus + ");";
  151. insertSpaceList.Add(insertParkingSpace);
  152. }
  153. }
  154. try
  155. {
  156. lock (Monitor.Monitor.localDBOper)
  157. {
  158. Monitor.Monitor.localDBOper.UpdateTransaction(updateSpaceList);
  159. Monitor.Monitor.localDBOper.Insert(insertSpaceList);
  160. }
  161. }
  162. catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "更新本地所有车位异常"); Console.WriteLine("更新本地所有车位异常" + e.Message); }
  163. }
  164. /// <summary>
  165. /// 更新车辆状态
  166. /// </summary>
  167. /// <param name="lic"></param>
  168. /// <param name="state"></param>
  169. private static void UpdateVehicle(string lic, int state, int parkingRecordsID, bool park, bool remote, int parkingSpaceID)
  170. {
  171. if (lic != "")
  172. {
  173. MySqlDataReader reader;
  174. //查询车辆是否在车辆表中
  175. string checkVehicleState = "select * from vehicle where numberPlate = '" + lic + "';";
  176. if (!remote)
  177. {
  178. reader = Monitor.Monitor.localDBOper.Query(checkVehicleState);
  179. }
  180. else
  181. {
  182. reader = Monitor.Monitor.remoteDBOper.Query(checkVehicleState);
  183. }
  184. if (reader != null)
  185. {
  186. if (reader.Read() && reader.HasRows)
  187. {
  188. //更新车辆状态
  189. string updateVehicleState = "";
  190. string updateRemoteVehicleState = "";
  191. if (park)
  192. {
  193. if (parkingRecordsID > 0)
  194. {
  195. if (parkingSpaceID == 0)
  196. {
  197. updateVehicleState = "update vehicle set vehiclepParkState = " + state + " ,parkingRecordsID = " + parkingRecordsID + " where numberPlate = '" + lic + "';";
  198. updateRemoteVehicleState = "update vehicle set vehiclepParkState = " + state + " ,parkingRecordsID = " + parkingRecordsID + ",garageID = " + Monitor.Monitor.garageID + " where numberPlate = '" + lic + "';";
  199. }
  200. else
  201. {
  202. updateVehicleState = "update vehicle set vehiclepParkState = " + state + " ,parkingRecordsID = " + parkingRecordsID + ",parkingSpaceID = " + parkingSpaceID + " where numberPlate = '" + lic + "';";
  203. updateRemoteVehicleState = "update vehicle set vehiclepParkState = " + state + " ,parkingRecordsID = " + parkingRecordsID + ",parkingSpaceID = " + parkingSpaceID + ",garageID = " + Monitor.Monitor.garageID + " where numberPlate = '" + lic + "';";
  204. }
  205. }
  206. else
  207. {
  208. updateVehicleState = "update vehicle set vehiclepParkState = " + state + " where numberPlate = '" + lic + "';";
  209. updateRemoteVehicleState = updateVehicleState;
  210. }
  211. }
  212. else
  213. {
  214. updateVehicleState = "update vehicle set vehiclepParkState = " + state + " where numberPlate = '" + lic + "';";
  215. updateRemoteVehicleState = updateVehicleState;
  216. }
  217. List<string> list = new List<string>();
  218. if (!remote)
  219. {
  220. list.Add(updateVehicleState);
  221. Monitor.Monitor.localDBOper.UpdateTransaction(list);
  222. }
  223. else
  224. {
  225. list.Add(updateRemoteVehicleState);
  226. Monitor.Monitor.remoteDBOper.UpdateTransaction(list);
  227. }
  228. }
  229. else
  230. {
  231. //插入车辆
  232. string insertVehicleWithState = "";
  233. if (park)
  234. {
  235. if (parkingRecordsID > 0)
  236. insertVehicleWithState = "insert into vehicle (numberPlate,vehicleTypeID,vehiclepParkState,parkingRecordsID) values " +
  237. "('" + lic + "',NULL,'" + state + "'," + parkingRecordsID + ");";
  238. else
  239. insertVehicleWithState = "insert into vehicle (numberPlate,vehicleTypeID,vehiclepParkState) values " +
  240. "('" + lic + "',NULL,'" + state + "');";
  241. }
  242. else
  243. {
  244. Log.WriteLog(LogType.process, LogFile.ERROR, "取车无法获得车辆信息");
  245. Console.WriteLine("明显异常,取车发现无车辆");
  246. try
  247. {
  248. reader.Close();
  249. reader.Dispose();
  250. }
  251. catch { }
  252. return;
  253. }
  254. List<string> list = new List<string>();
  255. list.Add(insertVehicleWithState);
  256. if (!remote)
  257. {
  258. Monitor.Monitor.localDBOper.Insert(list);
  259. }
  260. else
  261. {
  262. Monitor.Monitor.remoteDBOper.Insert(list);
  263. }
  264. }
  265. try
  266. {
  267. reader.Close();
  268. reader.Dispose();
  269. }
  270. catch { }
  271. }
  272. }
  273. }
  274. /// <summary>
  275. /// 流程结束清除终端相关信息
  276. /// </summary>
  277. /// <param name="id"></param>
  278. private static void ClearTerminal(int id)
  279. {
  280. TerminalStru tsFromCentral = new TerminalStru
  281. {
  282. terminalID = (short)id,
  283. parkingFee = (short)32767,
  284. };
  285. TerminalStru tsFromTerminal = new TerminalStru
  286. {
  287. terminalID = (short)id,
  288. btnStatus = (short)0,
  289. };
  290. Monitor.Monitor.PLC.WriteToPLC(tsFromCentral, PLCDataType.central);
  291. Monitor.Monitor.PLC.WriteToPLC(tsFromTerminal, PLCDataType.terminal);
  292. }
  293. /// <summary>
  294. /// 验证会员信息
  295. /// </summary>
  296. /// <param name="ts"></param>
  297. /// <param name="userID"></param>
  298. /// <param name="license"></param>
  299. /// <param name="status"></param>
  300. private static void ValidateUserInfo(TerminalStru ts, int userID, string license, out int status)
  301. {
  302. status = 0;
  303. //与云端数据比对
  304. string checkNetSql = "select * from user where userID = 1;";
  305. MySqlDataReader readerTest = Monitor.Monitor.remoteDBOper.Query(checkNetSql);
  306. if (readerTest != null)
  307. {
  308. if (readerTest.Read() && readerTest.HasRows)
  309. {
  310. string userInfoCheckSql = "select * from usercarrelation where userID = '" + userID + "'and numberPlate = '" + license + "';";
  311. MySqlDataReader reader = Monitor.Monitor.remoteDBOper.Query(userInfoCheckSql);
  312. if (reader != null && reader.Read() && reader.HasRows && userID != 0 && license != "")
  313. {
  314. ts.licVerification = 1;//验证成功
  315. Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central);
  316. status = 1;
  317. Log.WriteLog(LogType.process, LogFile.INFO, "号牌验证成功");
  318. Monitor.Monitor.SetNotification("注册用户,号牌验证成功", parkMonitor.model.TextColor.Info);
  319. }
  320. else
  321. {
  322. ts.licVerification = 2;//验证失败
  323. Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central);
  324. status = 2;
  325. Log.WriteLog(LogType.process, LogFile.WARNING, "号牌验证失败");
  326. Monitor.Monitor.SetNotification("注册用户,号牌验证失败", parkMonitor.model.TextColor.Error);
  327. }
  328. try
  329. {
  330. reader.Close();
  331. reader.Dispose();
  332. }
  333. catch { }
  334. }
  335. else
  336. {
  337. ts.licVerification = 1;//网络异常,跳过验证
  338. Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central);
  339. status = 1;
  340. Log.WriteLog(LogType.process, LogFile.ERROR, "网络异常,无法验证号牌");
  341. }
  342. try
  343. {
  344. readerTest.Close();
  345. readerTest.Dispose();
  346. }
  347. catch { }
  348. }
  349. }
  350. /// <summary>
  351. /// 查询停车记录id
  352. /// </summary>
  353. /// <param name="querySql"></param>
  354. /// <param name="recordsID"></param>
  355. /// <param name="remote"></param>
  356. private static void QueryParkingRecordsID(string querySql, out int recordsID, bool remote)
  357. {
  358. recordsID = 0;
  359. MySqlDataReader reader = null;
  360. if (!remote)
  361. {
  362. reader = Monitor.Monitor.localDBOper.Query(querySql);
  363. }
  364. else
  365. {
  366. reader = Monitor.Monitor.remoteDBOper.Query(querySql);
  367. }
  368. if (reader != null)
  369. {
  370. try
  371. {
  372. while (reader.Read())
  373. {
  374. if (reader.HasRows)
  375. recordsID = reader.GetInt32("parkingRecordsID");
  376. }
  377. }
  378. catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "查询停车记录id失败"); Console.WriteLine(e.Message); };
  379. try
  380. {
  381. reader.Close();
  382. reader.Dispose();
  383. }
  384. catch { }
  385. }
  386. }
  387. //private static void BookedCarProcess()
  388. //{
  389. // for (int i = 0; i < terminalInfo.Count; i++)
  390. // {
  391. // if (terminalInfo[i].groundStatus == 1 && terminalInfo[i].btnStatus == 0)
  392. // {
  393. // string license = Monitor.Monitor.numMachineLinker.GetLicensePlate(terminalInfo[i].terminalID);
  394. // if (license == "") { break; }
  395. // else
  396. // {
  397. // }
  398. // }
  399. // }
  400. //}
  401. #region 获取号牌方法,已调整
  402. /// <summary>
  403. /// 停车流程,收到号牌机启动后操作过程
  404. /// </summary>
  405. private static void ParkNumSubProcess()
  406. {
  407. for (int i = 0; i < terminalInfo.Count; i++)
  408. {
  409. //启动指令与终端id匹配
  410. //if (numMachineLaunch == terminalInfo[i].terminalID)
  411. if (terminalInfo[i].numMachineLaunch == 1 && terminalInfo[i].licVerification == 0)
  412. {
  413. int numReceivedStatus = 0;//1获得,2终止
  414. TerminalStru term = terminalInfo[i];
  415. if (term.terminalStatus == (short)1)
  416. {
  417. string license = "";
  418. //判断之前是否已拍摄号牌
  419. if (!idLicMap.ContainsKey(terminalInfo[i].terminalID))
  420. {
  421. license = "桂K88888"; //Monitor.Monitor.numMachineLinker.GetLicensePlate(terminalInfo[i].terminalID);
  422. Monitor.Monitor.SetNotification("启动" + terminalInfo[i].terminalID + "号号牌机,号牌:" + license, parkMonitor.model.TextColor.Info);
  423. }
  424. else
  425. {
  426. idLicMap.TryGetValue(terminalInfo[i].terminalID, out license);
  427. }
  428. //未获得号牌,告知PLC终止,告诉终端提示用户重新操作
  429. if (license == "")
  430. {
  431. MainBlockStru mb = new MainBlockStru
  432. {
  433. centralHearbeat = (short)-1,
  434. bookParkCmd = -1,
  435. bookFetchCmd = -1,
  436. licenseReceived = (short)2
  437. };
  438. Monitor.Monitor.PLC.WriteToPLC(mb, PLCDataType.central);
  439. TerminalStru ts = new TerminalStru
  440. {
  441. terminalID = (short)terminalInfo[i].terminalID,
  442. paymentStatus = -1,
  443. parkingFee = -1,
  444. userType = -1,
  445. licVerification = (short)2
  446. };
  447. Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central);
  448. Log.WriteLog(LogType.process, LogFile.ERROR, "未获得号牌");
  449. }
  450. else
  451. {
  452. //记录或更新当前号牌
  453. lock (idLicMap)
  454. {
  455. try
  456. {
  457. if (idLicMap.ContainsKey(terminalInfo[i].terminalID))
  458. {
  459. if (!idLicMap[terminalInfo[i].terminalID].Equals(license))
  460. idLicMap[terminalInfo[i].terminalID] = license;
  461. }
  462. else
  463. {
  464. idLicMap.Add(terminalInfo[i].terminalID, license);
  465. }
  466. }
  467. catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "号牌" + license + "记录号牌异常\n" + e.StackTrace); }
  468. }
  469. Log.WriteLog(LogType.process, LogFile.INFO, "号牌" + license + "已记录");
  470. TerminalStru ts = new TerminalStru
  471. {
  472. terminalID = (short)terminalInfo[i].terminalID,
  473. paymentStatus = -1,
  474. parkingFee = -1,
  475. userType = -1
  476. };
  477. //注册用户
  478. if (term.btnStatus == (short)2 || term.btnStatus == (short)3)
  479. {
  480. int userID = term.licenseCodeA;
  481. string userLicense = GetLicenseFromTerm(term);
  482. //与云端数据比对
  483. ValidateUserInfo(ts, userID, userLicense, out numReceivedStatus);
  484. if (numReceivedStatus == 2)
  485. {
  486. idLicMap.Remove(terminalInfo[i].terminalID);
  487. }
  488. }
  489. //非注册用户
  490. else if (term.btnStatus == (short)1 || term.btnStatus == (short)4)
  491. {
  492. numReceivedStatus = 1;
  493. ts.licVerification = 1;
  494. Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.central);
  495. }
  496. //无论是否注册,皆告知PLC,已获取号牌或比对异常、终止流程
  497. MainBlockStru mb = new MainBlockStru
  498. {
  499. centralHearbeat = -1,
  500. bookFetchCmd = -1,
  501. bookParkCmd = -1,
  502. licenseReceived = (short)numReceivedStatus
  503. };
  504. Monitor.Monitor.PLC.WriteToPLC(mb, PLCDataType.central);
  505. //号牌获取结果被清零才跳出
  506. Monitor.Monitor.SetNotification("已写入号牌获取结果,等待号牌机启动指令清零", parkMonitor.model.TextColor.Info);
  507. }
  508. int countdown = 5;
  509. while (countdown-- > 0)
  510. {
  511. if (term.numMachineLaunch == 0)
  512. {
  513. Monitor.Monitor.SetNotification("号牌机启动指令已被清零", parkMonitor.model.TextColor.Info); break;
  514. }
  515. else
  516. Thread.Sleep(1000);
  517. }
  518. }
  519. }
  520. }
  521. }
  522. #endregion
  523. //private static void ParkNumSubProcess()
  524. //{
  525. //}
  526. /// <summary>
  527. /// 停车流程,收到PLC停车完成信号后操作过程
  528. /// </summary>
  529. private static void ParkCompleteSubProcess()
  530. {
  531. int processAttrib = Monitor.Monitor.mainBlockInfo.parkingRunning;
  532. //int processCompleted = Monitor.Monitor.mainBlockInfo.processCompleted;
  533. int currentTerm = Monitor.Monitor.mainBlockInfo.terminalID;
  534. int parkingSpaceID = 0;
  535. if (processAttrib == 1)
  536. {
  537. TerminalStru term;
  538. string license;
  539. //等待完成信号
  540. while (Monitor.Monitor.mainBlockInfo.processCompleted != 1)
  541. {
  542. if (Monitor.Monitor.mainBlockInfo.processStopped == 1)
  543. return;
  544. Thread.Sleep(200);
  545. }
  546. //找到终端号,判断是否注册用户
  547. //拿到号牌
  548. if (/*terminalInfo[i].terminalID == currentTerm && */idLicMap.TryGetValue(currentTerm, out license) && license != "")
  549. {
  550. term = terminalInfo[currentTerm - 1];
  551. Thread.Sleep(1500);
  552. //找到停车位置
  553. for (int s = 0; s < Monitor.Monitor.parkingSpaceInfo.Count; s++)
  554. {
  555. //Console.WriteLine(Monitor.Monitor.parkingSpaceInfo[s].receiptNum + "," + term.receiptNum);
  556. if (Monitor.Monitor.parkingSpaceInfo[s].receiptNum == term.receiptNum)
  557. {
  558. parkingSpaceID = Monitor.Monitor.parkingSpaceInfo[s].parkingSpace;
  559. break;
  560. }
  561. }
  562. //无车位信息则跳出当前循环
  563. if (parkingSpaceID == 0 || term.receiptNum == 0)
  564. {
  565. try { idLicMap.Remove(currentTerm); } catch { }
  566. Monitor.Monitor.SetNotification("无车位或凭证号", parkMonitor.model.TextColor.Warning);
  567. return;
  568. }
  569. UpdateVehicle(license, 0, 0, true, false, 0);
  570. UpdateVehicle(license, 0, 0, true, true, 0);
  571. //插入停车记录
  572. string parkingRecordsSql = "";
  573. if (term.licenseCodeA != 0)
  574. {
  575. parkingRecordsSql = "INSERT INTO parkingrecords (userID, numberPlate,parkingSpaceID,garageID,parkingRecordsState,realParkTime,receiptNum,parkingPrice)" +
  576. "values ('" + term.licenseCodeA + "','" + license + "','" + parkingSpaceID + "','" + Monitor.Monitor.garageID + "',3,'" + DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss") + "','" + term.receiptNum + "',NULL);";
  577. }
  578. else
  579. {
  580. parkingRecordsSql = "INSERT INTO parkingrecords (userID, numberPlate,parkingSpaceID,garageID,parkingRecordsState,realParkTime,receiptNum,parkingPrice)" +
  581. "values ('" + 1 + "','" + license + "','" + parkingSpaceID + "','" + Monitor.Monitor.garageID + "',3,'" + DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss") + "','" + term.receiptNum + "',NULL);";
  582. }
  583. List<string> list = new List<string>();
  584. list.Add(parkingRecordsSql);
  585. Monitor.Monitor.localDBOper.Insert(list);
  586. Monitor.Monitor.remoteDBOper.Insert(list);
  587. Log.WriteLog(LogType.process, LogFile.INFO, "停车记录已插入," + license + "停在" + parkingSpaceID + ",凭证号:" + term.receiptNum);
  588. Monitor.Monitor.SetNotification("停车记录已插入", parkMonitor.model.TextColor.Info);
  589. ////注册用户记录插入云端
  590. //if (term.btnStatus == 0)
  591. //{
  592. //Monitor.Monitor.remoteDBOper.Insert(list);
  593. //}
  594. //查询记录ID号
  595. string findRecordSql = "select parkingRecordsID from parkingrecords where receiptNum = " + term.receiptNum + ";";
  596. int parkingRecordsID = 0;
  597. int remoteParkingRecordsID = 0;
  598. QueryParkingRecordsID(findRecordSql, out parkingRecordsID, false);
  599. QueryParkingRecordsID(findRecordSql, out remoteParkingRecordsID, true);
  600. //更新车辆表
  601. if (parkingRecordsID != 0)
  602. {
  603. UpdateVehicle(license, 1, parkingRecordsID, true, false, parkingSpaceID);
  604. }
  605. if (remoteParkingRecordsID != 0)
  606. {
  607. UpdateVehicle(license, 1, remoteParkingRecordsID, true, true, parkingSpaceID);
  608. }
  609. Log.WriteLog(LogType.process, LogFile.INFO, "停车记录表已更新");
  610. //更新本地车位
  611. UpdateAllParkingSpace();
  612. //Monitor.Monitor.AddNotification("停车数据库已更新,等待流程结束状态清零。");
  613. //while (Monitor.Monitor.mainBlockInfo.processCompleted != 0)
  614. //{
  615. // Thread.Sleep(1000);
  616. //}
  617. //中控清除车牌、凭证号、号牌验证等信息
  618. ClearTerminal(term.terminalID);
  619. try { idLicMap.Remove(currentTerm); } catch { }
  620. Monitor.Monitor.SetNotification(license + " 数据库已更新,停车流程结束", parkMonitor.model.TextColor.Info);
  621. }
  622. }
  623. }
  624. /// <summary>
  625. /// 预约车辆检测
  626. /// </summary>
  627. private static void ReservedCarCheck()
  628. {
  629. if (lockList.Count != terminalInfo.Count)
  630. {
  631. lockList.Clear();
  632. for (int i = 0; i < terminalInfo.Count; i++)
  633. {
  634. lockList.Add(false);
  635. }
  636. }
  637. //找到停车终端,且有地感无按钮数据
  638. for (int i = 0; i < terminalInfo.Count; i++)
  639. {
  640. //Console.WriteLine(i);
  641. if (terminalInfo[i].terminalStatus == 1 && terminalInfo[i].groundStatus == 1 && terminalInfo[i].btnStatus == 0 && !lockList[i])
  642. {
  643. lockList[i] = true;
  644. Action<int> reserveAction = new Action<int>(ReservedOper);
  645. reserveAction(i);
  646. }
  647. }
  648. }
  649. private static void ReservedOper(int index)
  650. {
  651. Task.Factory.StartNew(() =>
  652. {
  653. string license = "";
  654. int countdown = 2;
  655. short registered = 4;
  656. while (license == "" && countdown-- > 0)
  657. {
  658. license = "桂K88888"; //Monitor.Monitor.numMachineLinker.GetLicensePlate(terminalInfo[index].terminalID);
  659. }
  660. Monitor.Monitor.SetNotification(terminalInfo[index].terminalID + "号车位收到地感,拍到" + license, parkMonitor.model.TextColor.Log);
  661. if (license != "")
  662. {
  663. //map中加入或更新号牌,供完成时写入数据库用
  664. if (idLicMap.ContainsKey(terminalInfo[index].terminalID))
  665. {
  666. idLicMap[terminalInfo[index].terminalID] = license;
  667. }
  668. else
  669. {
  670. idLicMap.Add(terminalInfo[index].terminalID, license);
  671. }
  672. if (Monitor.Monitor.webServer.ReservedCarCheck(license))
  673. {
  674. registered = 3;
  675. Monitor.Monitor.SetNotification("预约车辆入场", parkMonitor.model.TextColor.Info);
  676. }
  677. #region 通过数据库查询是否预约车,方法待定
  678. //int vehicleState = -1;
  679. //string vehicleStateCheckSql = "select vehiclepParkState from vehicle where numberPlate = '" + license + "';";
  680. //MySqlDataReader reader = Monitor.Monitor.localDBOper.Query(vehicleStateCheckSql);
  681. //if (reader != null)
  682. //{
  683. // try
  684. // {
  685. // if (reader.Read())
  686. // {
  687. // vehicleState = reader.GetInt32("vehiclepParkState");
  688. // }
  689. // }
  690. // catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "预约检测,查询车辆状态异常"); ; Console.WriteLine(e.Message); };
  691. // try
  692. // {
  693. // reader.Close();
  694. // reader.Dispose();
  695. // }
  696. // catch { }
  697. //}
  698. //已预约车辆入场
  699. //if (vehicleState == 4)
  700. //{
  701. // registered = 3;
  702. //}
  703. #endregion
  704. TerminalStru ts = new TerminalStru
  705. {
  706. terminalID = terminalInfo[index].terminalID,
  707. paymentStatus = (short)-1,
  708. btnStatus = registered,
  709. cmd = (short)-1,
  710. licenseCodeA = -1,
  711. licenseCodeB = -1,
  712. licenseCodeC = -1,
  713. licenseCodeD = -1,
  714. receiptNum = -1
  715. };
  716. Monitor.Monitor.PLC.WriteToPLC(ts, PLCDataType.terminal);
  717. Monitor.Monitor.SetNotification("指令写入PLC:" + ts.btnStatus, parkMonitor.model.TextColor.Log);
  718. Thread.Sleep(1000);
  719. }
  720. else
  721. {
  722. Thread.Sleep(200);
  723. }
  724. lockList[index] = false;
  725. });
  726. }
  727. /// <summary>
  728. /// 停车相关操作
  729. /// 0.观测到地感信号,且按钮状态不为3,则启动号牌机获取号牌,并判断是否预约车
  730. /// 1.读取到号牌机启动指令,启动号牌机并根据是否注册用户进行操作
  731. /// 非注册拿到号牌后记录并告知plc
  732. /// 注册用户,核对号牌与用户关联信息
  733. /// 2.停车流程结束,写数据库
  734. /// </summary>
  735. ///
  736. private static void ParkProcess()
  737. {
  738. Task.Factory.StartNew(() =>
  739. {
  740. while (!isClosing)
  741. {
  742. ParkNumSubProcess();
  743. Thread.Sleep(Monitor.Monitor.plcRefreshInterval * 5);
  744. }
  745. });
  746. Task.Factory.StartNew(() =>
  747. {
  748. while (!isClosing)
  749. {
  750. ParkCompleteSubProcess();
  751. Thread.Sleep(Monitor.Monitor.plcRefreshInterval * 5);
  752. }
  753. });
  754. Task.Factory.StartNew(() =>
  755. {
  756. while (!isClosing)
  757. {
  758. ReservedCarCheck();
  759. Thread.Sleep(Monitor.Monitor.plcRefreshInterval * 5);
  760. }
  761. });
  762. }
  763. /// <summary>
  764. /// 根据凭证号查询停车记录
  765. /// </summary>
  766. /// <param name="receipt"></param>
  767. /// <param name="recordID"></param>
  768. /// <param name="userID"></param>
  769. /// <param name="license"></param>
  770. /// <param name="realParkTime"></param>
  771. private static bool FindLocalParkingRecord(int receipt, out int recordID, out int userID, out string license, out string realParkTime)
  772. {
  773. recordID = 0;
  774. userID = 0;
  775. license = "";
  776. realParkTime = "";
  777. bool result = false;
  778. string parkRecordsSql = "select parkingRecordsID,userID,numberPlate,realParkTime from parkingrecords where receiptNum = " + receipt + ";";
  779. MySqlDataReader reader = Monitor.Monitor.localDBOper.Query(parkRecordsSql);
  780. try
  781. {
  782. if (reader != null && reader.Read())
  783. {
  784. object[] receiver = new object[4];
  785. reader.GetValues(receiver);
  786. recordID = (int)receiver[0];
  787. userID = (int)receiver[1];
  788. license = (string)receiver[2];
  789. realParkTime = (string)receiver[3];
  790. result = true;
  791. }
  792. else
  793. {
  794. Log.WriteLog(LogType.process, LogFile.ERROR, "根据凭证号查询停车记录失败");
  795. Monitor.Monitor.SetNotification("取车流程, 根据凭证号查询停车记录失败", parkMonitor.model.TextColor.Error);
  796. result = false;
  797. }
  798. //if (reader != null)
  799. //{
  800. // reader.Close();
  801. // reader.Dispose();
  802. //}
  803. }
  804. catch (Exception e) { Log.WriteLog(LogType.process, LogFile.ERROR, "根据凭证号查询停车记录失败"); Console.WriteLine(e.Message); result = false; }
  805. try
  806. {
  807. if (reader != null)
  808. {
  809. reader.Close();
  810. reader.Dispose();
  811. }
  812. }
  813. catch { }
  814. if (result)
  815. Log.WriteLog(LogType.process, LogFile.INFO, "根据凭证号查询停车记录成功");
  816. return result;
  817. }
  818. private static bool FindRemoteParkingRecord(int receipt, out int recordID)
  819. {
  820. recordID = 0;
  821. bool result = false;
  822. string remoteParkRecordsSql = "select parkingRecordsID from parkingrecords where receiptNum = " + receipt + ";";
  823. MySqlDataReader reader = Monitor.Monitor.remoteDBOper.Query(remoteParkRecordsSql);
  824. try
  825. {
  826. if (reader != null && reader.Read())
  827. {
  828. object[] receiver = new object[1];
  829. reader.GetValues(receiver);
  830. recordID = (int)receiver[0];
  831. result = true;
  832. }
  833. }
  834. catch (Exception e) { Console.WriteLine(e.Message); result = false; }
  835. try
  836. {
  837. if (reader != null)
  838. {
  839. reader.Close();
  840. reader.Dispose();
  841. }
  842. }
  843. catch (Exception e) { Console.WriteLine(e.Message); result = false; }
  844. return result;
  845. }
  846. /// <summary>
  847. /// 根据号牌获取本地与远端用户VIP月卡及预约信息
  848. /// </summary>
  849. /// <param name="license"></param>
  850. /// <param name="orderRecordsID"></param>
  851. /// <param name="monthCardType"></param>
  852. /// <param name="monthCardTimeLength"></param>
  853. /// <param name="orderTimeLength"></param>
  854. /// <returns></returns>
  855. private static bool FindVipInfo(string license, ref int orderRecordsID, ref int monthCardType, ref TimeSpan monthCardTimeLength, ref TimeSpan orderTimeLength)
  856. {
  857. bool result = true;
  858. string monthCardTime = "";
  859. //本地VIP信息
  860. string vipInfoSql = "select orderRecordsID,monthCardType,monthCardTime from vehicle where numberPlate = '" + license + "';";
  861. MySqlDataReader reader = null;
  862. try
  863. {
  864. reader = Monitor.Monitor.localDBOper.Query(vipInfoSql);
  865. if (reader != null && reader.Read())
  866. {
  867. object[] receiver = new object[3];
  868. reader.GetValues(receiver);
  869. Console.WriteLine(receiver[2].GetType());
  870. if (!receiver[0].GetType().Equals(typeof(DBNull)))
  871. {
  872. orderRecordsID = (int)receiver[0];
  873. }
  874. if (!receiver[1].GetType().Equals(typeof(DBNull)))
  875. {
  876. monthCardType = (int)(UInt32)receiver[1];
  877. }
  878. if (!receiver[2].GetType().Equals(typeof(DBNull)))
  879. {
  880. monthCardTime = (string)receiver[2];
  881. }
  882. //orderRecordsID = (Int32)receiver[0];
  883. //monthCardType = (Int32)receiver[1];
  884. //monthCardTime = (string)receiver[2];
  885. monthCardTimeLength = DateTime.Parse(monthCardTime) - DateTime.Now;
  886. if (monthCardTimeLength.TotalHours <= 0)
  887. {
  888. monthCardType = 0;
  889. }
  890. Log.WriteLog(LogType.process, LogFile.INFO, "已获取本地预约与月卡信息");
  891. }
  892. }
  893. catch (Exception e) { Console.WriteLine(e.Message); result = false; }
  894. try
  895. {
  896. if (reader != null)
  897. {
  898. reader.Close();
  899. reader.Dispose();
  900. }
  901. }
  902. catch (Exception e) { Console.WriteLine(e.Message); result = false; }
  903. //云端VIP信息
  904. try
  905. {
  906. reader = Monitor.Monitor.remoteDBOper.Query(vipInfoSql);
  907. if (reader != null && reader.Read())
  908. {
  909. object[] receiver = new object[3];
  910. reader.GetValues(receiver);
  911. int cardType = (int)(UInt32)receiver[1];
  912. string CardTime = (string)receiver[2];
  913. TimeSpan t = DateTime.Parse(CardTime) - DateTime.Now;
  914. //云端
  915. if (t.TotalHours > 0 && cardType > monthCardType)
  916. {
  917. monthCardType = cardType;
  918. monthCardTimeLength = t;
  919. }
  920. Log.WriteLog(LogType.process, LogFile.INFO, "已获取云端预约与月卡信息");
  921. }
  922. }
  923. catch (Exception e) { Console.WriteLine(e.Message); result = false; }
  924. try
  925. {
  926. if (reader != null)
  927. {
  928. reader.Close();
  929. reader.Dispose();
  930. }
  931. }
  932. catch (Exception e) { Console.WriteLine(e.Message); result = false; }
  933. //有预约记录,判断记录有效性,有效则获取预约时长
  934. if (orderRecordsID != 0)
  935. {
  936. //修改orderTimeLength
  937. string orderInfoSql = "select bookHour from orderrecords where orderRecordsID = '" + orderRecordsID + "';";
  938. try
  939. {
  940. reader = Monitor.Monitor.localDBOper.Query(vipInfoSql);
  941. if (reader != null && reader.Read())
  942. {
  943. orderTimeLength = new TimeSpan(reader.GetInt32("bookHour"), 0, 0);
  944. }
  945. }
  946. catch { }
  947. }
  948. try
  949. {
  950. if (reader != null)
  951. {
  952. reader.Close();
  953. reader.Dispose();
  954. }
  955. }
  956. catch (Exception e) { Console.WriteLine(e.Message); }
  957. return result;
  958. }
  959. /// <summary>
  960. /// 预约与停车费用计算
  961. /// </summary>
  962. /// <param name="scheme"></param>
  963. /// <param name="parkTime"></param>
  964. /// <param name="orderTimeLength"></param>
  965. /// <returns></returns>
  966. private static int FeeCalc(PaymentScheme scheme, DateTime parkTime, TimeSpan orderTimeLength)
  967. {
  968. try
  969. {
  970. int orderFee = scheme.bookCharge * (int)orderTimeLength.TotalHours;
  971. int parkFee = 0;
  972. int hours = (int)(DateTime.Now - parkTime).TotalHours;
  973. switch (scheme.schemeType)
  974. {
  975. //按时计费
  976. case 1:
  977. if (hours > scheme.firstChargeTime + scheme.freeTime)
  978. {
  979. if (hours > 24)
  980. {
  981. parkFee = hours / 24 * scheme.upperBound + Math.Min(scheme.intervalCharge * (hours % 24) / scheme.chargeInterval, scheme.upperBound);
  982. }
  983. else
  984. {
  985. parkFee = Math.Min(scheme.firstCharge + scheme.intervalCharge * hours / scheme.chargeInterval, scheme.upperBound);
  986. }
  987. }
  988. else if (hours > scheme.freeTime)
  989. {
  990. parkFee = scheme.firstCharge;
  991. }
  992. else
  993. {
  994. parkFee = 0;
  995. }
  996. break;
  997. //按次计费
  998. case 2:
  999. //Console.WriteLine(DateTime.Now.Date.ToString()+","+ parkTime.Date.ToString());
  1000. int overnightCount = (DateTime.Now.Date - parkTime.Date).Days;
  1001. parkFee = scheme.eachCharge + overnightCount * scheme.overnightCharge;
  1002. break;
  1003. //按时间段计费
  1004. case 3:
  1005. TimeSpan currentTimeOfDay = DateTime.Now.TimeOfDay;
  1006. TimeSpan parkTimeOfDay = parkTime.TimeOfDay;
  1007. TimeSpan startTimeOfDay = DateTime.Parse(scheme.startChargeTime).TimeOfDay;
  1008. TimeSpan endTimeOfDay = DateTime.Parse(scheme.endChargeTime).TimeOfDay;
  1009. double countingHoursOfDay = endTimeOfDay.TotalHours - startTimeOfDay.TotalHours;
  1010. int days = (int)((DateTime.Now - parkTime).TotalHours - currentTimeOfDay.TotalHours + parkTimeOfDay.TotalHours);
  1011. int previousOffset = (int)(-(Math.Max(0, parkTimeOfDay.TotalHours - startTimeOfDay.TotalHours)));
  1012. int currentOffset = (int)Math.Min((currentTimeOfDay.TotalHours - startTimeOfDay.TotalHours), countingHoursOfDay);
  1013. int peakTimeLength = days * (int)countingHoursOfDay + previousOffset + currentOffset;
  1014. parkFee = peakTimeLength * scheme.chargeStandard + ((int)((DateTime.Now - parkTime).TotalHours) - peakTimeLength) * scheme.intervalCharge;
  1015. break;
  1016. }
  1017. Log.WriteLog(LogType.process, LogFile.INFO, "停车费用" + parkFee);
  1018. return parkFee;
  1019. }
  1020. catch (Exception e) { Console.WriteLine("费用计算异常"); return -1; }
  1021. }
  1022. /// <summary>
  1023. /// 取车计费子操作
  1024. /// </summary>
  1025. private static void FetchFeeCalcSubProcess()
  1026. {
  1027. int receiptNum = 0;
  1028. int termIndex = -1;
  1029. bool failed = false;
  1030. TerminalStru ts = new TerminalStru();
  1031. for (int i = 0; i < terminalInfo.Count; i++)
  1032. {
  1033. ts = terminalInfo[i];
  1034. termIndex = ts.terminalID;
  1035. receiptNum = ts.receiptNum;
  1036. //取车状态、凭证号不为空,查询数据库计费
  1037. //Console.WriteLine((termIndex != -1) + "," + (termUsedMap.Count >= termIndex) + "," + termUsedMap.TryGetValue(termIndex, out bool valuee) + "," + (!valuee) + "," + (fetchState == 1) + "," + (receiptNum != 0));
  1038. if (termIndex != -1 && termCalcMap.Count >= termIndex && termCalcMap.TryGetValue(termIndex, out bool value) && !value && ts.cmd == 2 && receiptNum != 0)
  1039. {
  1040. //fetchState = Monitor.Monitor.mainBlockInfo.fetchingRunning;
  1041. Monitor.Monitor.SetNotification(termIndex + "号终端准备计算费用", parkMonitor.model.TextColor.Log);
  1042. termCalcMap[termIndex] = true;
  1043. Console.WriteLine("终端编号" + termIndex);
  1044. int parkingRecordsID = 0;
  1045. int remoteParkingRecordsID = 0;
  1046. int userID = 0;
  1047. string license = "";
  1048. string realParkTime = "";
  1049. //1.根据凭证号查询停车记录
  1050. if (!FindLocalParkingRecord(receiptNum, out parkingRecordsID, out userID, out license, out realParkTime))
  1051. {
  1052. failed = true;
  1053. //return;
  1054. }
  1055. else
  1056. {
  1057. FindRemoteParkingRecord(receiptNum, out remoteParkingRecordsID);
  1058. }
  1059. //本地存在号牌,后续操作
  1060. //2.根据号牌查询车辆月卡信息与预约记录
  1061. int orderRecordsID = 0;
  1062. int monthCardType = -1;
  1063. string monthCardTime = "";
  1064. TimeSpan monthCardTimeLength = new TimeSpan(0);
  1065. TimeSpan orderTimeLength = new TimeSpan(0);
  1066. if (license != "")
  1067. {
  1068. FindVipInfo(license, ref orderRecordsID, ref monthCardType, ref monthCardTimeLength, ref orderTimeLength);
  1069. }
  1070. if (monthCardType == -1) monthCardType = 0;
  1071. //3.获取停车时刻,根据用户类型计费发送给PLC,暂认为无预约
  1072. DateTime parkTime = DateTime.Now, currentTime = DateTime.Now;
  1073. try
  1074. {
  1075. parkTime = DateTime.Parse(realParkTime);
  1076. }
  1077. catch { failed = true; }
  1078. int fee = 32767;
  1079. if (failed) { monthCardType = -2; }
  1080. if (PaymentScheme.ins != null)
  1081. {
  1082. if (monthCardTimeLength.TotalHours > 0)
  1083. {
  1084. fee = 0;
  1085. }
  1086. else if (failed)
  1087. {
  1088. fee = 0;
  1089. }
  1090. else
  1091. {
  1092. fee = FeeCalc(PaymentScheme.ins, parkTime, orderTimeLength);
  1093. }
  1094. try
  1095. {
  1096. if (Monitor.Monitor.PLC != null)
  1097. {
  1098. TerminalStru FeeMsg = new TerminalStru();
  1099. FeeMsg.terminalID = (short)termIndex;
  1100. FeeMsg.paymentStatus = (short)-1;
  1101. FeeMsg.licVerification = (short)-1;
  1102. FeeMsg.parkingFee = (short)fee;
  1103. FeeMsg.userType = (short)(monthCardType + 1);
  1104. Console.WriteLine(FeeMsg);
  1105. Monitor.Monitor.PLC.WriteToPLC(FeeMsg, PLCDataType.central);
  1106. Log.WriteLog(LogType.process, LogFile.INFO, "停车费用已发送至PLC");
  1107. }
  1108. }
  1109. catch { Console.WriteLine("error"); }
  1110. }
  1111. Monitor.Monitor.SetNotification("用户类型:" + (monthCardType + 1) + ",费用:" + fee + ",等待凭证号被清除且流程结束后更新车辆状态", parkMonitor.model.TextColor.Log);
  1112. FetchInfo fetchInfo = new FetchInfo(license, parkingRecordsID, remoteParkingRecordsID, fee, receiptNum);
  1113. if (!fetchInfoMap.ContainsKey(termIndex))
  1114. {
  1115. fetchInfoMap.Add(termIndex, fetchInfo);
  1116. fetchCompleteMap.Add(termIndex, true);
  1117. }
  1118. else
  1119. {
  1120. fetchInfoMap[termIndex] = fetchInfo;
  1121. fetchCompleteMap[termIndex] = true;
  1122. }
  1123. }
  1124. }
  1125. }
  1126. private static void FetchCompleteProcess()
  1127. {
  1128. int fetchState = Monitor.Monitor.mainBlockInfo.fetchingRunning;
  1129. int termIndex = -1;
  1130. try
  1131. {
  1132. if (fetchState == 1)
  1133. {
  1134. //找到当前取车终端
  1135. for (int i = 0; i < terminalInfo.Count; i++)
  1136. {
  1137. if (terminalInfo[i].terminalID == Monitor.Monitor.mainBlockInfo.terminalID && Monitor.Monitor.mainBlockInfo.terminalID != 0)
  1138. {
  1139. termIndex = i;
  1140. break;
  1141. }
  1142. }
  1143. if (fetchCompleteMap.ContainsKey(terminalInfo[termIndex].terminalID) && fetchCompleteMap[terminalInfo[termIndex].terminalID])
  1144. {
  1145. fetchCompleteMap[terminalInfo[termIndex].terminalID] = false;
  1146. Task.Factory.StartNew(() =>
  1147. {
  1148. //4.等待终端获得收费完成信号且将凭证号清除后,清除收费完成信号并将信息写入数据库
  1149. int count = 0;
  1150. while (!isClosing && termIndex != -1)
  1151. {
  1152. if (Monitor.Monitor.mainBlockInfo.processStopped == 1)
  1153. {
  1154. Log.WriteLog(LogType.process, LogFile.INFO, "检测到流程中断");
  1155. break;
  1156. }
  1157. if (Monitor.Monitor.mainBlockInfo.processCompleted == 1)
  1158. {
  1159. while (terminalInfo[termIndex].receiptNum != 0)
  1160. {
  1161. count++;
  1162. if (count == 1)
  1163. Monitor.Monitor.SetNotification("等待凭证号清除", parkMonitor.model.TextColor.Log);
  1164. if (count > 10000)//避免int型数据溢出
  1165. count = 2;
  1166. Thread.Sleep(200);
  1167. }
  1168. int paymentStatus = 0;
  1169. for (int i = 0; i < terminalInfo.Count; i++)
  1170. {
  1171. if (terminalInfo[i].terminalID == Monitor.Monitor.mainBlockInfo.terminalID)
  1172. {
  1173. paymentStatus = terminalInfo[i].paymentStatus;
  1174. break;
  1175. }
  1176. }
  1177. Log.WriteLog(LogType.process, LogFile.INFO, "检测到凭证号已被清除");
  1178. FetchInfo fi = null;
  1179. UpdateAllParkingSpace();
  1180. ClearTerminal(terminalInfo[termIndex].terminalID);
  1181. if (fetchInfoMap.ContainsKey(terminalInfo[termIndex].terminalID))
  1182. {
  1183. fi = fetchInfoMap[terminalInfo[termIndex].terminalID];
  1184. }
  1185. else
  1186. {
  1187. Monitor.Monitor.SetNotification("未查询到该取车终端存在计费操作", parkMonitor.model.TextColor.Error);
  1188. Log.WriteLog(LogType.process, LogFile.ERROR, "终端" + terminalInfo[termIndex].terminalID + "无计费操作");
  1189. return;
  1190. }
  1191. //TerminalStru fetchReset = new TerminalStru
  1192. //{
  1193. // terminalID = (short)termIndex,
  1194. // paymentStatus = (short)0,
  1195. // licVerification = (short)0,
  1196. // parkingFee = (short)32767,
  1197. // userType = (short)0
  1198. //};
  1199. //Monitor.Monitor.PLC.WriteToPLC(fetchReset, PLCDataType.central);
  1200. //更新停车记录与车辆状态
  1201. string updateParkingRecordsSql = "update parkingrecords set parkingRecordsState = 6,realGetTime = '" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") +
  1202. "',parkingPrice = " + fi.fee + ",paymentStatus = " + paymentStatus + " where receiptNum = '" + fi.receiptNum + "';";
  1203. List<string> list = new List<string>();
  1204. list.Add(updateParkingRecordsSql);
  1205. lock (Monitor.Monitor.localDBOper)
  1206. {
  1207. Monitor.Monitor.localDBOper.UpdateTransaction(list);
  1208. UpdateVehicle(fi.license, 0, fi.parkingRecordsID, false, false, 0);
  1209. }
  1210. lock (Monitor.Monitor.remoteDBOper)
  1211. {
  1212. Monitor.Monitor.remoteDBOper.UpdateTransaction(list);
  1213. UpdateVehicle(fi.license, 0, fi.remoteParkingRecordsID, false, true, 0);
  1214. }
  1215. Monitor.Monitor.SetNotification(fi.license + " 取车流程结束", parkMonitor.model.TextColor.Info);
  1216. break;
  1217. }
  1218. Thread.Sleep(200);
  1219. }
  1220. termCalcMap[terminalInfo[termIndex].terminalID] = false;
  1221. fetchInfoMap.Remove(terminalInfo[termIndex].terminalID);
  1222. fetchCompleteMap.Remove(terminalInfo[termIndex].terminalID);
  1223. });
  1224. }
  1225. }
  1226. }
  1227. catch (Exception ex) { Log.WriteLog(LogType.process, LogFile.ERROR, "取车完成流程异常," + ex.StackTrace); }
  1228. }
  1229. /// <summary>
  1230. /// 取车相关操作
  1231. ///
  1232. /// </summary>
  1233. private static void FetchProcess()
  1234. {
  1235. Task.Factory.StartNew(() =>
  1236. {
  1237. while (!isClosing)
  1238. {
  1239. FetchFeeCalcSubProcess();
  1240. Thread.Sleep(Monitor.Monitor.plcRefreshInterval);
  1241. }
  1242. });
  1243. Task.Factory.StartNew(() =>
  1244. {
  1245. while (!isClosing)
  1246. {
  1247. FetchCompleteProcess();
  1248. Thread.Sleep(Monitor.Monitor.plcRefreshInterval);
  1249. }
  1250. });
  1251. }
  1252. public static void Start()
  1253. {
  1254. for (int i = 0; i < Monitor.Monitor.plcTerminalCount; i++)
  1255. {
  1256. lockList.Add(false);
  1257. }
  1258. ParkProcess();
  1259. FetchProcess();
  1260. }
  1261. public static void Stop()
  1262. {
  1263. isClosing = true;
  1264. }
  1265. public class FetchInfo
  1266. {
  1267. public string license;
  1268. public int parkingRecordsID;
  1269. public int remoteParkingRecordsID;
  1270. public int fee;
  1271. public int receiptNum;
  1272. public FetchInfo(string license, int parkingRecordsID, int remoteParkingRecordsID, int fee, int receiptNum)
  1273. {
  1274. this.license = license;
  1275. this.parkingRecordsID = parkingRecordsID;
  1276. this.remoteParkingRecordsID = remoteParkingRecordsID;
  1277. this.fee = fee;
  1278. this.receiptNum = receiptNum;
  1279. }
  1280. }
  1281. }
  1282. }