NumMachine.cs 36 KB

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