NumMachine.cs 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. using centralController;
  2. using parkMonitor.entity;
  3. using parkMonitor.LOG;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Configuration;
  7. using System.Diagnostics;
  8. using System.Drawing;
  9. using System.IO;
  10. using System.Net;
  11. using System.Runtime.InteropServices;
  12. using System.Threading;
  13. using System.Threading.Tasks;
  14. using System.Windows.Forms;
  15. using VzClientSDKDemo;
  16. namespace NumMachine
  17. {
  18. /// <summary>
  19. /// 号牌机通信类
  20. /// </summary>
  21. public partial class NumMachineLinker : INumMachineLinker
  22. {
  23. /// <summary>
  24. /// 刷新时间间隔与个数
  25. /// </summary>
  26. public const int REFRESHINGTIME = 500, FILTERINGNUMBER = 5;
  27. ///<summary>通过设备句柄访问pic;链接时add,系统关闭时remove</summary>
  28. private static Dictionary<int, IntPtr> devPicMap = new Dictionary<int, IntPtr>();
  29. ///<summary>通过名字获取pic对象;创建pic时add,系统关闭remove</summary>
  30. private static Dictionary<string, IntPtr> namePicMap = new Dictionary<string, IntPtr>();
  31. ///<summary>通过ip获取设备id;产生ip时创建</summary>
  32. private static Dictionary<string, int> ipIdMap = new Dictionary<string, int>();
  33. ///<summary>通过ip获取设备句柄;产生句柄时创建</summary>
  34. private static Dictionary<string, int> ipHandleMap = new Dictionary<string, int>();
  35. /// <summary>句柄到号牌回调映射</summary>
  36. private static Dictionary<int, VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK> handleCallbackMap = new Dictionary<int, VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK>();
  37. ///<summary>号牌队列</summary>
  38. private static Queue<NumberMachineNode> LicBuffer = new Queue<NumberMachineNode>();
  39. ///<summary>计数Map</summary>
  40. private static Dictionary<string, Dictionary<NumberMachineNode, int>> filterMap = new Dictionary<string, Dictionary<NumberMachineNode, int>>();
  41. /// <summary> 终端编号与当前号牌映射表</summary>
  42. private static Dictionary<int, string> idLicenseMap = new Dictionary<int, string>();
  43. /// <summary>号牌机编号与激活计数</summary>
  44. private Dictionary<int, int> idCountMap = new Dictionary<int, int>();
  45. /// <summary>筛选计数</summary>
  46. private static int filterCount = 0;
  47. private static double filterRatio = 0.7;
  48. /// <summary>系统关闭</summary>
  49. private static bool isClosing = false;
  50. /// <summary>开启拍照的设备</summary>
  51. private static int snapshotDevHandle = -1;
  52. /// <summary>允许无号牌时拍照</summary>
  53. private static bool enableEmptySnapshot = true;
  54. private static NumberMachineMessage nmMsg = new NumberMachineMessage();
  55. private static VzClientSDK.VZLPRC_FIND_DEVICE_CALLBACK_EX find_DeviceCB = null;
  56. private const int MSG_PLATE_INFO = 0x901;
  57. private const int MSG_DEVICE_INFO = 0x902;
  58. /// <summary>
  59. /// 用于消息传递机制
  60. /// </summary>
  61. //public static IntPtr hwndMain;
  62. /// <summary>
  63. /// 定义时钟委托
  64. /// </summary>
  65. private delegate void SetDateTime();
  66. private static IntPtr flowLayoutPanel1;
  67. private static ToolStripStatusLabel timeLabel;
  68. /// <summary>
  69. /// 号牌机类构造函数
  70. /// </summary>
  71. public NumMachineLinker(IntPtr flpHandle)
  72. {
  73. //Control.CheckForIllegalCrossThreadCalls = false;
  74. //Thread thread = new Thread(new ThreadStart(DateTimeInfo));
  75. //thread.IsBackground = true;
  76. //thread.Start(); //显示当前时间
  77. flowLayoutPanel1 = flpHandle;
  78. //timeLabel = new ToolStripStatusLabel();
  79. try
  80. {
  81. VzClientSDK.VzLPRClient_Setup();
  82. filterRatio = Double.Parse(ConfigurationManager.AppSettings.Get("filterRatio"));
  83. }
  84. catch (Exception e) { Console.WriteLine(e.Message + ",号牌机配置文件异常"); }
  85. //m_sAppPath = System.IO.Directory.GetCurrentDirectory();
  86. }
  87. private void DateTimeInfo()
  88. {
  89. try
  90. {
  91. while (!isClosing)
  92. {
  93. SetDateTime setDate = new SetDateTime(
  94. delegate
  95. {
  96. timeLabel.Text = DateTime.Now.ToString();
  97. });
  98. setDate();
  99. Thread.Sleep(1000);
  100. }
  101. // ReSharper disable once FunctionNeverReturns
  102. }
  103. catch (Exception e) { Debug.Print(e.StackTrace); }
  104. }
  105. //******************************************************************************************************************
  106. private void UpdateStatus(NumberMachineNode nmn)
  107. {
  108. //提示次数计数
  109. int count = 0;
  110. while (!isClosing)
  111. {
  112. if (GetStatus(nmn.ip) == 1)
  113. {
  114. nmn.status = EnumNumberMachineStatus.Normal;
  115. count = 0;
  116. }
  117. else
  118. {
  119. count++;
  120. //号牌机断线写日志
  121. nmn.status = EnumNumberMachineStatus.Offline;
  122. if (count == 1)
  123. {
  124. Console.WriteLine("正在与ip为 " + nmn.ip + " 的号牌机 进行连接。");
  125. }
  126. else if (count == 30)
  127. {
  128. nmMsg.data.Remove(nmn);
  129. }
  130. Thread.Sleep(10000);
  131. }
  132. }
  133. }
  134. private void Run()
  135. {
  136. try
  137. {
  138. while (!isClosing)
  139. {
  140. Thread.Sleep(REFRESHINGTIME);
  141. ////定时更新号牌
  142. //lock (ipHandleMap)
  143. //{
  144. // Dictionary<string, int>.Enumerator HandleEnumer = ipHandleMap.GetEnumerator();
  145. // while (HandleEnumer.MoveNext())
  146. // {
  147. // ActivateSnap(HandleEnumer.Current.Value);
  148. // }
  149. //}
  150. ////读取设备ip与id映射关系
  151. //lock (ipHandleMap)
  152. //{
  153. // Dictionary<string, int>.Enumerator ipEnumer = ipHandleMap.GetEnumerator();
  154. // while (ipEnumer.MoveNext())
  155. // {
  156. // //映射关系不存在则读取配置文件
  157. // lock (ipIdMap)
  158. // {
  159. // if (ipEnumer.Current.Key != null && !ipIdMap.ContainsKey(ipEnumer.Current.Key))
  160. // {
  161. // try
  162. // {
  163. // int id = Int32.Parse(ConfigurationManager.AppSettings.Get(ipEnumer.Current.Key));
  164. // ipIdMap.Add(ipEnumer.Current.Key, id);
  165. // idCountMap.Add(id, FILTERINGNUMBER);
  166. // }
  167. // catch (Exception) { Console.WriteLine("读取号牌机编号映射失败,配置文件填写有误"); }
  168. // }
  169. // }
  170. // }
  171. //}
  172. lock (LicBuffer)
  173. {
  174. //删除已停好车的号牌
  175. for (int i = 0; i < LicBuffer.Count; i++)
  176. {
  177. NumberMachineNode n = LicBuffer.Dequeue();
  178. if (n.ip != "")
  179. {
  180. LicBuffer.Enqueue((NumberMachineNode)n.Clone());
  181. }
  182. }
  183. }
  184. }
  185. }
  186. catch (Exception ex)
  187. {
  188. Debug.WriteLine(ex.ToString());
  189. }
  190. }
  191. ///<summary>寻找设备回调函数</summary>
  192. private void FIND_DEVICE_CALLBACK_EX(string pStrDevName, string pStrIPAddr, ushort usPort1, ushort usPort2, uint SL, uint SH, string netmask, string gateway, IntPtr pUserData)
  193. {
  194. string pStrDev = pStrIPAddr.ToString() + ":" + usPort1.ToString();
  195. string serialNO = SL.ToString() + ":" + SH.ToString() + ":" + netmask + ":" + gateway;
  196. VzClientSDK.VZ_LPR_DEVICE_INFO device_info = new VzClientSDK.VZ_LPR_DEVICE_INFO();
  197. device_info.device_ip = pStrDev;
  198. device_info.serial_no = serialNO;
  199. DeviceLink(pStrDev, serialNO);
  200. }
  201. ///<summary>与设备连接,启动更新设备状态线程,输出视频</summary>
  202. private void DeviceLink(string pStrDev, string serialNO)
  203. {
  204. IPEndPoint ipe;
  205. GetIpEndPoint(pStrDev, out ipe);
  206. string ip = ipe.Address.ToString();
  207. if (ipHandleMap.ContainsKey(ip))
  208. {
  209. //MessageBox.Show("设备已分配句柄");
  210. return;
  211. }
  212. int handle = 0;
  213. handle = VzClientSDK.VzLPRClient_Open(ip, (ushort)80, "admin", "admin");
  214. if (handle == 0)
  215. {
  216. return;
  217. }
  218. VzClientSDK.VzLPRClient_SetVideoEncodeType(handle, 0);
  219. //将句柄加入
  220. lock (ipHandleMap)
  221. {
  222. ipHandleMap.Add(ip, handle);
  223. }
  224. //MessageBox.Show("摄像头打开成功");
  225. lock (handleCallbackMap)
  226. {
  227. handleCallbackMap.Add(handle, null);
  228. }
  229. int id = 0;
  230. //读到设备则添加id映射并初始化号牌计数器
  231. lock (ipIdMap)
  232. {
  233. if (!ipIdMap.ContainsKey(ip))
  234. {
  235. try
  236. {
  237. id = Int32.Parse(ConfigurationManager.AppSettings.Get(ip));
  238. ipIdMap.Add(ip, id);
  239. idCountMap.Add(id, FILTERINGNUMBER);
  240. GetLicensePlate(id);
  241. }
  242. catch (Exception) { Console.WriteLine("读取号牌机编号映射失败,配置文件填写有误"); }
  243. }
  244. }
  245. //找到设备,加入list
  246. NumberMachineNode node = new NumberMachineNode(ip, id, "", "", 1);
  247. nmMsg.data.Add(node);
  248. Task.Factory.StartNew(() =>
  249. {
  250. UpdateStatus(node);
  251. });
  252. //链接句柄到新PictureBox
  253. VideoOutput(handle);
  254. }
  255. ///<summary>视频输出</summary>
  256. private void VideoOutput(int handle)
  257. {
  258. try
  259. {
  260. lock (devPicMap)
  261. {
  262. lock (handleCallbackMap)
  263. {
  264. //存在设备则复位并在原pic上输出
  265. if (devPicMap.ContainsKey(handle))
  266. {
  267. VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, null, IntPtr.Zero, 0);
  268. IntPtr pic;
  269. if (devPicMap.TryGetValue(handle, out pic) && handleCallbackMap.ContainsKey(handle))
  270. {
  271. int playHandle = VzClientSDK.VzLPRClient_StartRealPlay(handle, pic);
  272. // 设置车牌识别结果回调
  273. handleCallbackMap[handle] = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
  274. VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, handleCallbackMap[handle], IntPtr.Zero, 1);
  275. //m_PlateResultCB = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
  276. //VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, m_PlateResultCB, IntPtr.Zero, 1);
  277. //VzClientSDK.VzLPRClient_StopRealPlay(handle);
  278. }
  279. }
  280. else//否则找一个空位加pic
  281. {
  282. for (int i = 0; i < 20; i++)
  283. {
  284. string str = "PictureBox" + Convert.ToString(i);
  285. //该名称对应控件不存在,则创建并链接pic
  286. lock (namePicMap)
  287. {
  288. if (!namePicMap.ContainsKey(str) && handleCallbackMap.ContainsKey(handle))
  289. {
  290. IntPtr pic;
  291. if (CreatePic(i, handle, out pic))
  292. {
  293. devPicMap.Add(handle, pic);
  294. //ipIdMap.Add(Get_IP(handle), i);
  295. VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, null, IntPtr.Zero, 0);
  296. //Console.WriteLine(handle+","+pic.ToString());
  297. int playHandle = VzClientSDK.VzLPRClient_StartRealPlay(handle, pic);
  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 e)
  314. {
  315. Debug.WriteLine(e.Message + ",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. Console.WriteLine("号牌机" + ip + "已拍照,图片保存于 " + strFilePath);
  348. }
  349. else
  350. {
  351. Console.WriteLine("图片保存失败");
  352. }
  353. }
  354. snapshotDevHandle = -1;
  355. }
  356. }
  357. return 0;
  358. }
  359. ///<summary>记录车牌,时间,状态信息;刷新本地entity,并且入buffer</summary>
  360. private void SetDetail(VzClientSDK.VZ_LPR_MSG_PLATE_INFO plateInformation, string strIP)
  361. {
  362. int stat = GetStatus(strIP);
  363. bool found = false;
  364. int id = 0;
  365. //检查设备是否存在
  366. foreach (NumberMachineNode nmn in nmMsg.data)
  367. {
  368. //相同设备
  369. if (nmn.ip == strIP)
  370. {
  371. found = true;
  372. //号牌不为空
  373. if (!(plateInformation.plate.Contains("_无_")))
  374. {
  375. //Log.WriteLog(LogType.process, LogFile.INFO, nmn.id + "收到号牌回调信息: [" + plateInformation.plate + "]");
  376. nmn.SetLic(strIP, nmn.id, plateInformation.plate, DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"), GetStatus(strIP));
  377. FilterLic(strIP, (NumberMachineNode)nmn.Clone());
  378. }
  379. //号牌为空
  380. else
  381. {
  382. nmn.SetLic(strIP, nmn.id, "", "", GetStatus(strIP));
  383. FilterLic(strIP, null);
  384. }
  385. }
  386. }
  387. //新设备
  388. if (!found)
  389. {
  390. lock (ipIdMap)
  391. {
  392. if (!(plateInformation.plate.Contains("_无_")) && ipIdMap.TryGetValue(strIP, out id))
  393. {
  394. NumberMachineNode nmn = new NumberMachineNode(strIP, id, plateInformation.plate, DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"), GetStatus(strIP));
  395. NumberMachineNode nmnc = (NumberMachineNode)nmn.Clone();
  396. nmMsg.data.Add(nmnc);
  397. FilterLic(strIP, nmnc);
  398. }
  399. else
  400. {
  401. nmMsg.data.Add(new NumberMachineNode(strIP, id, "", "", GetStatus(strIP)));
  402. FilterLic(strIP, null);
  403. }
  404. }
  405. }
  406. }
  407. ///<summary>筛选号牌</summary>
  408. private void FilterLic(string ip, NumberMachineNode nmn)
  409. {
  410. int id = 0, activeCount = 0;
  411. if (ipIdMap.TryGetValue(ip, out id) && idCountMap.TryGetValue(id, out activeCount))// && activeCount < FILTERINGNUMBER)
  412. {
  413. Dictionary<NumberMachineNode, int> filter;
  414. //该filter不存在则创建
  415. if (!filterMap.ContainsKey(ip))
  416. {
  417. filter = new Dictionary<NumberMachineNode, int>();
  418. filterMap.Add(ip, filter);
  419. }
  420. else if (!filterMap.TryGetValue(ip, out filter))//计数器异常
  421. {
  422. return;
  423. }
  424. else if (activeCount == 0) //刚接到拍摄命令
  425. {
  426. filter.Clear();
  427. }
  428. //激活次数统计
  429. idCountMap[id] = activeCount + 1;
  430. //filter计数
  431. int count = 0;
  432. if (nmn == null)
  433. {
  434. if (activeCount >= FILTERINGNUMBER - 1)
  435. {
  436. //UILogServer.ins.error("本轮未扫描到号牌,请重新点击按钮停车");
  437. //string context = System.DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ":" + "号牌未扫描到,请重发指令";
  438. //string sql = "insert into messagequeue(userID,context,messageType) values (1,'" + context + "',1)";
  439. //List<string> strs = new List<string>();
  440. //strs.Add(sql);
  441. //DBOperation.InsertMessageQueue(EntityForCore.remoteBQ, strs);
  442. }
  443. return;
  444. }
  445. else if (filter.ContainsKey(nmn) && filter.TryGetValue(nmn, out count))//存在则数量+1
  446. {
  447. filter[nmn] = count + 1;
  448. }
  449. else//不存在则计数1
  450. {
  451. filter.Add(nmn, 1);
  452. }
  453. //计算总数
  454. filterCount = 0;
  455. Dictionary<NumberMachineNode, int>.Enumerator countEnumer = filter.GetEnumerator();
  456. while (countEnumer.MoveNext())
  457. {
  458. filterCount += countEnumer.Current.Value;
  459. }
  460. //达到计数限制,计算总数是否达标,达标则入队
  461. if (filterCount >= FILTERINGNUMBER)
  462. {
  463. lock (LicBuffer)
  464. {
  465. Dictionary<NumberMachineNode, int>.Enumerator enumer = filter.GetEnumerator();
  466. int maxCount = 0;
  467. NumberMachineNode node = null;
  468. while (enumer.MoveNext())
  469. {
  470. ////遍历,计数达标且队列中无此号牌
  471. //Log.WriteLog(LogType.process, LogFile.INFO, "filter中号牌:" + enumer.Current.Key.LicenseNum + ", 个数:" + enumer.Current.Value);
  472. //if (enumer.Current.Value >= (int)(filterCount * filterRatio) && enumer.Current.Key != null && !LicBuffer.Contains(enumer.Current.Key))
  473. //找到最大计数及相应号牌信息
  474. if (enumer.Current.Value >= maxCount && enumer.Current.Key != null)// && !LicBuffer.Contains(enumer.Current.Key))
  475. {
  476. ////输出节点为空或与该号牌不同
  477. //if (nmMsg.aNode == null || nmMsg.aNode.LicenseNum == null || nmMsg.aNode.LicenseNum != enumer.Current.Key.LicenseNum)
  478. //{
  479. maxCount = enumer.Current.Value;
  480. node = (NumberMachineNode)enumer.Current.Key.Clone();
  481. //Log.WriteLog(LogType.process, LogFile.INFO, "筛出号牌:" + node);
  482. //}
  483. }
  484. }
  485. if (node != null)
  486. //if (node != null && ipIdMap.TryGetValue(node.ip, out node.id))
  487. {
  488. //LicBuffer.Enqueue((NumberMachineNode)node.Clone());
  489. LicBuffer.Enqueue(node);
  490. Log.WriteLog(LogType.process, LogFile.INFO, "号牌入队:" + node.LicenseNum);
  491. if (Monitor.Monitor.allInOneMachine != null)
  492. {
  493. if (Monitor.Monitor.allInOneMachine.boardList.Count >= id && node.LicenseNum != "")
  494. {
  495. Monitor.Monitor.allInOneMachine.boardList[id - 1].UpdateText("车辆"+ node.LicenseNum+"入场", 30, 2);
  496. //Monitor.Monitor.allInOneMachine.boardList[id - 1].UpdateArrow(-1, 2, 0);
  497. }
  498. //Monitor.Monitor.allInOneMachine.DispForAWhile(2, node.LicenseNum, 25, 1, node.LicenseNum + ",入场");
  499. //Monitor.Monitor.allInOneMachine.DispForAWhile(3, "号牌机编号:" + node.id, 25, 1, "");
  500. }
  501. }
  502. }
  503. //filterCount = 0;
  504. filter.Clear();
  505. }
  506. }
  507. }
  508. ///<summary>停止播放与设备句柄关联的视频</summary>
  509. private void StopPlay(int handleInput)
  510. {
  511. if (handleInput != 0)
  512. {
  513. int ret = VzClientSDK.VzLPRClient_StopRealPlay(handleInput);
  514. }
  515. }
  516. ///<summary>强制获取号牌</summary>
  517. private void ActivateSnap(int handle)
  518. {
  519. if (handle > 0)
  520. {
  521. VzClientSDK.VzLPRClient_ForceTrigger(handle);
  522. }
  523. }
  524. ///<summary>ip+port字符串转ipe</summary>
  525. private void GetIpEndPoint(string ipp, out IPEndPoint ipe)
  526. {
  527. IPAddress myIP = IPAddress.Parse(ipp.Remove(ipp.LastIndexOf(':')) + "");
  528. string myPort = ipp.Substring(ipp.IndexOf(':') + 1);
  529. ipe = new IPEndPoint(myIP, int.Parse(myPort));
  530. }
  531. ///<summary>创建新pic并记录在picNameMap</summary>
  532. private bool CreatePic(int index, int handle, out IntPtr pic)
  533. {
  534. pic = IntPtr.Zero;
  535. PictureBox pb = new PictureBox
  536. {
  537. Width = 179,
  538. Height = 127,
  539. //Bounds = new System.Drawing.Rectangle(0, 0, 230, 180),
  540. Name = "PictureBox" + Convert.ToString(index)
  541. };
  542. lock (namePicMap)
  543. {
  544. if (!namePicMap.ContainsKey(pb.Name))
  545. {
  546. PictureBox temp = pb;
  547. IntPtr picHandle = IntPtr.Zero;
  548. try
  549. {
  550. Control flp = Control.FromHandle(flowLayoutPanel1);
  551. //创建tableLayoutPanel显示号牌机信息
  552. string ip = Get_IP(handle);
  553. int id = 0;
  554. ipIdMap.TryGetValue(ip, out id);
  555. TableLayoutPanel tlp = new TableLayoutPanel()
  556. {
  557. Name = "tlp" + Convert.ToString(id),
  558. ColumnCount = 1,
  559. RowCount = 2,
  560. Size = new Size(185, 168),
  561. TabIndex = 3,
  562. };
  563. Label lb_numMachine = new Label()
  564. {
  565. Text = "编号" + id + "\nIP:" + ip,
  566. TextAlign = ContentAlignment.MiddleCenter,
  567. Size = new Size(179, 27)
  568. };
  569. //temp.Dock = DockStyle.Bottom;
  570. //lb_numMachine.Dock = DockStyle.Top;
  571. tlp.Controls.Add(temp, 0, 1);
  572. tlp.Controls.Add(lb_numMachine, 0, 0);
  573. tlp.RowStyles.Add(new RowStyle(SizeType.Percent, 20.00f));
  574. tlp.RowStyles.Add(new RowStyle(SizeType.Percent, 80.00f));
  575. temp.Click += delegate (object o, EventArgs e)
  576. {
  577. //Console.WriteLine(((PictureBox)o).TopLevelControl.Name+","+e.ToString());
  578. try
  579. {
  580. if (((PictureBox)o).TopLevelControl.Name != "FormNumberMachinePreview")
  581. {
  582. FormNumberMachinePreview form = new FormNumberMachinePreview("编号" + id + ", IP:" + ip, temp, tlp);
  583. form.ShowDialog();
  584. }
  585. }
  586. catch { }
  587. };
  588. //Control.FromHandle(flowLayoutPanel1).Controls.Add(temp);
  589. if (flp.InvokeRequired)
  590. {
  591. flp.Invoke(new Action(() =>
  592. {
  593. flp.Controls.Add(tlp);
  594. //for (int i = 0; i < 12; i++)
  595. //{
  596. // TableLayoutPanel tlpTemp = new TableLayoutPanel();
  597. // tlpTemp.Width = 200;
  598. // tlpTemp.Height = 200;
  599. // flp.Controls.Add(tlpTemp);
  600. //}
  601. Control.ControlCollection flpCC = flp.Controls;
  602. try
  603. {
  604. int rows = (int)Math.Sqrt(flp.Controls.Count + 1);
  605. int columns = (int)(flp.Controls.Count * 1.0 / rows + 1);
  606. //tlp.Width = (int)(flp.Width * 1.0 / (columns * 1.05));
  607. //tlp.Height = (int)(flp.Height * 1.0 / (rows * 1.05));
  608. for (int i = 0; i < flpCC.Count; i++)
  609. {
  610. flpCC[i].Width = (int)(flp.Width * 1.0 / (columns * 1.1));
  611. flpCC[i].Height = (int)(flp.Height * 1.0 / (rows * 1.15));
  612. Console.WriteLine("flp::" + flp.Width + "," + flp.Height);
  613. //Console.WriteLine("tlp--"+flpCC[i].Width + "," + flpCC[i].Height);
  614. Control.ControlCollection tlpCC = flpCC[i].Controls;
  615. if (tlpCC.Count == 2)
  616. {
  617. tlpCC[0].Width = (int)(flpCC[i].Width * 0.95);
  618. tlpCC[0].Height = (int)(flpCC[i].Height * 0.79);
  619. tlpCC[1].Width = (int)(flpCC[i].Width * 0.95);
  620. tlpCC[1].Height = (int)(flpCC[i].Height * 0.20);
  621. }
  622. }
  623. lb_numMachine.BackColor = Color.BurlyWood;
  624. }
  625. catch (Exception ex) { Console.WriteLine(ex.Message); }
  626. picHandle = temp.Handle;
  627. }));
  628. }
  629. else
  630. {
  631. flp.Controls.Add(pb);
  632. picHandle = temp.Handle;
  633. }
  634. }
  635. catch (Exception e) { Console.WriteLine(e.Message); }
  636. namePicMap.Add(pb.Name, picHandle);
  637. pic = picHandle;
  638. //Console.WriteLine(picHandle.ToString());
  639. return true;
  640. }
  641. else
  642. return false;
  643. }
  644. }
  645. ///<summary>更新设备状态</summary>
  646. private int GetStatus(string devIP)
  647. {
  648. int myHandle;
  649. byte stat = 0;
  650. try
  651. {
  652. if (ipHandleMap.TryGetValue(devIP, out myHandle))
  653. {
  654. VzClientSDK.VzLPRClient_IsConnected(myHandle, ref stat);
  655. return stat;
  656. }
  657. }
  658. catch { Console.WriteLine("获取设备状态异常"); }
  659. return -1;
  660. }
  661. private string Get_IP(int lprHandle)
  662. {
  663. byte[] strDecIP = new byte[32];
  664. int max_count = 32;
  665. int ret = VzClientSDK.VzLPRClient_GetDeviceIP(lprHandle, ref strDecIP[0], max_count);
  666. string strIP = System.Text.Encoding.Default.GetString(strDecIP);
  667. strIP = strIP.TrimEnd('\0');
  668. return strIP;
  669. }
  670. private bool NodeValidation(NumberMachineNode node)
  671. {
  672. return (node != null && node.ip != null && node.ip != "" && node.ip != "used" && node.LicenseNum != null && node.LicenseNum != "") ? true : false;
  673. }
  674. /// <summary>
  675. /// 更新终端编号与号牌映射表
  676. /// </summary>
  677. /// <param name="license"></param>
  678. /// <param name="clearBuffer"></param>
  679. private void UpdateIdLicenseMap(bool clearBuffer)
  680. {
  681. NumberMachineNode node = null;
  682. lock (LicBuffer)
  683. {
  684. idLicenseMap.Clear();
  685. for (int i = 0; i < LicBuffer.Count; i++)
  686. {
  687. node = LicBuffer.Dequeue();
  688. if (node != null)
  689. {
  690. if (!idLicenseMap.ContainsKey(node.id))
  691. {
  692. idLicenseMap.Add(node.id, node.LicenseNum);
  693. }
  694. else
  695. {
  696. idLicenseMap[node.id] = node.LicenseNum;
  697. }
  698. }
  699. if (!clearBuffer)
  700. LicBuffer.Enqueue(node);
  701. }
  702. }
  703. }
  704. /// <summary>
  705. /// 系统启动
  706. /// </summary>
  707. public void Start()
  708. {
  709. Task.Factory.StartNew(() =>
  710. {
  711. isClosing = false;
  712. try
  713. {
  714. VzClientSDK.VZLPRClient_StopFindDevice();
  715. find_DeviceCB = new VzClientSDK.VZLPRC_FIND_DEVICE_CALLBACK_EX(FIND_DEVICE_CALLBACK_EX);
  716. int ret = VzClientSDK.VZLPRClient_StartFindDeviceEx(find_DeviceCB, IntPtr.Zero);
  717. }
  718. catch (Exception ex)
  719. {
  720. Debug.WriteLine(ex.ToString());
  721. }
  722. });
  723. //应答模式下号牌机不需要清除号牌
  724. //Task.Factory.StartNew(() =>
  725. //{
  726. // Run();
  727. //});
  728. //Task imgTest = Task.Factory.StartNew(() =>
  729. //{
  730. // while (!isClosing)
  731. // {
  732. // Command cmd = new Command
  733. // {
  734. // id = 1
  735. // };
  736. // SetMessage(cmd);
  737. // Thread.Sleep(30000);
  738. // Command cmd2 = new Command
  739. // {
  740. // id = 2
  741. // };
  742. // SetMessage(cmd2);
  743. // Thread.Sleep(30000);
  744. // }
  745. //});
  746. }
  747. /// <summary>
  748. /// 系统关闭
  749. /// </summary>
  750. public void Stop()
  751. {
  752. try
  753. {
  754. VzClientSDK.VZLPRClient_StopFindDevice();
  755. }catch(Exception e)
  756. {
  757. }
  758. lock (devPicMap)
  759. {
  760. Dictionary<int, IntPtr>.Enumerator enumer = devPicMap.GetEnumerator();
  761. while (enumer.MoveNext())
  762. {
  763. if (enumer.Current.Key != 0)
  764. {
  765. StopPlay(enumer.Current.Key);
  766. VzClientSDK.VzLPRClient_Close(enumer.Current.Key);
  767. //flowLayoutPanel1.Controls.Remove(enumer.Current.Value);
  768. }
  769. }
  770. isClosing = true;
  771. devPicMap.Clear();
  772. }
  773. lock (namePicMap) { namePicMap.Clear(); }
  774. lock (ipIdMap) { ipIdMap.Clear(); }
  775. lock (ipHandleMap) { ipHandleMap.Clear(); }
  776. //this.Close();
  777. }
  778. /// <summary>
  779. /// 监控线程获取号牌机信息,核心线程获取号牌信息
  780. /// </summary>
  781. public AbstractMessage GetMessage()
  782. {
  783. //lock (LicBuffer)
  784. //{
  785. // //准备输出的数据中存在非法Node,且LicBuffer可出队产生一个合法Node,则替换该非法Node
  786. // if (!NodeValidation(nmMsg.aNode))
  787. // {
  788. // for (int i = 0; i < LicBuffer.Count; i++)
  789. // {
  790. // NumberMachineNode n = LicBuffer.Dequeue();
  791. // if (NodeValidation(n))
  792. // {
  793. // if (nmMsg.aNode != null && nmMsg.aNode.ip != null)
  794. // {
  795. // LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
  796. // }
  797. // nmMsg.aNode = n;
  798. // break;
  799. // }
  800. // else
  801. // {
  802. // LicBuffer.Enqueue(n);
  803. // }
  804. // }
  805. // //遍历licBuffer后仍不合法,则丢入队列,将node置为null
  806. // if (!NodeValidation(nmMsg.aNode))
  807. // {
  808. // if (nmMsg.aNode != null && nmMsg.aNode.ip != null)
  809. // {
  810. // LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
  811. // }
  812. // nmMsg.aNode = null;
  813. // }
  814. // }
  815. //}
  816. return nmMsg;
  817. }
  818. /// <summary>
  819. /// 一次停车流程完成时调用该方法,发送已完成车辆号牌信息
  820. /// </summary>
  821. /// <param name="message">已完成车辆的号牌相关信息存于message的aNode中,用于标记需清空的号牌</param>
  822. public void SetMessage(AbstractMessage message)
  823. {
  824. if (message.GetType().Equals(typeof(NumberMachineMessage)))
  825. {
  826. NumberMachineNode n = ((NumberMachineMessage)message).aNode;
  827. lock (LicBuffer)
  828. {
  829. //输入号牌格式无误
  830. if (n != null && n.ip != null && n.ip == "")
  831. {
  832. //与类成员变量中aNode号牌相同,将其ip复位表示已使用,重新入队等待清除
  833. if (nmMsg != null && nmMsg.aNode != null && nmMsg.aNode.LicenseNum == n.LicenseNum)
  834. {
  835. nmMsg.aNode.ip = "";
  836. LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
  837. nmMsg.aNode = null;
  838. }
  839. //搜索号牌队列,将相应号牌置空,准备清除
  840. else
  841. {
  842. for (int i = 0; i < LicBuffer.Count; i++)
  843. {
  844. NumberMachineNode temp = LicBuffer.Dequeue();
  845. //已匹配上,ip置空
  846. if (temp.LicenseNum == n.LicenseNum)
  847. {
  848. temp.ip = "";
  849. LicBuffer.Enqueue(temp);
  850. break;
  851. }
  852. LicBuffer.Enqueue(temp);
  853. }
  854. }
  855. }
  856. }
  857. }
  858. if (message.GetType().Equals(typeof(Command)))
  859. {
  860. Command cmd = (Command)message;
  861. if (cmd != null && cmd.id != 0)
  862. {
  863. //拍照功能根据ip找到handle,改变snapshotDevHandle的值在回调函数中截图
  864. lock (ipIdMap)
  865. {
  866. Dictionary<string, int>.Enumerator enumerator = ipIdMap.GetEnumerator();
  867. while (enumerator.MoveNext())
  868. {
  869. // if (enumerator.Current.Value == cmd.id && ipHandleMap.TryGetValue(enumerator.Current.Key, out int handle))
  870. int handle = 0;
  871. if (enumerator.Current.Value == cmd.id && ipHandleMap.TryGetValue(enumerator.Current.Key, out handle))
  872. {
  873. snapshotDevHandle = handle;
  874. break;
  875. }
  876. }
  877. }
  878. }
  879. else
  880. {
  881. Console.WriteLine("参数错误,图片未保存");
  882. }
  883. }
  884. }
  885. /// <summary>
  886. /// 根据id获取号牌
  887. /// </summary>
  888. /// <param name="id"></param>
  889. /// <returns></returns>
  890. public string GetLicensePlate(int id)
  891. {
  892. string license = "空";
  893. NumberMachineNode node = null;
  894. //Task.Factory.StartNew(() =>
  895. //{
  896. //清除同终端号过期号牌
  897. lock (LicBuffer)
  898. {
  899. for (int i = 0; i < LicBuffer.Count; i++)
  900. {
  901. node = LicBuffer.Dequeue();
  902. if (node != null)
  903. {
  904. if (node.id != id)
  905. {
  906. LicBuffer.Enqueue(node);
  907. }
  908. }
  909. }
  910. }
  911. //将相应计数器归零,启动号牌记录
  912. lock (idCountMap)
  913. {
  914. if (idCountMap.ContainsKey(id))
  915. {
  916. Dictionary<string, int>.Enumerator ipidEnumer = ipIdMap.GetEnumerator();
  917. int handle = 0;
  918. while (ipidEnumer.MoveNext())
  919. {
  920. if (ipidEnumer.Current.Value == id)
  921. {
  922. ipHandleMap.TryGetValue(ipidEnumer.Current.Key, out handle);
  923. break;
  924. }
  925. }
  926. idCountMap[id] = 0;
  927. int count = 0;
  928. while (count <= FILTERINGNUMBER)
  929. {
  930. //Console.WriteLine(handle);
  931. ActivateSnap(handle);
  932. count++;
  933. Thread.Sleep((int)(REFRESHINGTIME));
  934. }
  935. }
  936. }
  937. node = null;
  938. int timeLimit = FILTERINGNUMBER * 2;
  939. while (node == null && timeLimit-- > 0)
  940. {
  941. lock (LicBuffer)
  942. {
  943. //Log.WriteLog(LogType.process, LogFile.INFO, "licBuffer 元素个数:" + LicBuffer.Count);
  944. for (int i = 0; i < LicBuffer.Count; i++)
  945. {
  946. node = LicBuffer.Dequeue();
  947. if (node != null)
  948. {
  949. if (node.id == id && node.LicenseNum != "")
  950. {
  951. license = node.LicenseNum;
  952. //Log.WriteLog(LogType.process, LogFile.INFO, "license: " + license + ", id: " + id);
  953. break;
  954. }
  955. else
  956. {
  957. //Log.WriteLog(LogType.process, LogFile.INFO, "other license: " + node.LicenseNum + ", id: " + node.id);
  958. LicBuffer.Enqueue(node);
  959. }
  960. }
  961. }
  962. }
  963. Thread.Sleep(REFRESHINGTIME);
  964. }
  965. if (timeLimit <= 0) { Console.WriteLine("本次未找到号牌"); Log.WriteLog(LogType.process, LogFile.INFO, id + "号号牌机未找到号牌"); }
  966. else { Log.WriteLog(LogType.process, LogFile.INFO, id + "号号牌机本次号牌: [" + license + "]"); }
  967. //}).Wait();
  968. return license == "空" ? "" : license;
  969. }
  970. /// <summary>
  971. /// 获取号牌对应ID,以在手机停取时确定终端编号
  972. /// </summary>
  973. /// <param name="license"></param>
  974. /// <returns></returns>
  975. public int GetLicenseID(string license)
  976. {
  977. int id = 0;
  978. //启动所有号牌记录
  979. lock (ipHandleMap)
  980. {
  981. for (int i = 0; i < FILTERINGNUMBER; i++)
  982. {
  983. Dictionary<string, int>.Enumerator HandleEnumer = ipHandleMap.GetEnumerator();
  984. while (HandleEnumer.MoveNext())
  985. {
  986. ActivateSnap(HandleEnumer.Current.Value);
  987. Thread.Sleep(50);
  988. }
  989. Thread.Sleep((int)(REFRESHINGTIME * 0.8));
  990. }
  991. }
  992. Thread.Sleep(REFRESHINGTIME);
  993. UpdateIdLicenseMap(true);
  994. Dictionary<int, string>.Enumerator idEnumer = idLicenseMap.GetEnumerator();
  995. while (idEnumer.MoveNext())
  996. {
  997. if (idEnumer.Current.Value == license)
  998. {
  999. id = idEnumer.Current.Key;
  1000. break;
  1001. }
  1002. }
  1003. return id;
  1004. }
  1005. public Image GetImage(int id)
  1006. {
  1007. return null;
  1008. }
  1009. public Dictionary<string, int> GetIpIdMap()
  1010. {
  1011. return ipIdMap;
  1012. }
  1013. public void SetRatio(double ratio)
  1014. {
  1015. filterRatio = ratio;
  1016. }
  1017. }
  1018. }