|
@@ -0,0 +1,885 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Drawing;
|
|
|
+using System.Windows.Forms;
|
|
|
+using System.Threading;
|
|
|
+using System.Collections;
|
|
|
+using VzClientSDKDemo;
|
|
|
+using System.Runtime.InteropServices;
|
|
|
+using System.IO;
|
|
|
+using System.Net;
|
|
|
+using parkMonitor.entity;
|
|
|
+using System.Diagnostics;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using System.Configuration;
|
|
|
+using WpfApp1.Entry;
|
|
|
+
|
|
|
+namespace NumMachine
|
|
|
+{
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 号牌机通信类
|
|
|
+ /// </summary>
|
|
|
+ public partial class NumMachineLinker : INumMachineLinker
|
|
|
+ {
|
|
|
+ /// <summary>
|
|
|
+ /// 刷新时间间隔与个数
|
|
|
+ /// </summary>
|
|
|
+ public const int REFRESHINGTIME = 500, FILTERINGNUMBER = 8;
|
|
|
+ ///<summary>通过设备句柄访问pic;链接时add,系统关闭时remove</summary>
|
|
|
+ private static Dictionary<int, IntPtr> devPicMap = new Dictionary<int, IntPtr>();
|
|
|
+ ///<summary>通过名字获取pic对象;创建pic时add,系统关闭remove</summary>
|
|
|
+ private static Dictionary<string, IntPtr> namePicMap = new Dictionary<string, IntPtr>();
|
|
|
+ ///<summary>通过ip获取设备id;产生ip时创建</summary>
|
|
|
+ private static Dictionary<string, int> ipIdMap = new Dictionary<string, int>();
|
|
|
+ ///<summary>通过ip获取设备句柄;产生句柄时创建</summary>
|
|
|
+ private static Dictionary<string, int> ipHandleMap = new Dictionary<string, int>();
|
|
|
+ /// <summary>句柄到号牌回调映射</summary>
|
|
|
+ private static Dictionary<int, VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK> handleCallbackMap = new Dictionary<int, VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK>();
|
|
|
+ ///<summary>号牌队列</summary>
|
|
|
+ private static Queue<NumberMachineNode> LicBuffer = new Queue<NumberMachineNode>();
|
|
|
+ ///<summary>计数Map</summary>
|
|
|
+ private static Dictionary<string, Dictionary<NumberMachineNode, int>> filterMap = new Dictionary<string, Dictionary<NumberMachineNode, int>>();
|
|
|
+ /// <summary>号牌机编号与激活计数</summary>
|
|
|
+ private Dictionary<int, int> idCountMap = new Dictionary<int, int>();
|
|
|
+ /// <summary>筛选计数</summary>
|
|
|
+ private static int filterCount = 0;
|
|
|
+ private static double filterRatio = 0.7;
|
|
|
+ /// <summary>系统关闭</summary>
|
|
|
+ private static bool isClosing = false;
|
|
|
+ /// <summary>开启拍照的设备</summary>
|
|
|
+ private static int snapshotDevHandle = -1;
|
|
|
+ /// <summary>允许无号牌时拍照</summary>
|
|
|
+ private static bool enableEmptySnapshot = true;
|
|
|
+
|
|
|
+ private static NumberMachineMessage nmMsg = new NumberMachineMessage();
|
|
|
+ private static VzClientSDK.VZLPRC_FIND_DEVICE_CALLBACK_EX find_DeviceCB = null;
|
|
|
+ private const int MSG_PLATE_INFO = 0x901;
|
|
|
+ private const int MSG_DEVICE_INFO = 0x902;
|
|
|
+ /// <summary>
|
|
|
+ /// 用于消息传递机制
|
|
|
+ /// </summary>
|
|
|
+ //public static IntPtr hwndMain;
|
|
|
+
|
|
|
+ public static IntPtr flowLayoutPanel1;
|
|
|
+
|
|
|
+ public static ToolStripStatusLabel timeLabel;
|
|
|
+ /// <summary>
|
|
|
+ /// 号牌机类构造函数
|
|
|
+ /// </summary>
|
|
|
+ public NumMachineLinker(IntPtr flpHandle)
|
|
|
+ {
|
|
|
+ //Control.CheckForIllegalCrossThreadCalls = false;
|
|
|
+ //Thread thread = new Thread(new ThreadStart(DateTimeInfo));
|
|
|
+ //thread.IsBackground = true;
|
|
|
+ //thread.Start(); //显示当前时间
|
|
|
+ flowLayoutPanel1 = flpHandle;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //timeLabel = new ToolStripStatusLabel();
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ VzClientSDK.VzLPRClient_Setup();
|
|
|
+ filterRatio = Double.Parse(ConfigurationManager.AppSettings.Get("filterRatio"));
|
|
|
+ }
|
|
|
+ catch (Exception e) { Console.WriteLine(e.Message + ",号牌机配置文件异常"); }
|
|
|
+ //m_sAppPath = System.IO.Directory.GetCurrentDirectory();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 定义时钟委托
|
|
|
+ /// </summary>
|
|
|
+ public delegate void SetDateTime();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 实时采集
|
|
|
+ /// </summary>
|
|
|
+ public delegate void Begin_Read();
|
|
|
+
|
|
|
+ private void FormSiemens_Load(object sender, EventArgs e)
|
|
|
+ {
|
|
|
+ //Thread thread = new Thread(new ThreadStart(DateTimeInfo));
|
|
|
+ //thread.IsBackground = true;
|
|
|
+ //thread.Start(); //显示当前时间
|
|
|
+
|
|
|
+ //VzClientSDK.VzLPRClient_Setup();
|
|
|
+
|
|
|
+ //hwndMain = this.Handle;
|
|
|
+ //m_sAppPath = System.IO.Directory.GetCurrentDirectory();
|
|
|
+ //this.ShowInTaskbar = false;
|
|
|
+ //this.Opacity = 0;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void FormSiemens_FormClosing(object sender, FormClosingEventArgs e)
|
|
|
+ {
|
|
|
+ Stop();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void DateTimeInfo()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ while (!isClosing)
|
|
|
+ {
|
|
|
+ SetDateTime setDate = new SetDateTime(
|
|
|
+ delegate
|
|
|
+ {
|
|
|
+ timeLabel.Text = DateTime.Now.ToString();
|
|
|
+ });
|
|
|
+ setDate();
|
|
|
+ Thread.Sleep(1000);
|
|
|
+ }
|
|
|
+ // ReSharper disable once FunctionNeverReturns
|
|
|
+ }
|
|
|
+ catch (Exception e) { Debug.Print(e.StackTrace); }
|
|
|
+ }
|
|
|
+
|
|
|
+ //******************************************************************************************************************
|
|
|
+ private void UpdateStatus(NumberMachineNode nmn)
|
|
|
+ {
|
|
|
+ //提示次数计数
|
|
|
+ int count = 0;
|
|
|
+ while (!isClosing)
|
|
|
+ {
|
|
|
+ if (GetStatus(nmn.ip) == 1)
|
|
|
+ {
|
|
|
+ nmn.status = EnumNumberMachineStatus.Normal;
|
|
|
+ count = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ count++;
|
|
|
+ //号牌机断线写日志
|
|
|
+ nmn.status = EnumNumberMachineStatus.Offline;
|
|
|
+ if (count == 1)
|
|
|
+ {
|
|
|
+ Console.WriteLine("正在与ip为 " + nmn.ip + " 的号牌机 进行连接。");
|
|
|
+ }
|
|
|
+ else if (count == 30)
|
|
|
+ {
|
|
|
+ nmMsg.data.Remove(nmn);
|
|
|
+ }
|
|
|
+ Thread.Sleep(10000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Run()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ while (!isClosing)
|
|
|
+ {
|
|
|
+ Thread.Sleep(REFRESHINGTIME);
|
|
|
+ //定时更新号牌
|
|
|
+ lock (devPicMap)
|
|
|
+ {
|
|
|
+ Dictionary<int, IntPtr>.Enumerator devEnumer = devPicMap.GetEnumerator();
|
|
|
+ while (devEnumer.MoveNext())
|
|
|
+ {
|
|
|
+ ActivateSnap(devEnumer.Current.Key);
|
|
|
+ //Debug.WriteLine(lv.data.Count.ToString()+":\n"+ lv.data[lv.data.Count-1].LicenseNum+ lv.data[lv.data.Count - 1].TimeRecord);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //读取设备ip与id映射关系
|
|
|
+ lock (ipHandleMap)
|
|
|
+ {
|
|
|
+ Dictionary<string, int>.Enumerator ipEnumer = ipHandleMap.GetEnumerator();
|
|
|
+ while (ipEnumer.MoveNext())
|
|
|
+ {
|
|
|
+ //映射关系不存在则读取配置文件
|
|
|
+ lock (ipIdMap)
|
|
|
+ {
|
|
|
+ if (ipEnumer.Current.Key != null && !ipIdMap.ContainsKey(ipEnumer.Current.Key))
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ int id = Int32.Parse(ConfigurationManager.AppSettings.Get(ipEnumer.Current.Key));
|
|
|
+ ipIdMap.Add(ipEnumer.Current.Key, id);
|
|
|
+ idCountMap.Add(id, FILTERINGNUMBER);
|
|
|
+ }
|
|
|
+ catch (Exception) { Console.WriteLine("读取号牌机编号映射失败,配置文件填写有误"); }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ lock (LicBuffer)
|
|
|
+ {
|
|
|
+ //删除已停好车的号牌
|
|
|
+ for (int i = 0; i < LicBuffer.Count; i++)
|
|
|
+ {
|
|
|
+ NumberMachineNode n = (NumberMachineNode)LicBuffer.Dequeue().Clone();
|
|
|
+ if (n.ip != "")
|
|
|
+ {
|
|
|
+ LicBuffer.Enqueue((NumberMachineNode)n.Clone());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Debug.WriteLine(ex.ToString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ///<summary>寻找设备回调函数</summary>
|
|
|
+ private void FIND_DEVICE_CALLBACK_EX(string pStrDevName, string pStrIPAddr, ushort usPort1, ushort usPort2, uint SL, uint SH, string netmask, string gateway, IntPtr pUserData)
|
|
|
+ {
|
|
|
+ string pStrDev = pStrIPAddr.ToString() + ":" + usPort1.ToString();
|
|
|
+ string serialNO = SL.ToString() + ":" + SH.ToString() + ":" + netmask + ":" + gateway;
|
|
|
+
|
|
|
+ VzClientSDK.VZ_LPR_DEVICE_INFO device_info = new VzClientSDK.VZ_LPR_DEVICE_INFO();
|
|
|
+ device_info.device_ip = pStrDev;
|
|
|
+ device_info.serial_no = serialNO;
|
|
|
+ DeviceLink(pStrDev, serialNO);
|
|
|
+ }
|
|
|
+
|
|
|
+ ///<summary>与设备连接,启动更新设备状态线程,输出视频</summary>
|
|
|
+ private void DeviceLink(string pStrDev, string serialNO)
|
|
|
+ {
|
|
|
+ IPEndPoint ipe;
|
|
|
+ GetIpEndPoint(pStrDev, out ipe);
|
|
|
+ string ip = ipe.Address.ToString();
|
|
|
+ if (ipHandleMap.ContainsKey(ip))
|
|
|
+ {
|
|
|
+ //MessageBox.Show("设备已分配句柄");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ int handle = 0;
|
|
|
+ //找到设备,加入list
|
|
|
+ NumberMachineNode node = new NumberMachineNode(ip, 0, "", "", 1);
|
|
|
+ nmMsg.data.Add(node);
|
|
|
+ handle = VzClientSDK.VzLPRClient_Open(ip, (ushort)80, "admin", "admin");
|
|
|
+ Task.Factory.StartNew(() =>
|
|
|
+ {
|
|
|
+ UpdateStatus(node);
|
|
|
+ });
|
|
|
+ if (handle == 0)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ VzClientSDK.VzLPRClient_SetVideoEncodeType(handle, 0);
|
|
|
+ //将句柄加入
|
|
|
+ lock (ipHandleMap)
|
|
|
+ {
|
|
|
+ ipHandleMap.Add(ip, handle);
|
|
|
+ }
|
|
|
+ //MessageBox.Show("摄像头打开成功");
|
|
|
+ lock (handleCallbackMap)
|
|
|
+ {
|
|
|
+ handleCallbackMap.Add(handle, null);
|
|
|
+ }
|
|
|
+ //链接句柄到新PictureBox
|
|
|
+ VideoOutput(handle);
|
|
|
+ }
|
|
|
+
|
|
|
+ ///<summary>视频输出</summary>
|
|
|
+ private void VideoOutput(int handle)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ lock (devPicMap)
|
|
|
+ {
|
|
|
+ lock (handleCallbackMap)
|
|
|
+ {
|
|
|
+ //存在设备则复位并在原pic上输出
|
|
|
+ if (devPicMap.ContainsKey(handle))
|
|
|
+ {
|
|
|
+ VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, null, IntPtr.Zero, 0);
|
|
|
+ IntPtr pic;
|
|
|
+ if (devPicMap.TryGetValue(handle, out pic) && handleCallbackMap.ContainsKey(handle))
|
|
|
+ {
|
|
|
+ int playHandle = VzClientSDK.VzLPRClient_StartRealPlay(handle, pic);
|
|
|
+ // 设置车牌识别结果回调
|
|
|
+ handleCallbackMap[handle] = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
|
|
|
+ VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, handleCallbackMap[handle], IntPtr.Zero, 1);
|
|
|
+ //m_PlateResultCB = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
|
|
|
+ //VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, m_PlateResultCB, IntPtr.Zero, 1);
|
|
|
+ //VzClientSDK.VzLPRClient_StopRealPlay(handle);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else//否则找一个空位加pic
|
|
|
+ {
|
|
|
+ for (int i = 0; i < 20; i++)
|
|
|
+ {
|
|
|
+ string str = "PictureBox" + Convert.ToString(i);
|
|
|
+ //该名称对应控件不存在,则创建并链接pic
|
|
|
+ lock (namePicMap)
|
|
|
+ {
|
|
|
+ if (!namePicMap.ContainsKey(str) && handleCallbackMap.ContainsKey(handle))
|
|
|
+ {
|
|
|
+ IntPtr pic;
|
|
|
+ if (CreatePic(i, out pic))
|
|
|
+ {
|
|
|
+ devPicMap.Add(handle, pic);
|
|
|
+ //ipIdMap.Add(Get_IP(handle), i);
|
|
|
+ VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, null, IntPtr.Zero, 0);
|
|
|
+ //Console.WriteLine(handle+","+pic.ToString());
|
|
|
+ int playHandle = VzClientSDK.VzLPRClient_StartRealPlay(handle, pic);
|
|
|
+ // 设置车牌识别结果回调
|
|
|
+ handleCallbackMap[handle] = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
|
|
|
+ VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, handleCallbackMap[handle], IntPtr.Zero, 1);
|
|
|
+ //m_PlateResultCB = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
|
|
|
+ //VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, m_PlateResultCB, IntPtr.Zero, 1);
|
|
|
+ //VzClientSDK.VzLPRClient_StopRealPlay(handle);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ Debug.WriteLine(e.Message + ",jumped out");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ///<summary>号牌信息回调</summary>
|
|
|
+ private int OnPlateResult(int handle, IntPtr pUserData,
|
|
|
+ IntPtr pResult, uint uNumPlates,
|
|
|
+ VzClientSDK.VZ_LPRC_RESULT_TYPE eResultType,
|
|
|
+ IntPtr pImgFull,
|
|
|
+ IntPtr pImgPlateClip)
|
|
|
+ {
|
|
|
+ if (eResultType != VzClientSDK.VZ_LPRC_RESULT_TYPE.VZ_LPRC_RESULT_REALTIME)
|
|
|
+ {
|
|
|
+ VzClientSDK.TH_PlateResult result = (VzClientSDK.TH_PlateResult)Marshal.PtrToStructure(pResult, typeof(VzClientSDK.TH_PlateResult));
|
|
|
+ string strLicense = (new string(result.license)).Split('\0')[0];
|
|
|
+
|
|
|
+ VzClientSDK.VZ_LPR_MSG_PLATE_INFO plateInfo = new VzClientSDK.VZ_LPR_MSG_PLATE_INFO();
|
|
|
+ plateInfo.plate = strLicense;
|
|
|
+ SetDetail(plateInfo, Get_IP(handle));
|
|
|
+
|
|
|
+ //根据setMessage中通过id信息找到的handle保存图片
|
|
|
+ if (handle == snapshotDevHandle)
|
|
|
+ {
|
|
|
+ if (enableEmptySnapshot || !strLicense.Contains("_无_"))
|
|
|
+ {
|
|
|
+ string strFilePath = ConfigurationManager.AppSettings["LogPath"] + DateTime.Now.ToString("yyyyMMdd") + "\\";
|
|
|
+ if (!Directory.Exists(strFilePath))
|
|
|
+ {
|
|
|
+ Directory.CreateDirectory(strFilePath);
|
|
|
+ }
|
|
|
+ string ip = Get_IP(handle);
|
|
|
+ string path = strFilePath + ip + "-" + DateTime.Now.ToString("hh_mm_ss") + ".jpg";
|
|
|
+ int temp = VzClientSDK.VzLPRClient_ImageSaveToJpeg(pImgFull, path, 50);
|
|
|
+ if (temp != -1)
|
|
|
+ {
|
|
|
+ Console.WriteLine("号牌机" + ip + "已拍照,图片保存于 " + strFilePath);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Console.WriteLine("图片保存失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ snapshotDevHandle = -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ ///<summary>记录车牌,时间,状态信息;刷新本地entity,并且入buffer</summary>
|
|
|
+ private void SetDetail(VzClientSDK.VZ_LPR_MSG_PLATE_INFO plateInformation, string strIP)
|
|
|
+ {
|
|
|
+ int stat = GetStatus(strIP);
|
|
|
+ bool found = false;
|
|
|
+ int id = 0;
|
|
|
+ lock (ipIdMap)
|
|
|
+ {
|
|
|
+ if (!ipIdMap.ContainsKey(strIP))
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ id = Int32.Parse(ConfigurationManager.AppSettings.Get(strIP));
|
|
|
+ ipIdMap.Add(strIP, id);
|
|
|
+ idCountMap.Add(id, FILTERINGNUMBER);
|
|
|
+ }
|
|
|
+ catch (Exception) { Console.WriteLine("读取号牌机编号映射失败,配置文件填写有误"); }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //检查设备是否存在
|
|
|
+ foreach (NumberMachineNode nmn in nmMsg.data)
|
|
|
+ {
|
|
|
+ //相同设备
|
|
|
+ if (nmn.ip == strIP)
|
|
|
+ {
|
|
|
+ found = true;
|
|
|
+ //号牌不为空
|
|
|
+ if (!(plateInformation.plate.Contains("_无_")))
|
|
|
+ {
|
|
|
+ nmn.SetLic(strIP, nmn.id, plateInformation.plate, DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"), GetStatus(strIP));
|
|
|
+ FilterLic(strIP, (NumberMachineNode)nmn.Clone());
|
|
|
+ }
|
|
|
+ //号牌为空
|
|
|
+ else
|
|
|
+ {
|
|
|
+ nmn.SetLic(strIP, nmn.id, "", "", GetStatus(strIP));
|
|
|
+ FilterLic(strIP, null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //新设备
|
|
|
+ if (!found)
|
|
|
+ {
|
|
|
+ lock (ipIdMap)
|
|
|
+ {
|
|
|
+ if (!(plateInformation.plate.Contains("_无_")) && ipIdMap.TryGetValue(strIP, out id))
|
|
|
+ {
|
|
|
+ NumberMachineNode nmn = new NumberMachineNode(strIP, id, plateInformation.plate, DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"), GetStatus(strIP));
|
|
|
+ NumberMachineNode nmnc = (NumberMachineNode)nmn.Clone();
|
|
|
+ nmMsg.data.Add(nmnc);
|
|
|
+ FilterLic(strIP, nmnc);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ nmMsg.data.Add(new NumberMachineNode(strIP, id, "", "", GetStatus(strIP)));
|
|
|
+ FilterLic(strIP, null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ///<summary>筛选号牌</summary>
|
|
|
+ private void FilterLic(string ip, NumberMachineNode nmn)
|
|
|
+ {
|
|
|
+ int id = 0, activeCount = 0;
|
|
|
+ if (ipIdMap.TryGetValue(ip, out id) && idCountMap.TryGetValue(id, out activeCount) && activeCount < FILTERINGNUMBER)
|
|
|
+ {
|
|
|
+ Dictionary<NumberMachineNode, int> filter;
|
|
|
+ //该filter不存在则创建
|
|
|
+ if (!filterMap.ContainsKey(ip))
|
|
|
+ {
|
|
|
+ filter = new Dictionary<NumberMachineNode, int>();
|
|
|
+ filterMap.Add(ip, filter);
|
|
|
+ }
|
|
|
+ else if (!filterMap.TryGetValue(ip, out filter))//计数器异常
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else if (activeCount == 0) //刚接到拍摄命令
|
|
|
+ {
|
|
|
+ filter.Clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ //激活次数统计
|
|
|
+ idCountMap[id] = activeCount + 1;
|
|
|
+
|
|
|
+ //filter计数
|
|
|
+ int count = 0;
|
|
|
+ if (nmn == null)
|
|
|
+ {
|
|
|
+ if (activeCount >= FILTERINGNUMBER - 1)
|
|
|
+ {
|
|
|
+ //UILogServer.ins.error("本轮未扫描到号牌,请重新点击按钮停车");
|
|
|
+ //string context = System.DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ":" + "号牌未扫描到,请重发指令";
|
|
|
+ //string sql = "insert into messagequeue(userID,context,messageType) values (1,'" + context + "',1)";
|
|
|
+ //List<string> strs = new List<string>();
|
|
|
+ //strs.Add(sql);
|
|
|
+ //DBOperation.InsertMessageQueue(EntityForCore.remoteBQ, strs);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else if (filter.ContainsKey(nmn) && filter.TryGetValue(nmn, out count))//存在则数量+1
|
|
|
+ {
|
|
|
+ filter[nmn] = count + 1;
|
|
|
+ }
|
|
|
+ else//不存在则计数1
|
|
|
+ {
|
|
|
+ filter.Add(nmn, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ //计算总数
|
|
|
+ filterCount = 0;
|
|
|
+ Dictionary<NumberMachineNode, int>.Enumerator countEnumer = filter.GetEnumerator();
|
|
|
+ while (countEnumer.MoveNext())
|
|
|
+ {
|
|
|
+ filterCount += countEnumer.Current.Value;
|
|
|
+ }
|
|
|
+
|
|
|
+ //达到计数限制,计算总数是否达标,达标则入队
|
|
|
+ if (filterCount >= FILTERINGNUMBER)
|
|
|
+ {
|
|
|
+ lock (LicBuffer)
|
|
|
+ {
|
|
|
+ Dictionary<NumberMachineNode, int>.Enumerator enumer = filter.GetEnumerator();
|
|
|
+ int maxCount = 0;
|
|
|
+ NumberMachineNode node = null;
|
|
|
+ while (enumer.MoveNext())
|
|
|
+ {
|
|
|
+ ////遍历,计数达标且队列中无此号牌
|
|
|
+ //if (enumer.Current.Value >= (int)(filterCount * filterRatio) && enumer.Current.Key != null && !LicBuffer.Contains(enumer.Current.Key))
|
|
|
+ //找到最大计数及相应号牌信息
|
|
|
+ if (enumer.Current.Value >= maxCount && enumer.Current.Key != null && !LicBuffer.Contains(enumer.Current.Key))
|
|
|
+ {
|
|
|
+ //输出节点为空或与该号牌不同
|
|
|
+ if (nmMsg.aNode == null || nmMsg.aNode.LicenseNum == null || nmMsg.aNode.LicenseNum != enumer.Current.Key.LicenseNum)
|
|
|
+ {
|
|
|
+ maxCount = enumer.Current.Value;
|
|
|
+ node = (NumberMachineNode)enumer.Current.Key.Clone();
|
|
|
+ if (node != null && ipIdMap.TryGetValue(node.ip, out node.id))
|
|
|
+ {
|
|
|
+ LicBuffer.Enqueue((NumberMachineNode)node.Clone());
|
|
|
+ if (node.id == 1)
|
|
|
+ {
|
|
|
+ Task.Factory.StartNew(() =>
|
|
|
+ {
|
|
|
+ if (SystemInitializer.allInOneMachine != null)
|
|
|
+ {
|
|
|
+ SystemInitializer.allInOneMachine.Play(1, BroadcastModule.BroadcastBoard.PlayMode.temporary, node.LicenseNum, 6);
|
|
|
+ SystemInitializer.allInOneMachine.Play(1, BroadcastModule.BroadcastBoard.PlayMode.audio, node.LicenseNum + ",入场");
|
|
|
+ Thread.Sleep(5000);
|
|
|
+ SystemInitializer.allInOneMachine.Play(1, BroadcastModule.BroadcastBoard.PlayMode.readBuffer, "", 0, 0);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ filterCount = 0;
|
|
|
+ filter.Clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ///<summary>停止播放与设备句柄关联的视频</summary>
|
|
|
+ private void StopPlay(int handleInput)
|
|
|
+ {
|
|
|
+ if (handleInput != 0)
|
|
|
+ {
|
|
|
+ int ret = VzClientSDK.VzLPRClient_StopRealPlay(handleInput);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ///<summary>强制获取号牌</summary>
|
|
|
+ private void ActivateSnap(int handle)
|
|
|
+ {
|
|
|
+ if (handle > 0)
|
|
|
+ {
|
|
|
+ VzClientSDK.VzLPRClient_ForceTrigger(handle);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ ///<summary>ip+port字符串转ipe</summary>
|
|
|
+ private void GetIpEndPoint(string ipp, out IPEndPoint ipe)
|
|
|
+ {
|
|
|
+ IPAddress myIP = IPAddress.Parse(ipp.Remove(ipp.LastIndexOf(':')) + "");
|
|
|
+ string myPort = ipp.Substring(ipp.IndexOf(':') + 1);
|
|
|
+ ipe = new IPEndPoint(myIP, int.Parse(myPort));
|
|
|
+ }
|
|
|
+
|
|
|
+ ///<summary>创建新pic并记录在picNameMap</summary>
|
|
|
+ private bool CreatePic(int index, out IntPtr pic)
|
|
|
+ {
|
|
|
+ pic = IntPtr.Zero;
|
|
|
+ PictureBox pb = new PictureBox
|
|
|
+ {
|
|
|
+ Width = 230,
|
|
|
+ Height = 180,
|
|
|
+ Bounds = new System.Drawing.Rectangle(0, 0, 230, 180),
|
|
|
+ Name = "PictureBox" + Convert.ToString(index)
|
|
|
+ };
|
|
|
+ lock (namePicMap)
|
|
|
+ {
|
|
|
+ if (!namePicMap.ContainsKey(pb.Name))
|
|
|
+ {
|
|
|
+ PictureBox temp = pb;
|
|
|
+ IntPtr picHandle = IntPtr.Zero;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ Control flp = Control.FromHandle(flowLayoutPanel1);
|
|
|
+
|
|
|
+ //Control.FromHandle(flowLayoutPanel1).Controls.Add(temp);
|
|
|
+ if (flp.InvokeRequired)
|
|
|
+ {
|
|
|
+ flp.Invoke(new Action(() => { flp.Controls.Add(temp); picHandle = temp.Handle; }));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ flp.Controls.Add(pb);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception e) { Console.WriteLine(e.Message); }
|
|
|
+ namePicMap.Add(pb.Name, picHandle);
|
|
|
+ pic = picHandle;
|
|
|
+ //Console.WriteLine(picHandle.ToString());
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ///<summary>更新设备状态</summary>
|
|
|
+ private int GetStatus(string devIP)
|
|
|
+ {
|
|
|
+ int myHandle;
|
|
|
+ byte stat = 0;
|
|
|
+ if (ipHandleMap.TryGetValue(devIP, out myHandle))
|
|
|
+ {
|
|
|
+ VzClientSDK.VzLPRClient_IsConnected(myHandle, ref stat);
|
|
|
+ return stat;
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ private string Get_IP(int lprHandle)
|
|
|
+ {
|
|
|
+ byte[] strDecIP = new byte[32];
|
|
|
+ int max_count = 32;
|
|
|
+ int ret = VzClientSDK.VzLPRClient_GetDeviceIP(lprHandle, ref strDecIP[0], max_count);
|
|
|
+ string strIP = System.Text.Encoding.Default.GetString(strDecIP);
|
|
|
+ strIP = strIP.TrimEnd('\0');
|
|
|
+ return strIP;
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool NodeValidation(NumberMachineNode node)
|
|
|
+ {
|
|
|
+ return (node != null && node.ip != null && node.ip != "" && node.ip != "used" && node.LicenseNum != null && node.LicenseNum != "") ? true : false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 系统启动
|
|
|
+ /// </summary>
|
|
|
+ public void Start()
|
|
|
+ {
|
|
|
+
|
|
|
+ Task.Factory.StartNew(() =>
|
|
|
+ {
|
|
|
+ isClosing = false;
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ VzClientSDK.VZLPRClient_StopFindDevice();
|
|
|
+
|
|
|
+ find_DeviceCB = new VzClientSDK.VZLPRC_FIND_DEVICE_CALLBACK_EX(FIND_DEVICE_CALLBACK_EX);
|
|
|
+ int ret = VzClientSDK.VZLPRClient_StartFindDeviceEx(find_DeviceCB, IntPtr.Zero);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Debug.WriteLine(ex.ToString());
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ Task.Factory.StartNew(() =>
|
|
|
+ {
|
|
|
+ Run();
|
|
|
+ });
|
|
|
+ //Task imgTest = Task.Factory.StartNew(() =>
|
|
|
+ //{
|
|
|
+ // while (!isClosing)
|
|
|
+ // {
|
|
|
+ // Command cmd = new Command
|
|
|
+ // {
|
|
|
+ // id = 1
|
|
|
+ // };
|
|
|
+ // SetMessage(cmd);
|
|
|
+ // Thread.Sleep(30000);
|
|
|
+ // Command cmd2 = new Command
|
|
|
+ // {
|
|
|
+ // id = 2
|
|
|
+ // };
|
|
|
+ // SetMessage(cmd2);
|
|
|
+ // Thread.Sleep(30000);
|
|
|
+ // }
|
|
|
+ //});
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 系统关闭
|
|
|
+ /// </summary>
|
|
|
+ public void Stop()
|
|
|
+ {
|
|
|
+ VzClientSDK.VZLPRClient_StopFindDevice();
|
|
|
+ lock (devPicMap)
|
|
|
+ {
|
|
|
+ Dictionary<int, IntPtr>.Enumerator enumer = devPicMap.GetEnumerator();
|
|
|
+ while (enumer.MoveNext())
|
|
|
+ {
|
|
|
+ if (enumer.Current.Key != 0)
|
|
|
+ {
|
|
|
+ StopPlay(enumer.Current.Key);
|
|
|
+ VzClientSDK.VzLPRClient_Close(enumer.Current.Key);
|
|
|
+ //flowLayoutPanel1.Controls.Remove(enumer.Current.Value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ isClosing = true;
|
|
|
+ devPicMap.Clear();
|
|
|
+ }
|
|
|
+ lock (namePicMap) { namePicMap.Clear(); }
|
|
|
+ lock (ipIdMap) { ipIdMap.Clear(); }
|
|
|
+ lock (ipHandleMap) { ipHandleMap.Clear(); }
|
|
|
+ //this.Close();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 监控线程获取号牌机信息,核心线程获取号牌信息
|
|
|
+ /// </summary>
|
|
|
+ public AbstractMessage GetMessage()
|
|
|
+ {
|
|
|
+ lock (LicBuffer)
|
|
|
+ {
|
|
|
+ //准备输出的数据中存在非法Node,且LicBuffer可出队产生一个合法Node,则替换该非法Node
|
|
|
+ if (!NodeValidation(nmMsg.aNode))
|
|
|
+ {
|
|
|
+ for (int i = 0; i < LicBuffer.Count; i++)
|
|
|
+ {
|
|
|
+ NumberMachineNode n = LicBuffer.Dequeue();
|
|
|
+ if (NodeValidation(n))
|
|
|
+ {
|
|
|
+ if (nmMsg.aNode != null && nmMsg.aNode.ip != null)
|
|
|
+ {
|
|
|
+ LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
|
|
|
+ }
|
|
|
+ nmMsg.aNode = n;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LicBuffer.Enqueue(n);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //遍历licBuffer后仍不合法,则丢入队列,将node置为null
|
|
|
+ if (!NodeValidation(nmMsg.aNode))
|
|
|
+ {
|
|
|
+ if (nmMsg.aNode != null && nmMsg.aNode.ip != null)
|
|
|
+ {
|
|
|
+ LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
|
|
|
+ }
|
|
|
+ nmMsg.aNode = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nmMsg;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 一次停车流程完成时调用该方法,发送已完成车辆号牌信息
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="message">已完成车辆的号牌相关信息存于message的aNode中,用于标记需清空的号牌</param>
|
|
|
+ public void SetMessage(AbstractMessage message)
|
|
|
+ {
|
|
|
+ if (message.GetType().Equals(typeof(NumberMachineMessage)))
|
|
|
+ {
|
|
|
+ NumberMachineNode n = ((NumberMachineMessage)message).aNode;
|
|
|
+ lock (LicBuffer)
|
|
|
+ {
|
|
|
+ //输入号牌格式无误
|
|
|
+ if (n != null && n.ip != null && n.ip == "")
|
|
|
+ {
|
|
|
+ //与类成员变量中aNode号牌相同,将其ip复位表示已使用,重新入队等待清除
|
|
|
+ if (nmMsg != null && nmMsg.aNode != null && nmMsg.aNode.LicenseNum == n.LicenseNum)
|
|
|
+ {
|
|
|
+ nmMsg.aNode.ip = "";
|
|
|
+ LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
|
|
|
+ nmMsg.aNode = null;
|
|
|
+ }
|
|
|
+ //搜索号牌队列,将相应号牌置空,准备清除
|
|
|
+ else
|
|
|
+ {
|
|
|
+ for (int i = 0; i < LicBuffer.Count; i++)
|
|
|
+ {
|
|
|
+ NumberMachineNode temp = LicBuffer.Dequeue();
|
|
|
+ //已匹配上,ip置空
|
|
|
+ if (temp.LicenseNum == n.LicenseNum)
|
|
|
+ {
|
|
|
+ temp.ip = "";
|
|
|
+ LicBuffer.Enqueue(temp);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ LicBuffer.Enqueue(temp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (message.GetType().Equals(typeof(Command)))
|
|
|
+ {
|
|
|
+ Command cmd = (Command)message;
|
|
|
+ if (cmd != null && cmd.id != 0)
|
|
|
+ {
|
|
|
+ //拍照功能根据ip找到handle,改变snapshotDevHandle的值在回调函数中截图
|
|
|
+ lock (ipIdMap)
|
|
|
+ {
|
|
|
+ Dictionary<string, int>.Enumerator enumerator = ipIdMap.GetEnumerator();
|
|
|
+ while (enumerator.MoveNext())
|
|
|
+ {
|
|
|
+ // if (enumerator.Current.Value == cmd.id && ipHandleMap.TryGetValue(enumerator.Current.Key, out int handle))
|
|
|
+ int handle = 0;
|
|
|
+ if (enumerator.Current.Value == cmd.id && ipHandleMap.TryGetValue(enumerator.Current.Key, out handle))
|
|
|
+ {
|
|
|
+ snapshotDevHandle = handle;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Console.WriteLine("参数错误,图片未保存");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public string GetLicensePlate(int id)
|
|
|
+ {
|
|
|
+ string license = "";
|
|
|
+ //将相应计数器归零,启动号牌记录
|
|
|
+ lock (idCountMap)
|
|
|
+ {
|
|
|
+ if (idCountMap.ContainsKey(id))
|
|
|
+ {
|
|
|
+ idCountMap[id] = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Task.Factory.StartNew(() =>
|
|
|
+ {
|
|
|
+ NumberMachineNode node = null;
|
|
|
+ int timeLimit = 8;
|
|
|
+ while (node == null && timeLimit-- > 0)
|
|
|
+ {
|
|
|
+ lock (LicBuffer)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < LicBuffer.Count; i++)
|
|
|
+ {
|
|
|
+ node = LicBuffer.Dequeue();
|
|
|
+ if (node != null)
|
|
|
+ {
|
|
|
+ if (node.id == id)
|
|
|
+ {
|
|
|
+ license = node.LicenseNum;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LicBuffer.Enqueue(node);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Thread.Sleep(1000);
|
|
|
+ }
|
|
|
+ }).Wait();
|
|
|
+ return license;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Image GetImage(int id)
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|