Terminal.cs 50 KB

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