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");
}
}
}