目录
1.介绍
海康威视官方有对应的demo,该文章只是总结!
使用的wpf,数据库用的是mysql
主要使用的字段:文章中出现的base_user_extend是表名
字段 | 类型 | 注释 |
UserCode | varchar | 员工编号 |
UserName | varchar | 员工姓名 |
user_key | varchar | |
hk_face_info | blob | 人脸信息 |
2.登录设备
- 在App.config中添加配置:设备IP,设备管理员账号,管理员账号密码
- 登录设备
<!--质量信息到人人脸设备地址 -->
<add key="sDeviceAddress" value="192.168.0.1"/>
<!--质量信息到人人脸识别登陆名 -->
<add key="sUserName" value="admin"/>
<!--质量信息到人人脸识别登陆密码 -->
<add key="sPassword" value="hk12356"/>
public static int m_UserID = -1;
public void Login()
{
if (m_UserID >= 0)
{
CHCNetSDK.NET_DVR_Logout_V30(m_UserID);
m_UserID = -1;
}
CHCNetSDK.NET_DVR_USER_LOGIN_INFO struLoginInfo = new CHCNetSDK.NET_DVR_USER_LOGIN_INFO();
CHCNetSDK.NET_DVR_DEVICEINFO_V40 struDeviceInfoV40 = new CHCNetSDK.NET_DVR_DEVICEINFO_V40();
struDeviceInfoV40.struDeviceV30.sSerialNumber = new byte[CHCNetSDK.SERIALNO_LEN];
struLoginInfo.sDeviceAddress = Global.GetAppSetting("sDeviceAddress");
struLoginInfo.sUserName = Global.GetAppSetting("sUserName");
struLoginInfo.sPassword = Global.GetAppSetting("sPassword");
ushort.TryParse("8000", out struLoginInfo.wPort);
int lUserID = -1;
lUserID = CHCNetSDK.NET_DVR_Login_V40(ref struLoginInfo, ref struDeviceInfoV40);
if (lUserID >= 0)
{
m_UserID = lUserID;
Logger.Log("人脸 :Login Successful");
}
else
{
lblMsg.Content = "同步设备信息失败";
uint nErr = CHCNetSDK.NET_DVR_GetLastError();
if (nErr == CHCNetSDK.NET_DVR_PASSWORD_ERROR)
{
Logger.Error("user name or password error!");
if (1 == struDeviceInfoV40.bySupportLock)
{
Logger.Error(string.Format("Left {0} try opportunity", struDeviceInfoV40.byRetryLoginTime));
}
}
else if (nErr == CHCNetSDK.NET_DVR_USER_LOCKED)
{
if (1 == struDeviceInfoV40.bySupportLock)
{
Logger.Error(string.Format("user is locked, the remaining lock time is {0}", struDeviceInfoV40.dwSurplusLockTime));
}
}
else
{
Logger.Error($"Login fail error:{nErr} ");
}
}
}
3.退出登录设备
/// <summary>
/// 退出设备
/// </summary>
public void Logout()
{
try
{
if (m_UserID >= 0)
{
CHCNetSDK.NET_DVR_Logout_V30(m_UserID);
m_UserID = -1;
}
}
catch (Exception ex)
{
Logger.Error("人脸退出登录异常:" + ex.Message);
}
}
4.云端→设备
- 在设备创建用户,使用了BackgroundWorker
public QTM_FaceInfo() { InitializeComponent(); bw.WorkerReportsProgress = true; bw.DoWork += new DoWorkEventHandler(bw_DoWork); bw.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgessChanged);//进度改变事件 bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);//进度完成事件 } //远端→设备 按钮代码 private void Viewbtn_Click(object sender, RoutedEventArgs e) { try { lblMsg.Visibility = Visibility.Visible; lblMsg.Content = "正在同步"; Login(); if (m_UserID >= 0) { bw.RunWorkerAsync(); } else { lblMsg.Content = "同步失败,无法打开设备端口"; } } catch (Exception ex) { Logger.Error("同步异常:" + ex.Message); lblMsg.Content = "同步异常,无法打开设备端口"; } } #region BackgroundWorker private int syncStatus = 0; void bw_DoWork(object sender, DoWorkEventArgs e) { #region 创建用户 //校验url信息 bw.ReportProgress(1); int jindu = 1; bw.ReportProgress(jindu); List<base_user_extend> facelst = fingerlst.Where(x => !string.IsNullOrEmpty(x.hk_face_info)).ToList(); foreach (var item in facelst) { if (string.IsNullOrEmpty(item.user_key)) { Logger.Error($"同步人脸信息:user_key为空!{item.UserCode}==={item.UserName}"); } else { jindu = jindu + 1; int isuser = CreateUserInfo(item); if (syncStatus == 200) { int iscard = CreateCardInfo(item); } if (syncStatus == 200) { SendFaceData(item); } if (jindu < 9) { bw.ReportProgress(jindu); } } } #endregion } private void bgWorker_ProgessChanged(object sender, ProgressChangedEventArgs e) { if (e.ProgressPercentage == 1) { lblMsg.Content = "正在校验人脸设备信息,进度:10%"; } if (e.ProgressPercentage > 1 && e.ProgressPercentage <= 8) { lblMsg.Content = $"正在将设备信息传输到设备,进度:{e.ProgressPercentage * 10}%"; } if (e.ProgressPercentage == 9) { lblMsg.Content = "正在同步,进度:30%"; } } void bw_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) { switch (syncStatus) { case 200: lblMsg.Content = "同步人脸设备信息成功!"; break; case 0: lblMsg.Content = "同步人脸设备信息失败!"; break; case -1: lblMsg.Content = "同步人脸设备信息:设备创建用户失败!"; break; case -2: lblMsg.Content = "同步人脸设备信息:设备创建用户卡号失败!"; break; case -3: lblMsg.Content = "同步人脸设备信息:人脸数据添加失败!"; break; } Logout(); //lblMsg.Visibility = Visibility.Collapsed; } #endregion public Int32 m_lSetUserCfgHandle = -1; public Int32 m_lSetCardCfgHandle = -1; private int m_lSetFaceCfgHandle = -1; private int m_lGetFaceCfgHandle = -1; private List<base_user_extend> fingerlst; private BackgroundWorker bw = new BackgroundWorker(); #region 创建用户 /// <summary> /// 校验创建用户url /// </summary> private int CreateUserInfo(base_user_extend info) { if (m_lSetUserCfgHandle != -1) { if (CHCNetSDK.NET_DVR_StopRemoteConfig(m_lSetUserCfgHandle)) { m_lSetUserCfgHandle = -1; } } string sURL = "PUT /ISAPI/AccessControl/UserInfo/SetUp?format=json"; IntPtr ptrURL = Marshal.StringToHGlobalAnsi(sURL); m_lSetUserCfgHandle = CHCNetSDK.NET_DVR_StartRemoteConfig(m_UserID, CHCNetSDK.NET_DVR_JSON_CONFIG, ptrURL, sURL.Length, null, IntPtr.Zero); if (m_lSetUserCfgHandle < 0) { Logger.Error("NET_DVR_StartRemoteConfig fail [url:PUT /ISAPI/AccessControl/UserInfo/SetUp?format=json] error:" + CHCNetSDK.NET_DVR_GetLastError()); Marshal.FreeHGlobal(ptrURL); syncStatus = -1; return -1; } else { SendUserInfo(info); Marshal.FreeHGlobal(ptrURL); return 200; } } /// <summary> /// 在设备上创建用户信息 /// </summary> /// <param name="info"></param> private void SendUserInfo(base_user_extend info) { syncStatus = -1; CUserInfoCfg JsonUserInfo = new CUserInfoCfg(); JsonUserInfo.UserInfo = new CUserInfo(); JsonUserInfo.UserInfo.employeeNo = info.UserCode; JsonUserInfo.UserInfo.name = info.UserName; JsonUserInfo.UserInfo.userType = "normal"; JsonUserInfo.UserInfo.Valid = new CValid(); JsonUserInfo.UserInfo.Valid.enable = true; JsonUserInfo.UserInfo.Valid.beginTime = "2017-08-01T17:30:08"; JsonUserInfo.UserInfo.Valid.endTime = "2037-12-31T23:59:59"; JsonUserInfo.UserInfo.Valid.timeType = "local"; JsonUserInfo.UserInfo.RightPlan = new List<CRightPlan>(); JsonUserInfo.UserInfo.doorRight = "1"; //一定要设置,不设置人脸设置会提示没权限 CRightPlan JsonRightPlan = new CRightPlan(); JsonRightPlan.doorNo = 1; JsonRightPlan.planTemplateNo = "1"; JsonUserInfo.UserInfo.RightPlan.Add(JsonRightPlan); // JsonUserInfo.UserInfo.userVerifyMode = "face"; string strJsonUserInfo = JsonConvert.SerializeObject(JsonUserInfo, Formatting.Indented, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore }); byte[] byJsonUserInfo = System.Text.Encoding.UTF8.GetBytes(strJsonUserInfo); IntPtr ptrJsonUserInfo = Marshal.StringToHGlobalAnsi(strJsonUserInfo); Marshal.Copy(byJsonUserInfo, 0, ptrJsonUserInfo, byJsonUserInfo.Length); IntPtr ptrJsonData = Marshal.AllocHGlobal(1024); for (int i = 0; i < 1024; i++) { Marshal.WriteByte(ptrJsonData, i, 0); } int dwState = (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_SUCCESS; uint dwReturned = 0; while (true) { dwState = CHCNetSDK.NET_DVR_SendWithRecvRemoteConfig(m_lSetUserCfgHandle, ptrJsonUserInfo, (uint)byJsonUserInfo.Length, ptrJsonData, 1024, ref dwReturned); string strJsonData = Marshal.PtrToStringAnsi(ptrJsonData); if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_NEEDWAIT) { Thread.Sleep(10); continue; } else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_FAILED) { Logger.Error("Set User Fail error:" + CHCNetSDK.NET_DVR_GetLastError()); break; } else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_SUCCESS) { //返回NET_SDK_CONFIG_STATUS_SUCCESS代表流程走通了,但并不代表下发成功,比如有些设备可能因为人员已存在等原因下发失败,所以需要解析Json报文 CResponseStatus JsonResponseStatus = new CResponseStatus(); JsonResponseStatus = JsonConvert.DeserializeObject<CResponseStatus>(strJsonData); if (JsonResponseStatus.statusCode == 1) { syncStatus = 200; Logger.Log("Set User Success"); } else { Logger.Error("Set User Fail, ResponseStatus.statusCode" + JsonResponseStatus.statusCode); } break; } else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_FINISH) { //下发人员时:dwState其实不会走到这里,因为设备不知道我们会下发多少个人,所以长连接需要我们主动关闭 Logger.Log("Set User Finish"); break; } else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_EXCEPTION) { Logger.Error("Set User Exception error:" + CHCNetSDK.NET_DVR_GetLastError()); break; } else { Logger.Error("unknown Status error:" + CHCNetSDK.NET_DVR_GetLastError()); break; } } if (m_lSetUserCfgHandle != -1) { if (CHCNetSDK.NET_DVR_StopRemoteConfig(m_lSetUserCfgHandle)) { m_lSetUserCfgHandle = -1; } } Marshal.FreeHGlobal(ptrJsonUserInfo); Marshal.FreeHGlobal(ptrJsonData); } #endregion
- 给创建的用户创建卡片
#region 创建卡片 private int CreateCardInfo(base_user_extend info) { if (m_lSetCardCfgHandle != -1) { if (CHCNetSDK.NET_DVR_StopRemoteConfig(m_lSetCardCfgHandle)) { m_lSetCardCfgHandle = -1; } } string sURL = "PUT /ISAPI/AccessControl/CardInfo/SetUp?format=json"; IntPtr ptrURL = Marshal.StringToHGlobalAnsi(sURL); m_lSetCardCfgHandle = CHCNetSDK.NET_DVR_StartRemoteConfig(m_UserID, CHCNetSDK.NET_DVR_JSON_CONFIG, ptrURL, sURL.Length, null, IntPtr.Zero); if (m_lSetCardCfgHandle < 0) { MessageBox.Show("NET_DVR_StartRemoteConfig fail [url:PUT /ISAPI/AccessControl/CardInfo/SetUp?format=json] error:" + CHCNetSDK.NET_DVR_GetLastError()); Marshal.FreeHGlobal(ptrURL); syncStatus = -2; return -1; } else { SendCardData(info); Marshal.FreeHGlobal(ptrURL); return 200; } } /// <summary> /// 创建用户卡号 /// </summary> /// <param name="info"></param> private void SendCardData(base_user_extend info) { syncStatus = -2; CCardInfoCfg JsonCardInfo = new CCardInfoCfg(); JsonCardInfo.CardInfo = new CCardInfo(); JsonCardInfo.CardInfo.employeeNo = info.UserCode; JsonCardInfo.CardInfo.cardNo = info.user_key; JsonCardInfo.CardInfo.cardType = "normalCard"; string strJsonCardInfo = JsonConvert.SerializeObject(JsonCardInfo, Formatting.Indented, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore }); IntPtr ptrJsonCardInfo = Marshal.StringToHGlobalAnsi(strJsonCardInfo); IntPtr ptrJsonData = Marshal.AllocHGlobal(1024); for (int i = 0; i < 1024; i++) { Marshal.WriteByte(ptrJsonData, i, 0); } int dwState = 0; uint dwReturned = 0; while (true) { dwState = CHCNetSDK.NET_DVR_SendWithRecvRemoteConfig(m_lSetCardCfgHandle, ptrJsonCardInfo, (uint)strJsonCardInfo.Length, ptrJsonData, 1024, ref dwReturned); string strJsonData = Marshal.PtrToStringAnsi(ptrJsonData); if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_NEEDWAIT) { Thread.Sleep(10); continue; } else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_FAILED) { Logger.Error("Set Card Fail error:" + CHCNetSDK.NET_DVR_GetLastError()); break; } else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_SUCCESS) { CResponseStatus JsonResponseStatus = new CResponseStatus(); JsonResponseStatus = JsonConvert.DeserializeObject<CResponseStatus>(strJsonData); if (JsonResponseStatus.statusCode == 1) { Logger.Log("Set Card Success"); syncStatus = 200; } else { Logger.Error("Set Card Fail, ResponseStatus.statusCode:" + JsonResponseStatus.statusCode); } break; } else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_EXCEPTION) { Logger.Error("Set Card Exception error:" + CHCNetSDK.NET_DVR_GetLastError()); break; } else { Logger.Error("unknown Status error:" + CHCNetSDK.NET_DVR_GetLastError()); break; } } if (m_lSetCardCfgHandle != -1) { if (CHCNetSDK.NET_DVR_StopRemoteConfig(m_lSetCardCfgHandle)) { m_lSetCardCfgHandle = -1; } } Marshal.FreeHGlobal(ptrJsonCardInfo); Marshal.FreeHGlobal(ptrJsonData); } #endregion
- 给创建的用户添加人脸信息
#region 下发人脸信息到设备 private void SendFaceData(base_user_extend info) { syncStatus = -3; string filename = Base64StringToImage(info.hk_face_info); string sURL = "PUT /ISAPI/Intelligent/FDLib/FDSetUp?format=json"; IntPtr ptrURL = Marshal.StringToHGlobalAnsi(sURL); m_lSetFaceCfgHandle = CHCNetSDK.NET_DVR_StartRemoteConfig(m_UserID, CHCNetSDK.NET_DVR_FACE_DATA_RECORD, ptrURL, sURL.Length, null, IntPtr.Zero); if (m_lSetFaceCfgHandle == -1) { Marshal.FreeHGlobal(ptrURL); Logger.Error("NET_DVR_StartRemoteConfig fail [url:PUT /ISAPI/Intelligent/FDLib/FDSetUp?format=json] error:" + CHCNetSDK.NET_DVR_GetLastError()); return; } Marshal.FreeHGlobal(ptrURL); CSetFaceDataCond JsonSetFaceDataCond = new CSetFaceDataCond(); JsonSetFaceDataCond.faceLibType = "blackFD"; JsonSetFaceDataCond.FDID = "1"; JsonSetFaceDataCond.FPID = info.UserCode; string strJsonSearchFaceDataCond = JsonConvert.SerializeObject(JsonSetFaceDataCond, Formatting.Indented, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore }); IntPtr ptrJsonSearchFaceDataCond = Marshal.StringToHGlobalAnsi(strJsonSearchFaceDataCond); CHCNetSDK.NET_DVR_JSON_DATA_CFG struJsonDataCfg = new CHCNetSDK.NET_DVR_JSON_DATA_CFG(); struJsonDataCfg.dwSize = (uint)Marshal.SizeOf(struJsonDataCfg); struJsonDataCfg.lpJsonData = ptrJsonSearchFaceDataCond; struJsonDataCfg.dwJsonDataSize = (uint)strJsonSearchFaceDataCond.Length; if (!File.Exists(filename)) { Logger.Error("The picture does not exist!"); Marshal.FreeHGlobal(ptrJsonSearchFaceDataCond); return; } FileStream fs = new FileStream(filename, FileMode.OpenOrCreate); if (0 == fs.Length) { Logger.Error("The picture is 0k,please input another picture!"); Marshal.FreeHGlobal(ptrJsonSearchFaceDataCond); fs.Close(); return; } if (200 * 1024 < fs.Length) { Logger.Error("The picture is larger than 200k,please input another picture!"); Marshal.FreeHGlobal(ptrJsonSearchFaceDataCond); fs.Close(); return; } struJsonDataCfg.dwPicDataSize = (uint)fs.Length; int iLen = (int)struJsonDataCfg.dwPicDataSize; byte[] by = new byte[iLen]; struJsonDataCfg.lpPicData = Marshal.AllocHGlobal(iLen); fs.Read(by, 0, iLen); Marshal.Copy(by, 0, struJsonDataCfg.lpPicData, iLen); fs.Close(); IntPtr ptrJsonDataCfg = Marshal.AllocHGlobal((int)struJsonDataCfg.dwSize); Marshal.StructureToPtr(struJsonDataCfg, ptrJsonDataCfg, false); IntPtr ptrJsonResponseStatus = Marshal.AllocHGlobal(1024); for (int i = 0; i < 1024; i++) { Marshal.WriteByte(ptrJsonResponseStatus, i, 0); } int dwState = (int)CHCNetSDK.NET_SDK_GET_NEXT_STATUS_SUCCESS; uint dwReturned = 0; while (true) { dwState = CHCNetSDK.NET_DVR_SendWithRecvRemoteConfig(m_lSetFaceCfgHandle, ptrJsonDataCfg, struJsonDataCfg.dwSize, ptrJsonResponseStatus, 1024, ref dwReturned); string strResponseStatus = Marshal.PtrToStringAnsi(ptrJsonResponseStatus); if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_NEEDWAIT) { Thread.Sleep(10); continue; } else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_FAILED) { Logger.Error("Set Face Error:" + CHCNetSDK.NET_DVR_GetLastError()); break; } else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_SUCCESS) { CResponseStatus JsonResponseStatus = new CResponseStatus(); JsonResponseStatus = JsonConvert.DeserializeObject<CResponseStatus>(strResponseStatus); if (JsonResponseStatus.statusCode == 1) { syncStatus = 200; Logger.Log("Set Face Success"); } else { Logger.Error("Set Face Fail, ResponseStatus.statusCode = " + JsonResponseStatus.statusCode); } break; } else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_EXCEPTION) { Logger.Error("Set Face Exception Error:" + CHCNetSDK.NET_DVR_GetLastError()); break; } else { Logger.Error("unknown Status Error:" + CHCNetSDK.NET_DVR_GetLastError()); break; } } if (m_lSetFaceCfgHandle > 0) { CHCNetSDK.NET_DVR_StopRemoteConfig(m_lSetFaceCfgHandle); m_lSetFaceCfgHandle = -1; } Marshal.FreeHGlobal(ptrJsonDataCfg); Marshal.FreeHGlobal(ptrJsonResponseStatus); } #endregion