NumMachine.cs 38 KB

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