NumMachineModel.cs 35 KB

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