NumMachine.cs 40 KB

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