NumMachine.cs 43 KB

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