HkCarPlateRecognizeApp.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.IO;
  5. using System.Runtime.InteropServices;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using Edge.Core.Processor;using Edge.Core.IndustryStandardInterface.Pump;
  9. using Edge.Core.UniversalApi;
  10. using Newtonsoft.Json;
  11. namespace HKCarPlateRecognize_App
  12. {
  13. public class HkCarPlateRecognizeApp : IAppProcessor
  14. {
  15. public string MetaConfigName { get; set; }
  16. private bool etcCarPlate = false;
  17. private string DeviceAddress { get; set; }
  18. private int Port { get; set; }
  19. private string UserName { get; set; }
  20. private string PassWord { get; set; }
  21. private int CarPlateTimeOut { get; set; }
  22. /// <summary>
  23. /// 接口返回-1表示登录失败,其他值表示返回的用户ID值
  24. /// </summary>
  25. private int _luser = -1;
  26. /// <summary>
  27. /// -1表示失败,其他值作为NET_DVR_CloseAlarmChan_V30函数的句柄参数
  28. /// </summary>
  29. private int _lHandle = -1;
  30. public event EventHandler<PlateCatchedEventArgs> NewCarPlateCatched;
  31. private Dictionary<string, DateTime> PlateLicenses = new Dictionary<string, DateTime>();
  32. private static NLog.Logger logger = NLog.LogManager.LoadConfiguration("NLog.config").GetLogger("HkPalteRecognize");
  33. private CHCNetSDK.MSGCallBack_V31 m_falarmData_V31 = null;
  34. /// <summary>
  35. ///
  36. /// </summary>
  37. /// <param name="deviceAddress">IP address of the device</param>
  38. /// <param name="port">device's listening port</param>
  39. /// <param name="userName"> user name used to login device</param>
  40. /// <param name="passWord">password used to login device</param>
  41. public HkCarPlateRecognizeApp(string deviceAddress, int port, string userName, string passWord, int carPlateTimeOut, string etcCarPlate)
  42. {
  43. DeviceAddress = deviceAddress;
  44. Port = port;
  45. UserName = userName;
  46. PassWord = passWord;
  47. CarPlateTimeOut = carPlateTimeOut;
  48. this.etcCarPlate = bool.Parse(etcCarPlate);
  49. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
  50. }
  51. [UniversalApi(Description = "Param ciphertext is the EtcCarPlateCatched information was encrypted with AES")]
  52. public async Task<bool> NewCarPlateCatchedAsync(string ciphertext)
  53. {
  54. try
  55. {
  56. string password = "27c8fa1a46baabda88d2b977de272c1f";
  57. string content = AesHelper.DecodeAES(ciphertext, password);
  58. var etcCarPlate = JsonConvert.DeserializeObject<EtcCarPlateCatched>(content);
  59. logger.Debug($"NewCarPlateCatchedAsync with etcCarPlate {content}");
  60. NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(etcCarPlate.carNumber, DateTime.ParseExact(etcCarPlate.timeStamp, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture)));
  61. }
  62. catch (Exception ex)
  63. {
  64. logger.Error($"In NewCarPlateCatchedAsync {ex}");
  65. return await Task.FromResult(false);
  66. }
  67. return await Task.FromResult(true);
  68. }
  69. public async Task<bool> Start()
  70. {
  71. bool started = false;
  72. if (etcCarPlate)
  73. return await Task.FromResult(true);
  74. var m_bInitSDK = CHCNetSDK.NET_DVR_Init();
  75. if (m_falarmData_V31 == null)
  76. m_falarmData_V31 = new CHCNetSDK.MSGCallBack_V31(MessageCallback);
  77. // CHCNetSDK.NET_DVR_SetExceptionCallBack_V30(0, IntPtr.Zero, ExceptionCallBack, IntPtr.Zero);
  78. if (m_bInitSDK)
  79. {
  80. if (CHCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(m_falarmData_V31, IntPtr.Zero))
  81. {
  82. //_luser = NetDVRLoginV40;
  83. _luser = NetDVRLoginV30();
  84. if (_luser < 0)
  85. {
  86. uint error = CHCNetSDK.NET_DVR_GetLastError();
  87. logger.Info("Failed to login device, CHCNetSDK.NET_DVR_Login_V40, err:{0}", error);
  88. if (error == CHCNetSDK.NET_DVR_NETWORK_FAIL_CONNECT)
  89. {
  90. System.Timers.Timer reloginTimer = new System.Timers.Timer();
  91. reloginTimer.Elapsed += (a, b) =>
  92. {
  93. logger.Debug("relogin timer elapsed");
  94. reloginTimer.Enabled = false;
  95. //var stringPlateLicense = DateTime.Now.Millisecond.ToString(CultureInfo.InvariantCulture);
  96. //NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.Now));
  97. //_luser = NetDVRLoginV40();
  98. _luser = NetDVRLoginV30();
  99. if (_luser < 0)
  100. {
  101. uint e = CHCNetSDK.NET_DVR_GetLastError();
  102. var b1 = e == CHCNetSDK.NET_DVR_NETWORK_FAIL_CONNECT ? reloginTimer.Enabled = true : reloginTimer.Enabled = false;
  103. }
  104. else
  105. {
  106. _lHandle = SetupAlarmChan_V41();
  107. if (_lHandle < 0)
  108. {
  109. var e = CHCNetSDK.NET_DVR_GetLastError();
  110. }
  111. }
  112. };
  113. reloginTimer.Interval = 60000;
  114. reloginTimer.Start();
  115. }
  116. }
  117. else
  118. {
  119. _lHandle = SetupAlarmChan_V41();
  120. if (_lHandle < 0)
  121. {
  122. uint error = CHCNetSDK.NET_DVR_GetLastError();
  123. logger.Info("error happens when call SetupAlarmChan_V41, err:{0}", error);
  124. }
  125. else
  126. {
  127. logger.Info("HK PlateRecognizeApp started successfully");
  128. started = true;
  129. }
  130. }
  131. }
  132. }
  133. return started;
  134. }
  135. public int NetDVRLoginV40()
  136. {
  137. CHCNetSDK.NET_DVR_USER_LOGIN_INFO struLoginInfo = new CHCNetSDK.NET_DVR_USER_LOGIN_INFO();
  138. struLoginInfo.bUseAsynLogin = 0; //同步登录方式
  139. struLoginInfo.sDeviceAddress = DeviceAddress;
  140. struLoginInfo.wPort = (ushort)Port;
  141. struLoginInfo.sUserName = UserName;
  142. struLoginInfo.sPassword = PassWord;
  143. CHCNetSDK.NET_DVR_DEVICEINFO_V40 deviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V40();
  144. return CHCNetSDK.NET_DVR_Login_V40(struLoginInfo, deviceInfo);
  145. }
  146. public int NetDVRLoginV30()
  147. {
  148. logger.Debug("NetDVRLoginV30 new device info");
  149. CHCNetSDK.NET_DVR_DEVICEINFO_V30 deviceInfov30 = new CHCNetSDK.NET_DVR_DEVICEINFO_V30();
  150. logger.Debug("NetDVRLoginV30 Login_V30");
  151. return CHCNetSDK.NET_DVR_Login_V30(DeviceAddress, Port, UserName, PassWord, ref deviceInfov30);
  152. }
  153. public int SetupAlarmChan_V41()
  154. {
  155. CHCNetSDK.NET_DVR_SETUPALARM_PARAM alarmParam = new CHCNetSDK.NET_DVR_SETUPALARM_PARAM();
  156. alarmParam.dwSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(CHCNetSDK.NET_DVR_SETUPALARM_PARAM));
  157. alarmParam.byLevel = 1; //布防优先级:0- 一等级(高),1- 二等级(中)
  158. alarmParam.byAlarmInfoType = 1; //上传报警信息类型: 0- 老报警信息(NET_DVR_PLATE_RESULT), 1- 新报警信息(NET_ITS_PLATE_RESULT)
  159. return CHCNetSDK.NET_DVR_SetupAlarmChan_V41(_luser, ref alarmParam);
  160. }
  161. public bool MessageCallback(int lCommand, ref CHCNetSDK.NET_DVR_ALARMER pAlarmer, IntPtr pAlarmInfo, uint dwBufLen, IntPtr pUser)
  162. {
  163. logger.Info("HkPlateRecognizeApp:MessageCallback, message received:{0}", lCommand);
  164. switch (lCommand)
  165. {
  166. case CHCNetSDK.COMM_UPLOAD_PLATE_RESULT:
  167. ProcessCommAlarm_Plate(ref pAlarmer, pAlarmInfo, dwBufLen, pUser);
  168. break;
  169. case CHCNetSDK.COMM_ITS_PLATE_RESULT:
  170. ProcessCommAlarm_ITSPlate(ref pAlarmer, pAlarmInfo, dwBufLen, pUser);
  171. break;
  172. default:
  173. break;
  174. }
  175. return true;
  176. }
  177. public void ExceptionCallBack(uint dwType, int lUserID, int lHandle, IntPtr pUser)
  178. {
  179. logger.Info("HkPlateRecognizeApp::ExceptionCallBack");
  180. }
  181. private void ProcessCommAlarm_Plate(ref CHCNetSDK.NET_DVR_ALARMER pAlarmer, IntPtr pAlarmInfo, uint dwBufLen, IntPtr pUser)
  182. {
  183. try
  184. {
  185. CHCNetSDK.NET_DVR_PLATE_RESULT struPlateResultInfo = new CHCNetSDK.NET_DVR_PLATE_RESULT();
  186. uint dwSize = (uint)Marshal.SizeOf(struPlateResultInfo);
  187. struPlateResultInfo = (CHCNetSDK.NET_DVR_PLATE_RESULT)Marshal.PtrToStructure(pAlarmInfo, typeof(CHCNetSDK.NET_DVR_PLATE_RESULT));
  188. //保存抓拍图片
  189. string str = "";
  190. if (struPlateResultInfo.byResultType == 1 && struPlateResultInfo.dwPicLen != 0)
  191. {
  192. str = ".\\picture\\Plate_UserID_" + pAlarmer.lUserID + "_近景图.jpg";
  193. FileStream fs = new FileStream(str, FileMode.Create);
  194. int iLen = (int)struPlateResultInfo.dwPicLen;
  195. byte[] by = new byte[iLen];
  196. Marshal.Copy(struPlateResultInfo.pBuffer1, by, 0, iLen);
  197. fs.Write(by, 0, iLen);
  198. fs.Close();
  199. }
  200. if (struPlateResultInfo.dwPicPlateLen != 0)
  201. {
  202. str = ".\\picture\\Plate_UserID_" + pAlarmer.lUserID + "_车牌图.jpg";
  203. FileStream fs = new FileStream(str, FileMode.Create);
  204. int iLen = (int)struPlateResultInfo.dwPicPlateLen;
  205. byte[] by = new byte[iLen];
  206. Marshal.Copy(struPlateResultInfo.pBuffer2, by, 0, iLen);
  207. fs.Write(by, 0, iLen);
  208. fs.Close();
  209. }
  210. if (struPlateResultInfo.dwFarCarPicLen != 0)
  211. {
  212. str = ".\\picture\\Plate_UserID_" + pAlarmer.lUserID + "_远景图.jpg";
  213. FileStream fs = new FileStream(str, FileMode.Create);
  214. int iLen = (int)struPlateResultInfo.dwFarCarPicLen;
  215. byte[] by = new byte[iLen];
  216. Marshal.Copy(struPlateResultInfo.pBuffer5, by, 0, iLen);
  217. fs.Write(by, 0, iLen);
  218. fs.Close();
  219. }
  220. //报警设备IP地址
  221. string strIP = System.Text.Encoding.UTF8.GetString(pAlarmer.sDeviceIP).TrimEnd('\0');
  222. //抓拍时间:年月日时分秒
  223. string strTimeYear = System.Text.Encoding.UTF8.GetString(struPlateResultInfo.byAbsTime).TrimEnd('\0');
  224. //上传结果
  225. string stringPlateLicense = System.Text.Encoding.GetEncoding("GBK").GetString(struPlateResultInfo.struPlateInfo.sLicense).TrimEnd('\0');
  226. string stringAlarm = "抓拍上传," + "车牌:" + stringPlateLicense + ",车辆序号:" + struPlateResultInfo.struVehicleInfo.dwIndex;
  227. logger.Info("HkPlateRecognizeApp::ProcessCommAlarm_Plate strTimeTear:{0},stringPlateLicense{1}", strTimeYear, stringPlateLicense);
  228. lock (PlateLicenses)
  229. {
  230. if (PlateLicenses.ContainsKey(stringPlateLicense))
  231. {
  232. TimeSpan timeSpan = DateTime.Now - PlateLicenses[stringPlateLicense];
  233. if (timeSpan.TotalMinutes > 30)
  234. {
  235. PlateLicenses.Remove(stringPlateLicense);
  236. PlateLicenses.Add(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture));
  237. NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture)));
  238. }
  239. }
  240. else
  241. {
  242. PlateLicenses.Add(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture));
  243. NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture)));
  244. }
  245. }
  246. //if (InvokeRequired)
  247. //{
  248. // object[] paras = new object[3];
  249. // paras[0] = strTimeYear; //当前PC系统时间为DateTime.Now.ToString();
  250. // paras[1] = strIP;
  251. // paras[2] = stringAlarm;
  252. // listViewAlarmInfo.BeginInvoke(new UpdateListBoxCallback(UpdateClientList), paras);
  253. //}
  254. //else
  255. //{
  256. // //创建该控件的主线程直接更新信息列表
  257. // UpdateClientList(DateTime.Now.ToString(), strIP, stringAlarm);
  258. //}
  259. }
  260. catch (Exception e)
  261. {
  262. logger.Info("Exception happened in ProcessCommAlarm_Plate:" + e.Message);
  263. //throw;
  264. }
  265. }
  266. private void ProcessCommAlarm_ITSPlate(ref CHCNetSDK.NET_DVR_ALARMER pAlarmer, IntPtr pAlarmInfo, uint dwBufLen, IntPtr pUser)
  267. {
  268. try
  269. {
  270. //check the existing plates to see if anything has existing for a long time, then remove it
  271. CheckAndRemoveTheExpiredPlate();
  272. CHCNetSDK.NET_ITS_PLATE_RESULT struITSPlateResult = new CHCNetSDK.NET_ITS_PLATE_RESULT();
  273. uint dwSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(struITSPlateResult);
  274. struITSPlateResult = (CHCNetSDK.NET_ITS_PLATE_RESULT)Marshal.PtrToStructure(pAlarmInfo, typeof(CHCNetSDK.NET_ITS_PLATE_RESULT));
  275. logger.Debug("plate info catched --1");
  276. //报警设备IP地址
  277. string strIP = System.Text.Encoding.UTF8.GetString(pAlarmer.sDeviceIP).TrimEnd('\0');
  278. logger.Debug("The IP address of the device:" + strIP);
  279. //抓拍时间:年月日时分秒
  280. string strTimeYear = string.Format("{0:D4}", struITSPlateResult.struSnapFirstPicTime.wYear) +
  281. string.Format("{0:D2}", struITSPlateResult.struSnapFirstPicTime.byMonth) +
  282. string.Format("{0:D2}", struITSPlateResult.struSnapFirstPicTime.byDay) + " "
  283. + string.Format("{0:D2}", struITSPlateResult.struSnapFirstPicTime.byHour) + ":"
  284. + string.Format("{0:D2}", struITSPlateResult.struSnapFirstPicTime.byMinute) + ":"
  285. + string.Format("{0:D2}", struITSPlateResult.struSnapFirstPicTime.bySecond) + ":"
  286. + string.Format("{0:D3}", struITSPlateResult.struSnapFirstPicTime.wMilliSec);
  287. //上传结果
  288. string stringPlateLicense = System.Text.Encoding.GetEncoding("GBK").GetString(struITSPlateResult.struPlateInfo.sLicense).TrimEnd('\0').Substring(1);
  289. string stringAlarm = "抓拍上传," + "车牌:" + stringPlateLicense + ",车辆序号:" + struITSPlateResult.struVehicleInfo.dwIndex;
  290. logger.Info("HkPlateRecognizeApp::ProcessCommAlarm_ITSPlate strTimeTear:{0},stringPlateLicense{1}", strTimeYear, stringPlateLicense);
  291. lock (PlateLicenses)
  292. {
  293. if (PlateLicenses.ContainsKey(stringPlateLicense))
  294. {
  295. TimeSpan timeSpan = DateTime.Now - PlateLicenses[stringPlateLicense];
  296. logger.Debug("PlateLicenses contains:{0} plates,time{1},timespan minutes{2}", PlateLicenses.Count, PlateLicenses[stringPlateLicense], timeSpan.Minutes);
  297. if (timeSpan.TotalMinutes > CarPlateTimeOut)
  298. {
  299. logger.Debug("new plate over {0} min", CarPlateTimeOut);
  300. PlateLicenses.Remove(stringPlateLicense);
  301. //PlateLicenses.Add(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss:fff", CultureInfo.InvariantCulture));
  302. PlateLicenses.Add(stringPlateLicense, DateTime.Now);
  303. NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.Now));
  304. //NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss:fff", CultureInfo.InvariantCulture)));
  305. }
  306. else
  307. {
  308. logger.Debug("Ignored the plate{0}, because it was already caught at:{1}", stringPlateLicense, PlateLicenses[stringPlateLicense]);
  309. }
  310. }
  311. else
  312. {
  313. //PlateLicenses.Add(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss:fff", CultureInfo.InvariantCulture));
  314. //NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.ParseExact(strTimeYear, "yyyyMMdd HH:mm:ss:fff", CultureInfo.InvariantCulture)));
  315. PlateLicenses.Add(stringPlateLicense, DateTime.Now);
  316. NewCarPlateCatched?.Invoke(this, new PlateCatchedEventArgs(stringPlateLicense, DateTime.Now));
  317. }
  318. }
  319. }
  320. catch (Exception e)
  321. {
  322. logger.Error("HKPlateRecongnizeApp:ProcessCommAlarm_ITSPlate exception happened: " + e.Message);
  323. }
  324. }
  325. /// <summary>
  326. /// Remove the plates which have existing for a long time
  327. /// </summary>
  328. private void CheckAndRemoveTheExpiredPlate()
  329. {
  330. var platesToRemove = new List<string>();
  331. lock (PlateLicenses)
  332. {
  333. foreach (var plateLicense in PlateLicenses)
  334. {
  335. if ((DateTime.Now - plateLicense.Value).TotalMinutes > CarPlateTimeOut)
  336. platesToRemove.Add(plateLicense.Key);
  337. }
  338. }
  339. //remove the plates
  340. if (platesToRemove.Count > 0)
  341. {
  342. logger.Debug("{0} plates will be removed", platesToRemove.Count);
  343. lock (PlateLicenses)
  344. {
  345. foreach (var plate in platesToRemove)
  346. if (PlateLicenses.ContainsKey(plate)) PlateLicenses.Remove(plate);
  347. }
  348. }
  349. }
  350. public async Task<bool> Stop()
  351. {
  352. if (_lHandle > 0)
  353. CHCNetSDK.NET_DVR_CloseAlarmChan_V30(_lHandle);
  354. if (_luser > 0)
  355. CHCNetSDK.NET_DVR_Logout(_luser);
  356. //release resoures for SDKS
  357. CHCNetSDK.NET_DVR_Cleanup();
  358. return true;
  359. }
  360. public void Init(IEnumerable<IProcessor> processors)
  361. {
  362. logger.Info("HKPlateRecongnizeApp:Init");
  363. }
  364. }
  365. }