using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Edge.Core.Processor;using Edge.Core.IndustryStandardInterface.Pump; using Edge.Core.UniversalApi; using Newtonsoft.Json; namespace HKCarPlateRecognize_App { public class HkCarPlateRecognizeApp : IAppProcessor { public string MetaConfigName { get; set; } private bool etcCarPlate = false; private string DeviceAddress { get; set; } private int Port { get; set; } private string UserName { get; set; } private string PassWord { get; set; } private int CarPlateTimeOut { get; set; } /// /// 接口返回-1表示登录失败,其他值表示返回的用户ID值 /// private int _luser = -1; /// /// -1表示失败,其他值作为NET_DVR_CloseAlarmChan_V30函数的句柄参数 /// private int _lHandle = -1; public event EventHandler NewCarPlateCatched; private Dictionary PlateLicenses = new Dictionary(); private static NLog.Logger logger = NLog.LogManager.LoadConfiguration("NLog.config").GetLogger("HkPalteRecognize"); private CHCNetSDK.MSGCallBack_V31 m_falarmData_V31 = null; /// /// /// /// IP address of the device /// device's listening port /// user name used to login device /// password used to login device public HkCarPlateRecognizeApp(string deviceAddress, int port, string userName, string passWord, int carPlateTimeOut, string etcCarPlate) { DeviceAddress = deviceAddress; Port = port; UserName = userName; PassWord = passWord; CarPlateTimeOut = carPlateTimeOut; this.etcCarPlate = bool.Parse(etcCarPlate); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); } [UniversalApi(Description = "Param ciphertext is the EtcCarPlateCatched information was encrypted with AES")] public async Task NewCarPlateCatchedAsync(string ciphertext) { try { string password = "27c8fa1a46baabda88d2b977de272c1f"; string content = AesHelper.DecodeAES(ciphertext, password); var etcCarPlate = JsonConvert.DeserializeObject(content); logger.Debug($"NewCarPlateCatchedAsync with etcCarPlate {content}"); NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(etcCarPlate.carNumber, DateTime.ParseExact(etcCarPlate.timeStamp, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture))); } catch (Exception ex) { logger.Error($"In NewCarPlateCatchedAsync {ex}"); return await Task.FromResult(false); } return await Task.FromResult(true); } public async Task Start() { bool started = false; if (etcCarPlate) return await Task.FromResult(true); var m_bInitSDK = CHCNetSDK.NET_DVR_Init(); if (m_falarmData_V31 == null) m_falarmData_V31 = new CHCNetSDK.MSGCallBack_V31(MessageCallback); // CHCNetSDK.NET_DVR_SetExceptionCallBack_V30(0, IntPtr.Zero, ExceptionCallBack, IntPtr.Zero); if (m_bInitSDK) { if (CHCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(m_falarmData_V31, IntPtr.Zero)) { //_luser = NetDVRLoginV40; _luser = NetDVRLoginV30(); if (_luser < 0) { uint error = CHCNetSDK.NET_DVR_GetLastError(); logger.Info("Failed to login device, CHCNetSDK.NET_DVR_Login_V40, err:{0}", error); if (error == CHCNetSDK.NET_DVR_NETWORK_FAIL_CONNECT) { System.Timers.Timer reloginTimer = new System.Timers.Timer(); reloginTimer.Elapsed += (a, b) => { logger.Debug("relogin timer elapsed"); reloginTimer.Enabled = false; //var stringPlateLicense = DateTime.Now.Millisecond.ToString(CultureInfo.InvariantCulture); //NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.Now)); //_luser = NetDVRLoginV40(); _luser = NetDVRLoginV30(); if (_luser < 0) { uint e = CHCNetSDK.NET_DVR_GetLastError(); var b1 = e == CHCNetSDK.NET_DVR_NETWORK_FAIL_CONNECT ? reloginTimer.Enabled = true : reloginTimer.Enabled = false; } else { _lHandle = SetupAlarmChan_V41(); if (_lHandle < 0) { var e = CHCNetSDK.NET_DVR_GetLastError(); } } }; reloginTimer.Interval = 60000; reloginTimer.Start(); } } else { _lHandle = SetupAlarmChan_V41(); if (_lHandle < 0) { uint error = CHCNetSDK.NET_DVR_GetLastError(); logger.Info("error happens when call SetupAlarmChan_V41, err:{0}", error); } else { logger.Info("HK PlateRecognizeApp started successfully"); started = true; } } } } return started; } public int NetDVRLoginV40() { CHCNetSDK.NET_DVR_USER_LOGIN_INFO struLoginInfo = new CHCNetSDK.NET_DVR_USER_LOGIN_INFO(); struLoginInfo.bUseAsynLogin = 0; //同步登录方式 struLoginInfo.sDeviceAddress = DeviceAddress; struLoginInfo.wPort = (ushort)Port; struLoginInfo.sUserName = UserName; struLoginInfo.sPassword = PassWord; CHCNetSDK.NET_DVR_DEVICEINFO_V40 deviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V40(); return CHCNetSDK.NET_DVR_Login_V40(struLoginInfo, deviceInfo); } public int NetDVRLoginV30() { logger.Debug("NetDVRLoginV30 new device info"); CHCNetSDK.NET_DVR_DEVICEINFO_V30 deviceInfov30 = new CHCNetSDK.NET_DVR_DEVICEINFO_V30(); logger.Debug("NetDVRLoginV30 Login_V30"); return CHCNetSDK.NET_DVR_Login_V30(DeviceAddress, Port, UserName, PassWord, ref deviceInfov30); } public int SetupAlarmChan_V41() { CHCNetSDK.NET_DVR_SETUPALARM_PARAM alarmParam = new CHCNetSDK.NET_DVR_SETUPALARM_PARAM(); alarmParam.dwSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(CHCNetSDK.NET_DVR_SETUPALARM_PARAM)); alarmParam.byLevel = 1; //布防优先级:0- 一等级(高),1- 二等级(中) alarmParam.byAlarmInfoType = 1; //上传报警信息类型: 0- 老报警信息(NET_DVR_PLATE_RESULT), 1- 新报警信息(NET_ITS_PLATE_RESULT) return CHCNetSDK.NET_DVR_SetupAlarmChan_V41(_luser, ref alarmParam); } public bool MessageCallback(int lCommand, ref CHCNetSDK.NET_DVR_ALARMER pAlarmer, IntPtr pAlarmInfo, uint dwBufLen, IntPtr pUser) { logger.Info("HkPlateRecognizeApp:MessageCallback, message received:{0}", lCommand); switch (lCommand) { case CHCNetSDK.COMM_UPLOAD_PLATE_RESULT: ProcessCommAlarm_Plate(ref pAlarmer, pAlarmInfo, dwBufLen, pUser); break; case CHCNetSDK.COMM_ITS_PLATE_RESULT: ProcessCommAlarm_ITSPlate(ref pAlarmer, pAlarmInfo, dwBufLen, pUser); break; default: break; } return true; } public void ExceptionCallBack(uint dwType, int lUserID, int lHandle, IntPtr pUser) { logger.Info("HkPlateRecognizeApp::ExceptionCallBack"); } private void ProcessCommAlarm_Plate(ref CHCNetSDK.NET_DVR_ALARMER pAlarmer, IntPtr pAlarmInfo, uint dwBufLen, IntPtr pUser) { try { CHCNetSDK.NET_DVR_PLATE_RESULT struPlateResultInfo = new CHCNetSDK.NET_DVR_PLATE_RESULT(); uint dwSize = (uint)Marshal.SizeOf(struPlateResultInfo); struPlateResultInfo = (CHCNetSDK.NET_DVR_PLATE_RESULT)Marshal.PtrToStructure(pAlarmInfo, typeof(CHCNetSDK.NET_DVR_PLATE_RESULT)); //保存抓拍图片 string str = ""; if (struPlateResultInfo.byResultType == 1 && struPlateResultInfo.dwPicLen != 0) { str = ".\\picture\\Plate_UserID_" + pAlarmer.lUserID + "_近景图.jpg"; FileStream fs = new FileStream(str, FileMode.Create); int iLen = (int)struPlateResultInfo.dwPicLen; byte[] by = new byte[iLen]; Marshal.Copy(struPlateResultInfo.pBuffer1, by, 0, iLen); fs.Write(by, 0, iLen); fs.Close(); } if (struPlateResultInfo.dwPicPlateLen != 0) { str = ".\\picture\\Plate_UserID_" + pAlarmer.lUserID + "_车牌图.jpg"; FileStream fs = new FileStream(str, FileMode.Create); int iLen = (int)struPlateResultInfo.dwPicPlateLen; byte[] by = new byte[iLen]; Marshal.Copy(struPlateResultInfo.pBuffer2, by, 0, iLen); fs.Write(by, 0, iLen); fs.Close(); } if (struPlateResultInfo.dwFarCarPicLen != 0) { str = ".\\picture\\Plate_UserID_" + pAlarmer.lUserID + "_远景图.jpg"; FileStream fs = new FileStream(str, FileMode.Create); int iLen = (int)struPlateResultInfo.dwFarCarPicLen; byte[] by = new byte[iLen]; Marshal.Copy(struPlateResultInfo.pBuffer5, by, 0, iLen); fs.Write(by, 0, iLen); fs.Close(); } //报警设备IP地址 string strIP = System.Text.Encoding.UTF8.GetString(pAlarmer.sDeviceIP).TrimEnd('\0'); //抓拍时间:年月日时分秒 string strTimeYear = System.Text.Encoding.UTF8.GetString(struPlateResultInfo.byAbsTime).TrimEnd('\0'); //上传结果 string stringPlateLicense = System.Text.Encoding.GetEncoding("GBK").GetString(struPlateResultInfo.struPlateInfo.sLicense).TrimEnd('\0'); string stringAlarm = "抓拍上传," + "车牌:" + stringPlateLicense + ",车辆序号:" + struPlateResultInfo.struVehicleInfo.dwIndex; logger.Info("HkPlateRecognizeApp::ProcessCommAlarm_Plate strTimeTear:{0},stringPlateLicense{1}", strTimeYear, stringPlateLicense); lock (PlateLicenses) { if (PlateLicenses.ContainsKey(stringPlateLicense)) { TimeSpan timeSpan = DateTime.Now - PlateLicenses[stringPlateLicense]; if (timeSpan.TotalMinutes > 30) { PlateLicenses.Remove(stringPlateLicense); PlateLicenses.Add(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture)); NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture))); } } else { PlateLicenses.Add(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture)); NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture))); } } //if (InvokeRequired) //{ // object[] paras = new object[3]; // paras[0] = strTimeYear; //当前PC系统时间为DateTime.Now.ToString(); // paras[1] = strIP; // paras[2] = stringAlarm; // listViewAlarmInfo.BeginInvoke(new UpdateListBoxCallback(UpdateClientList), paras); //} //else //{ // //创建该控件的主线程直接更新信息列表 // UpdateClientList(DateTime.Now.ToString(), strIP, stringAlarm); //} } catch (Exception e) { logger.Info("Exception happened in ProcessCommAlarm_Plate:" + e.Message); //throw; } } private void ProcessCommAlarm_ITSPlate(ref CHCNetSDK.NET_DVR_ALARMER pAlarmer, IntPtr pAlarmInfo, uint dwBufLen, IntPtr pUser) { try { //check the existing plates to see if anything has existing for a long time, then remove it CheckAndRemoveTheExpiredPlate(); CHCNetSDK.NET_ITS_PLATE_RESULT struITSPlateResult = new CHCNetSDK.NET_ITS_PLATE_RESULT(); uint dwSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(struITSPlateResult); struITSPlateResult = (CHCNetSDK.NET_ITS_PLATE_RESULT)Marshal.PtrToStructure(pAlarmInfo, typeof(CHCNetSDK.NET_ITS_PLATE_RESULT)); logger.Debug("plate info catched --1"); //报警设备IP地址 string strIP = System.Text.Encoding.UTF8.GetString(pAlarmer.sDeviceIP).TrimEnd('\0'); logger.Debug("The IP address of the device:" + strIP); //抓拍时间:年月日时分秒 string strTimeYear = string.Format("{0:D4}", struITSPlateResult.struSnapFirstPicTime.wYear) + string.Format("{0:D2}", struITSPlateResult.struSnapFirstPicTime.byMonth) + string.Format("{0:D2}", struITSPlateResult.struSnapFirstPicTime.byDay) + " " + string.Format("{0:D2}", struITSPlateResult.struSnapFirstPicTime.byHour) + ":" + string.Format("{0:D2}", struITSPlateResult.struSnapFirstPicTime.byMinute) + ":" + string.Format("{0:D2}", struITSPlateResult.struSnapFirstPicTime.bySecond) + ":" + string.Format("{0:D3}", struITSPlateResult.struSnapFirstPicTime.wMilliSec); //上传结果 string stringPlateLicense = System.Text.Encoding.GetEncoding("GBK").GetString(struITSPlateResult.struPlateInfo.sLicense).TrimEnd('\0').Substring(1); string stringAlarm = "抓拍上传," + "车牌:" + stringPlateLicense + ",车辆序号:" + struITSPlateResult.struVehicleInfo.dwIndex; logger.Info("HkPlateRecognizeApp::ProcessCommAlarm_ITSPlate strTimeTear:{0},stringPlateLicense{1}", strTimeYear, stringPlateLicense); lock (PlateLicenses) { if (PlateLicenses.ContainsKey(stringPlateLicense)) { TimeSpan timeSpan = DateTime.Now - PlateLicenses[stringPlateLicense]; logger.Debug("PlateLicenses contains:{0} plates,time{1},timespan minutes{2}", PlateLicenses.Count, PlateLicenses[stringPlateLicense], timeSpan.Minutes); if (timeSpan.TotalMinutes > CarPlateTimeOut) { logger.Debug("new plate over {0} min", CarPlateTimeOut); PlateLicenses.Remove(stringPlateLicense); //PlateLicenses.Add(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss:fff", CultureInfo.InvariantCulture)); PlateLicenses.Add(stringPlateLicense, DateTime.Now); NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.Now)); //NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss:fff", CultureInfo.InvariantCulture))); } else { logger.Debug("Ignored the plate{0}, because it was already caught at:{1}", stringPlateLicense, PlateLicenses[stringPlateLicense]); } } else { //PlateLicenses.Add(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss:fff", CultureInfo.InvariantCulture)); //NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss:fff", CultureInfo.InvariantCulture))); PlateLicenses.Add(stringPlateLicense, DateTime.Now); NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.Now)); } } } catch (Exception e) { logger.Error("HKPlateRecongnizeApp:ProcessCommAlarm_ITSPlate exception happened: " + e.Message); } } /// /// Remove the plates which have existing for a long time /// private void CheckAndRemoveTheExpiredPlate() { var platesToRemove = new List(); lock (PlateLicenses) { foreach (var plateLicense in PlateLicenses) { if ((DateTime.Now - plateLicense.Value).TotalMinutes > CarPlateTimeOut) platesToRemove.Add(plateLicense.Key); } } //remove the plates if (platesToRemove.Count > 0) { logger.Debug("{0} plates will be removed", platesToRemove.Count); lock (PlateLicenses) { foreach (var plate in platesToRemove) if (PlateLicenses.ContainsKey(plate)) PlateLicenses.Remove(plate); } } } public async Task Stop() { if (_lHandle > 0) CHCNetSDK.NET_DVR_CloseAlarmChan_V30(_lHandle); if (_luser > 0) CHCNetSDK.NET_DVR_Logout(_luser); //release resoures for SDKS CHCNetSDK.NET_DVR_Cleanup(); return true; } public void Init(IEnumerable processors) { logger.Info("HKPlateRecongnizeApp:Init"); } } }