Terminal.cs 48 KB

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