NumMachine.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Windows.Forms;
  5. using HslCommunication;
  6. using HslCommunication.ModBus;
  7. using System.Threading;
  8. using System.Collections;
  9. using HslCommunication.Controls;
  10. using VzClientSDKDemo;
  11. using System.Runtime.InteropServices;
  12. using System.IO;
  13. using System.Net;
  14. using parkMonitor.entity;
  15. using System.Diagnostics;
  16. using System.Threading.Tasks;
  17. using parkMonitor.model;
  18. using parkMonitor.viewModel.objectTree;
  19. using parkMonitor.server.uiLogServer;
  20. using System.Configuration;
  21. using parkMonitor.LOG;
  22. namespace parkMonitor.server
  23. {
  24. /// <summary>
  25. /// 号牌机通信类
  26. /// </summary>
  27. public partial class NumMachineLinker : Form, IEquipments
  28. {
  29. /// <summary>
  30. /// 刷新时间间隔与个数
  31. /// </summary>
  32. public const int REFRESHINGTIME = 500, FILTERINGNUMBER = 8;
  33. ///<summary>通过设备句柄访问pic;链接时add,系统关闭时remove</summary>
  34. private static Dictionary<int, PictureBox> devPicMap = new Dictionary<int, PictureBox>();
  35. ///<summary>通过名字获取pic对象;创建pic时add,系统关闭remove</summary>
  36. private static Dictionary<string, PictureBox> namePicMap = new Dictionary<string, PictureBox>();
  37. ///<summary>通过ip获取设备id;产生ip时创建</summary>
  38. private static Dictionary<string, int> ipIdMap = new Dictionary<string, int>();
  39. ///<summary>通过ip获取设备句柄;产生句柄时创建</summary>
  40. private static Dictionary<string, int> ipHandleMap = new Dictionary<string, int>();
  41. /// <summary>句柄到号牌回调映射</summary>
  42. private static Dictionary<int, VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK> handleCallbackMap = new Dictionary<int, VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK>();
  43. ///<summary>号牌队列</summary>
  44. private static Queue<NumberMachineNode> LicBuffer = new Queue<NumberMachineNode>();
  45. ///<summary>计数Map</summary>
  46. private static Dictionary<string, Dictionary<NumberMachineNode, int>> filterMap = new Dictionary<string, Dictionary<NumberMachineNode, int>>();
  47. /// <summary>筛选计数</summary>
  48. private static int filterCount = 0;
  49. private static double filterRatio = 0.7;
  50. /// <summary>系统关闭</summary>
  51. private static bool isClosing = false;
  52. /// <summary>开启拍照的设备</summary>
  53. private static int snapshotDevHandle = -1;
  54. /// <summary>允许无号牌时拍照</summary>
  55. private static bool enableEmptySnapshot = true;
  56. private static NumberMachineMessage nmMsg = new NumberMachineMessage();
  57. private static VzClientSDK.VZLPRC_FIND_DEVICE_CALLBACK_EX find_DeviceCB = null;
  58. private const int MSG_PLATE_INFO = 0x901;
  59. private const int MSG_DEVICE_INFO = 0x902;
  60. /// <summary>
  61. /// 用于消息传递机制
  62. /// </summary>
  63. public static IntPtr hwndMain;
  64. /// <summary>
  65. /// 号牌机类构造函数
  66. /// </summary>
  67. public NumMachineLinker()
  68. {
  69. Control.CheckForIllegalCrossThreadCalls = false;
  70. InitializeComponent();
  71. Thread thread = new Thread(new ThreadStart(DateTimeInfo));
  72. thread.IsBackground = true;
  73. thread.Start(); //显示当前时间
  74. VzClientSDK.VzLPRClient_Setup();
  75. hwndMain = this.Handle;
  76. try
  77. {
  78. filterRatio = Double.Parse(ConfigurationManager.AppSettings.Get("filterRatio"));
  79. }
  80. catch (Exception) { UILogServer.ins.error("号牌机配置文件异常"); Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "号牌机配置文件异常"); }
  81. //m_sAppPath = System.IO.Directory.GetCurrentDirectory();
  82. }
  83. /// <summary>
  84. /// 定义时钟委托
  85. /// </summary>
  86. public delegate void SetDateTime();
  87. /// <summary>
  88. /// 实时采集
  89. /// </summary>
  90. public delegate void Begin_Read();
  91. private void FormSiemens_Load(object sender, EventArgs e)
  92. {
  93. Thread thread = new Thread(new ThreadStart(DateTimeInfo));
  94. thread.IsBackground = true;
  95. thread.Start(); //显示当前时间
  96. VzClientSDK.VzLPRClient_Setup();
  97. hwndMain = this.Handle;
  98. //m_sAppPath = System.IO.Directory.GetCurrentDirectory();
  99. //this.ShowInTaskbar = false;
  100. //this.Opacity = 0;
  101. }
  102. private void FormSiemens_FormClosing(object sender, FormClosingEventArgs e)
  103. {
  104. Stop();
  105. }
  106. private void DateTimeInfo()
  107. {
  108. try
  109. {
  110. while (!isClosing)
  111. {
  112. SetDateTime setDate = new SetDateTime(
  113. delegate
  114. {
  115. toolStripStatusLabel2.Text = DateTime.Now.ToString();
  116. });
  117. setDate();
  118. Thread.Sleep(1000);
  119. }
  120. // ReSharper disable once FunctionNeverReturns
  121. }
  122. catch (Exception e) { Debug.Print(e.StackTrace); }
  123. }
  124. //******************************************************************************************************************
  125. private void UpdateStatus(NumberMachineNode nmn)
  126. {
  127. //提示次数计数
  128. int count = 0;
  129. while (!isClosing)
  130. {
  131. if (GetStatus(nmn.ip) == 1)
  132. {
  133. nmn.status = EnumNumberMachineStatus.Normal;
  134. count = 0;
  135. }
  136. else
  137. {
  138. count++;
  139. //号牌机断线写日志
  140. nmn.status = EnumNumberMachineStatus.Offline;
  141. if (count == 1)
  142. {
  143. Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "正在与ip为 " + nmn.ip + " 的号牌机 进行连接。");
  144. UILogServer.ins.info("正在与ip为 " + nmn.ip + " 的号牌机 进行连接。");
  145. }
  146. Thread.Sleep(10000);
  147. }
  148. Thread.Sleep(REFRESHINGTIME);
  149. }
  150. }
  151. private void Run()
  152. {
  153. try
  154. {
  155. while (!isClosing)
  156. {
  157. Thread.Sleep(REFRESHINGTIME);
  158. //定时返回号牌
  159. lock (devPicMap)
  160. {
  161. Dictionary<int, PictureBox>.Enumerator devEnumer = devPicMap.GetEnumerator();
  162. while (devEnumer.MoveNext())
  163. {
  164. ActivateSnap(devEnumer.Current.Key);
  165. //Debug.WriteLine(lv.data.Count.ToString()+":\n"+ lv.data[lv.data.Count-1].LicenseNum+ lv.data[lv.data.Count - 1].TimeRecord);
  166. }
  167. }
  168. //读取设备ip与id映射关系
  169. lock (ipHandleMap)
  170. {
  171. Dictionary<string, int>.Enumerator ipEnumer = ipHandleMap.GetEnumerator();
  172. while (ipEnumer.MoveNext())
  173. {
  174. //映射关系不存在则读取配置文件
  175. lock (ipIdMap)
  176. {
  177. if (ipEnumer.Current.Key != null && !ipIdMap.ContainsKey(ipEnumer.Current.Key))
  178. {
  179. try
  180. {
  181. int id = Int32.Parse(ConfigurationManager.AppSettings.Get(ipEnumer.Current.Key));
  182. ipIdMap.Add(ipEnumer.Current.Key, id);
  183. }
  184. catch (Exception) { UILogServer.ins.log("读取号牌机编号映射失败,配置文件填写有误"); Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "读取号牌机编号映射失败"); }
  185. }
  186. }
  187. }
  188. }
  189. lock (LicBuffer)
  190. {
  191. //删除已停好车的号牌
  192. for (int i = 0; i < LicBuffer.Count; i++)
  193. {
  194. NumberMachineNode n = (NumberMachineNode)LicBuffer.Dequeue().Clone();
  195. if (n.ip != "")
  196. {
  197. LicBuffer.Enqueue((NumberMachineNode)n.Clone());
  198. }
  199. }
  200. }
  201. }
  202. }
  203. catch (Exception ex)
  204. {
  205. Debug.WriteLine(ex.ToString());
  206. }
  207. }
  208. ///<summary>寻找设备回调函数</summary>
  209. private void FIND_DEVICE_CALLBACK_EX(string pStrDevName, string pStrIPAddr, ushort usPort1, ushort usPort2, uint SL, uint SH, string netmask, string gateway, IntPtr pUserData)
  210. {
  211. string pStrDev = pStrIPAddr.ToString() + ":" + usPort1.ToString();
  212. string serialNO = SL.ToString() + ":" + SH.ToString() + ":" + netmask + ":" + gateway;
  213. VzClientSDK.VZ_LPR_DEVICE_INFO device_info = new VzClientSDK.VZ_LPR_DEVICE_INFO();
  214. device_info.device_ip = pStrDev;
  215. device_info.serial_no = serialNO;
  216. DeviceLink(pStrDev, serialNO);
  217. }
  218. ///<summary>与设备连接,启动更新设备状态线程,输出视频</summary>
  219. private void DeviceLink(string pStrDev, string serialNO)
  220. {
  221. IPEndPoint ipe;
  222. GetIpEndPoint(pStrDev, out ipe);
  223. string ip = ipe.Address.ToString();
  224. if (ipHandleMap.ContainsKey(ip))
  225. {
  226. //MessageBox.Show("设备已分配句柄");
  227. return;
  228. }
  229. int handle = 0;
  230. //找到设备,加入list
  231. NumberMachineNode node = new NumberMachineNode(ip, 0, "", "", 1);
  232. nmMsg.data.Add(node);
  233. handle = VzClientSDK.VzLPRClient_Open(ip, (ushort)80, "admin", "admin");
  234. Task.Factory.StartNew(() =>
  235. {
  236. UpdateStatus(node);
  237. });
  238. if (handle == 0)
  239. {
  240. return;
  241. }
  242. VzClientSDK.VzLPRClient_SetVideoEncodeType(handle, 0);
  243. //将句柄加入
  244. lock (ipHandleMap)
  245. {
  246. ipHandleMap.Add(ip, handle);
  247. }
  248. //MessageBox.Show("摄像头打开成功");
  249. lock (handleCallbackMap)
  250. {
  251. handleCallbackMap.Add(handle, null);
  252. }
  253. //链接句柄到新PictureBox
  254. VideoOutput(handle);
  255. }
  256. ///<summary>视频输出</summary>
  257. private void VideoOutput(int handle)
  258. {
  259. try
  260. {
  261. lock (devPicMap)
  262. {
  263. lock (handleCallbackMap)
  264. {
  265. //存在设备则复位并在原pic上输出
  266. if (devPicMap.ContainsKey(handle))
  267. {
  268. VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, null, IntPtr.Zero, 0);
  269. PictureBox pic;
  270. if (devPicMap.TryGetValue(handle, out pic) && handleCallbackMap.ContainsKey(handle))
  271. {
  272. int playHandle = VzClientSDK.VzLPRClient_StartRealPlay(handle, pic.Handle);
  273. // 设置车牌识别结果回调
  274. handleCallbackMap[handle] = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
  275. VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, handleCallbackMap[handle], IntPtr.Zero, 1);
  276. //m_PlateResultCB = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
  277. //VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, m_PlateResultCB, IntPtr.Zero, 1);
  278. //VzClientSDK.VzLPRClient_StopRealPlay(handle);
  279. }
  280. }
  281. else//否则找一个空位加pic
  282. {
  283. for (int i = 0; i < 20; i++)
  284. {
  285. string str = "PictureBox" + Convert.ToString(i);
  286. //该名称对应控件不存在,则创建并链接pic
  287. lock (namePicMap)
  288. {
  289. if (!namePicMap.ContainsKey(str) && handleCallbackMap.ContainsKey(handle))
  290. {
  291. PictureBox pic;
  292. if (CreatePic(i, out pic))
  293. {
  294. devPicMap.Add(handle, pic);
  295. //ipIdMap.Add(Get_IP(handle), i);
  296. VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, null, IntPtr.Zero, 0);
  297. int playHandle = VzClientSDK.VzLPRClient_StartRealPlay(handle, pic.Handle);
  298. // 设置车牌识别结果回调
  299. handleCallbackMap[handle] = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
  300. VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, handleCallbackMap[handle], IntPtr.Zero, 1);
  301. //m_PlateResultCB = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
  302. //VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, m_PlateResultCB, IntPtr.Zero, 1);
  303. //VzClientSDK.VzLPRClient_StopRealPlay(handle);
  304. break;
  305. }
  306. }
  307. }
  308. }
  309. }
  310. }
  311. }
  312. }
  313. catch (Exception)
  314. {
  315. Debug.WriteLine("jumped out");
  316. }
  317. }
  318. ///<summary>号牌信息回调</summary>
  319. private int OnPlateResult(int handle, IntPtr pUserData,
  320. IntPtr pResult, uint uNumPlates,
  321. VzClientSDK.VZ_LPRC_RESULT_TYPE eResultType,
  322. IntPtr pImgFull,
  323. IntPtr pImgPlateClip)
  324. {
  325. if (eResultType != VzClientSDK.VZ_LPRC_RESULT_TYPE.VZ_LPRC_RESULT_REALTIME)
  326. {
  327. VzClientSDK.TH_PlateResult result = (VzClientSDK.TH_PlateResult)Marshal.PtrToStructure(pResult, typeof(VzClientSDK.TH_PlateResult));
  328. string strLicense = (new string(result.license)).Split('\0')[0];
  329. VzClientSDK.VZ_LPR_MSG_PLATE_INFO plateInfo = new VzClientSDK.VZ_LPR_MSG_PLATE_INFO();
  330. plateInfo.plate = strLicense;
  331. SetDetail(plateInfo, Get_IP(handle));
  332. //根据setMessage中通过id信息找到的handle保存图片
  333. if (handle == snapshotDevHandle)
  334. {
  335. if (enableEmptySnapshot || !strLicense.Contains("_无_"))
  336. {
  337. string strFilePath = ConfigurationManager.AppSettings["LogPath"] + DateTime.Now.ToString("yyyyMMdd") + "\\";
  338. if (!Directory.Exists(strFilePath))
  339. {
  340. Directory.CreateDirectory(strFilePath);
  341. }
  342. string ip = Get_IP(handle);
  343. string path = strFilePath + ip + "-" + DateTime.Now.ToString("hh_mm_ss") + ".jpg";
  344. int temp = VzClientSDK.VzLPRClient_ImageSaveToJpeg(pImgFull, path, 50);
  345. if (temp != -1)
  346. {
  347. Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "号牌机" + ip + "已拍照,图片保存于 " + strFilePath);
  348. UILogServer.ins.info("号牌机" + ip + "已拍照,图片保存于 " + strFilePath);
  349. }
  350. else
  351. {
  352. UILogServer.ins.info("图片保存失败");
  353. Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "图片保存失败");
  354. }
  355. }
  356. snapshotDevHandle = -1;
  357. }
  358. }
  359. return 0;
  360. }
  361. ///<summary>记录车牌,时间,状态信息;刷新本地entity,并且入buffer</summary>
  362. private void SetDetail(VzClientSDK.VZ_LPR_MSG_PLATE_INFO plateInformation, string strIP)
  363. {
  364. int stat = GetStatus(strIP);
  365. bool found = false;
  366. int id = 0;
  367. lock (ipIdMap)
  368. {
  369. if (!ipIdMap.ContainsKey(strIP))
  370. {
  371. try
  372. {
  373. id = Int32.Parse(ConfigurationManager.AppSettings.Get(strIP));
  374. ipIdMap.Add(strIP, id);
  375. }
  376. catch (Exception) { UILogServer.ins.error("读取号牌机编号映射失败,配置文件填写有误"); Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "读取号牌机编号映射失败"); }
  377. }
  378. }
  379. //检查设备是否存在
  380. foreach (NumberMachineNode nmn in nmMsg.data)
  381. {
  382. //相同设备
  383. if (nmn.ip == strIP)
  384. {
  385. found = true;
  386. //号牌不为空
  387. if (!(plateInformation.plate.Contains("_无_")))
  388. {
  389. nmn.SetLic(strIP, nmn.id, plateInformation.plate, DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"), GetStatus(strIP));
  390. FilterLic(strIP, (NumberMachineNode)nmn.Clone());
  391. }
  392. //号牌为空
  393. else
  394. {
  395. nmn.SetLic(strIP, nmn.id, "", "", GetStatus(strIP));
  396. }
  397. }
  398. }
  399. //新设备
  400. if (!found)
  401. {
  402. lock (ipIdMap)
  403. {
  404. if (!(plateInformation.plate.Contains("_无_")) && ipIdMap.TryGetValue(strIP, out id))
  405. {
  406. NumberMachineNode nmn = new NumberMachineNode(strIP, id, plateInformation.plate, DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"), GetStatus(strIP));
  407. NumberMachineNode nmnc = (NumberMachineNode)nmn.Clone();
  408. nmMsg.data.Add(nmnc);
  409. FilterLic(strIP, nmnc);
  410. }
  411. else
  412. {
  413. nmMsg.data.Add(new NumberMachineNode(strIP, id, "", "", GetStatus(strIP)));
  414. }
  415. }
  416. }
  417. }
  418. ///<summary>筛选号牌</summary>
  419. private void FilterLic(string ip, NumberMachineNode nmn)
  420. {
  421. Dictionary<NumberMachineNode, int> filter;
  422. //该filter不存在则创建
  423. if (!filterMap.ContainsKey(ip))
  424. {
  425. filter = new Dictionary<NumberMachineNode, int>();
  426. filterMap.Add(ip, filter);
  427. }
  428. //计数器异常
  429. else if (!filterMap.TryGetValue(ip, out filter))
  430. {
  431. return;
  432. }
  433. //filter计数
  434. int count = 0;
  435. if (filter.ContainsKey(nmn) && filter.TryGetValue(nmn, out count))//存在则数量+1
  436. {
  437. filter[nmn] = count + 1;
  438. }
  439. else//不存在则计数1
  440. {
  441. filter.Add(nmn, 1);
  442. }
  443. //计算总数
  444. filterCount = 0;
  445. Dictionary<NumberMachineNode, int>.Enumerator countEnumer = filter.GetEnumerator();
  446. while (countEnumer.MoveNext())
  447. {
  448. filterCount += countEnumer.Current.Value;
  449. }
  450. //达到计数限制,计算众数是否达标,达标则入队
  451. if (filterCount >= FILTERINGNUMBER)
  452. {
  453. lock (LicBuffer)
  454. {
  455. Dictionary<NumberMachineNode, int>.Enumerator enumer = filter.GetEnumerator();
  456. while (enumer.MoveNext())
  457. {
  458. //遍历,筛到号牌则入队
  459. if (enumer.Current.Value >= (int)(filterCount * filterRatio) && enumer.Current.Key != null && !LicBuffer.Contains(enumer.Current.Key))
  460. {
  461. if (nmMsg.aNode == null || nmMsg.aNode.LicenseNum == null || nmMsg.aNode.LicenseNum != enumer.Current.Key.LicenseNum)
  462. {
  463. NumberMachineNode node = (NumberMachineNode)enumer.Current.Key.Clone();
  464. if (ipIdMap.TryGetValue(node.ip, out node.id))
  465. {
  466. LicBuffer.Enqueue((NumberMachineNode)node.Clone());
  467. }
  468. }
  469. }
  470. };
  471. filterCount = 0;
  472. filter.Clear();
  473. }
  474. }
  475. }
  476. ///<summary>停止播放与设备句柄关联的视频</summary>
  477. private void StopPlay(int handleInput)
  478. {
  479. if (handleInput != 0)
  480. {
  481. int ret = VzClientSDK.VzLPRClient_StopRealPlay(handleInput);
  482. }
  483. }
  484. ///<summary>强制获取号牌</summary>
  485. private void ActivateSnap(int handle)
  486. {
  487. if (handle > 0)
  488. {
  489. VzClientSDK.VzLPRClient_ForceTrigger(handle);
  490. }
  491. }
  492. ///<summary>ip+port字符串转ipe</summary>
  493. private void GetIpEndPoint(string ipp, out IPEndPoint ipe)
  494. {
  495. IPAddress myIP = IPAddress.Parse(ipp.Remove(ipp.LastIndexOf(':')) + "");
  496. string myPort = ipp.Substring(ipp.IndexOf(':') + 1);
  497. ipe = new IPEndPoint(myIP, int.Parse(myPort));
  498. }
  499. ///<summary>创建新pic并记录在picNameMap</summary>
  500. private bool CreatePic(int index, out PictureBox pb)
  501. {
  502. pb = new PictureBox
  503. {
  504. Width = 230,
  505. Height = 180,
  506. AutoSize = false,
  507. Name = "PictureBox" + Convert.ToString(index)
  508. };
  509. lock (namePicMap)
  510. {
  511. if (!namePicMap.ContainsKey(pb.Name))
  512. {
  513. flowLayoutPanel1.Controls.Add(pb);
  514. namePicMap.Add(pb.Name, pb);
  515. return true;
  516. }
  517. else
  518. return false;
  519. }
  520. }
  521. ///<summary>更新设备状态</summary>
  522. private int GetStatus(string devIP)
  523. {
  524. int myHandle;
  525. byte stat = 0;
  526. if (ipHandleMap.TryGetValue(devIP, out myHandle))
  527. {
  528. VzClientSDK.VzLPRClient_IsConnected(myHandle, ref stat);
  529. return stat;
  530. }
  531. return -1;
  532. }
  533. private string Get_IP(int lprHandle)
  534. {
  535. byte[] strDecIP = new byte[32];
  536. int max_count = 32;
  537. int ret = VzClientSDK.VzLPRClient_GetDeviceIP(lprHandle, ref strDecIP[0], max_count);
  538. string strIP = System.Text.Encoding.Default.GetString(strDecIP);
  539. strIP = strIP.TrimEnd('\0');
  540. return strIP;
  541. }
  542. private bool NodeValidation(NumberMachineNode node)
  543. {
  544. return (node != null && node.ip != null && node.ip != "" && node.ip != "used" && node.LicenseNum != null && node.LicenseNum != "") ? true : false;
  545. }
  546. /// <summary>
  547. /// 系统启动
  548. /// </summary>
  549. public void Start()
  550. {
  551. Task.Factory.StartNew(() =>
  552. {
  553. isClosing = false;
  554. try
  555. {
  556. VzClientSDK.VZLPRClient_StopFindDevice();
  557. find_DeviceCB = new VzClientSDK.VZLPRC_FIND_DEVICE_CALLBACK_EX(FIND_DEVICE_CALLBACK_EX);
  558. int ret = VzClientSDK.VZLPRClient_StartFindDeviceEx(find_DeviceCB, IntPtr.Zero);
  559. }
  560. catch (Exception ex)
  561. {
  562. Debug.WriteLine(ex.ToString());
  563. }
  564. });
  565. Task.Factory.StartNew(() =>
  566. {
  567. Run();
  568. });
  569. //Task imgTest = Task.Factory.StartNew(() =>
  570. //{
  571. // while (!isClosing)
  572. // {
  573. // Command cmd = new Command
  574. // {
  575. // id = 1
  576. // };
  577. // SetMessage(cmd);
  578. // Thread.Sleep(30000);
  579. // Command cmd2 = new Command
  580. // {
  581. // id = 2
  582. // };
  583. // SetMessage(cmd2);
  584. // Thread.Sleep(30000);
  585. // }
  586. //});
  587. }
  588. /// <summary>
  589. /// 系统关闭
  590. /// </summary>
  591. public void Stop()
  592. {
  593. VzClientSDK.VZLPRClient_StopFindDevice();
  594. lock (devPicMap)
  595. {
  596. Dictionary<int, PictureBox>.Enumerator enumer = devPicMap.GetEnumerator();
  597. while (enumer.MoveNext())
  598. {
  599. if (enumer.Current.Key != 0)
  600. {
  601. StopPlay(enumer.Current.Key);
  602. VzClientSDK.VzLPRClient_Close(enumer.Current.Key);
  603. flowLayoutPanel1.Controls.Remove(enumer.Current.Value);
  604. }
  605. }
  606. isClosing = true;
  607. devPicMap.Clear();
  608. }
  609. lock (namePicMap) { namePicMap.Clear(); }
  610. lock (ipIdMap) { ipIdMap.Clear(); }
  611. lock (ipHandleMap) { ipHandleMap.Clear(); }
  612. //this.Close();
  613. }
  614. /// <summary>
  615. /// 监控线程获取号牌机信息,核心线程获取号牌信息
  616. /// </summary>
  617. public AbstractMessage GetMessage()
  618. {
  619. lock (LicBuffer)
  620. {
  621. //准备输出的数据中存在非法Node,且LicBuffer可出队产生一个合法Node,则替换该非法Node
  622. if (!NodeValidation(nmMsg.aNode))
  623. {
  624. for (int i = 0; i < LicBuffer.Count; i++)
  625. {
  626. NumberMachineNode n = LicBuffer.Dequeue();
  627. if (NodeValidation(n))
  628. {
  629. if (nmMsg.aNode != null && nmMsg.aNode.ip != null)
  630. {
  631. LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
  632. }
  633. nmMsg.aNode = n;
  634. break;
  635. }
  636. else
  637. {
  638. LicBuffer.Enqueue(n);
  639. }
  640. }
  641. //遍历licBuffer后仍不合法,则丢入队列,将node置为null
  642. if (!NodeValidation(nmMsg.aNode))
  643. {
  644. if (nmMsg.aNode != null && nmMsg.aNode.ip != null)
  645. {
  646. LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
  647. }
  648. nmMsg.aNode = null;
  649. }
  650. }
  651. }
  652. return nmMsg;
  653. }
  654. /// <summary>
  655. /// 一次停车流程完成时调用该方法,发送已完成车辆号牌信息
  656. /// </summary>
  657. /// <param name="message">已完成车辆的号牌相关信息存于message的aNode中,用于标记需清空的号牌</param>
  658. public void SetMessage(AbstractMessage message)
  659. {
  660. if (message.GetType().Equals(typeof(NumberMachineMessage)))
  661. {
  662. NumberMachineNode n = ((NumberMachineMessage)message).aNode;
  663. lock (LicBuffer)
  664. {
  665. //输入号牌格式无误
  666. if (n != null && n.ip != null && n.ip == "")
  667. {
  668. //与类成员变量中aNode号牌相同,将其ip复位表示已使用,重新入队等待清除
  669. if (nmMsg != null && nmMsg.aNode != null && nmMsg.aNode.LicenseNum == n.LicenseNum)
  670. {
  671. nmMsg.aNode.ip = "";
  672. LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
  673. nmMsg.aNode = null;
  674. }
  675. //搜索号牌队列,将相应号牌置空,准备清除
  676. else
  677. {
  678. for (int i = 0; i < LicBuffer.Count; i++)
  679. {
  680. NumberMachineNode temp = LicBuffer.Dequeue();
  681. //已匹配上,ip置空
  682. if (temp.LicenseNum == n.LicenseNum)
  683. {
  684. temp.ip = "";
  685. LicBuffer.Enqueue(temp);
  686. break;
  687. }
  688. LicBuffer.Enqueue(temp);
  689. }
  690. }
  691. }
  692. }
  693. }
  694. //传入异常号牌,根据ip找到handle,改变snapshotDevHandle的值在回调函数中截图
  695. if (message.GetType().Equals(typeof(Command)))
  696. {
  697. Command cmd = (Command)message;
  698. if (cmd != null && cmd.id != 0)
  699. {
  700. lock (ipIdMap)
  701. {
  702. Dictionary<string, int>.Enumerator enumerator = ipIdMap.GetEnumerator();
  703. while (enumerator.MoveNext())
  704. {
  705. // if (enumerator.Current.Value == cmd.id && ipHandleMap.TryGetValue(enumerator.Current.Key, out int handle))
  706. int handle = 0;
  707. if (enumerator.Current.Value == cmd.id && ipHandleMap.TryGetValue(enumerator.Current.Key, out handle))
  708. {
  709. snapshotDevHandle = handle;
  710. break;
  711. }
  712. }
  713. }
  714. }
  715. else
  716. {
  717. UILogServer.ins.error("参数错误,图片未保存");
  718. Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "参数错误,图片未保存");
  719. }
  720. }
  721. }
  722. }
  723. public class NumMachineManager : IEquipments
  724. {
  725. public static NumMachineLinker ins;
  726. public AbstractMessage GetMessage()
  727. {
  728. if (ins != null)
  729. {
  730. return ins.GetMessage();
  731. }
  732. return null;
  733. }
  734. public void SetMessage(AbstractMessage message)
  735. {
  736. if (ins != null)
  737. {
  738. ins.SetMessage(message);
  739. }
  740. }
  741. public void Start()
  742. {
  743. Task.Factory.StartNew(() =>
  744. {
  745. ins = new NumMachineLinker();
  746. Task.Factory.StartNew(() =>
  747. {
  748. ins.Start();
  749. //ins.Bounds = new Rectangle(0, 0, 0, 0);
  750. //ins.ShowDialog();
  751. });
  752. //ins.WindowState = FormWindowState.Minimized;
  753. ins.Hide();
  754. });
  755. }
  756. public void Stop()
  757. {
  758. Task.Factory.StartNew(() =>
  759. {
  760. ins.Close();
  761. ins.Stop();
  762. });
  763. }
  764. }
  765. }