前言
本来一个很简单的SDK接口对接,折腾了好久;总结下原因有:
海康的SDK底层使用C++写的,我不熟悉C++;
海康Java源码示例写的是一个Swing桌面应用,我需要的是嵌入到web项目;
海康《设备网络SDK使用手册》中的示例是用C++写的;并且会出现使用手册和Java源码示例版本不匹配的情况(用手册版本高于Java源码示例版)
我的需求
使用海康认证对面设备在刷身份证和人脸识别通过后,取到身份证信息和人脸照片并且传到页面上。
代码处理
1.将SDK开发包【库文件】里的HCNetSDK.dll、HCCore.dll、PlayCtrl.dll、SuperRender.dll、AudioRender.dll、HCNetSDKCom文件夹、ssleay32.dll、libeay32.dll文件均要加载到程序里面,【HCNetSDKCom文件夹】(包含里面的功能组件dll库文件)需要和HCNetSDK.dll、HCCore.dll一起加载,放在同一个目录下(我的事springboot项目,放在resources目录下),且HCNetSDKCom文件夹名不能修改。
2.HCNetSDK INSTANCE = (HCNetSDK) Native.loadLibrary(“E:\project\renliantext\src\main\resources\lib\HCNetSDK”, HCNetSDK.class);修改HCnetSDK的引入路径。
3.将路径:将Demo示例\4- Java 开发示例\2-报警布防监听\AlarmJavaDemo\src\alarmjavademo的demo包移植过来并且解决报错信息,就是导入包的问题 手动引入jar包或者从MAVEN再导入就好
4,写Service类,调用接口进行注册,布防。布防成功后设置报警回调函数
5,写serviceimp类,就是报警回调函数的实现在里面取到想要的数据。
下面是代码
Service类源码 里面有main方法 可以先进行测试看时候可以注册成功已经设置回到函数成功
package com.jeeplus.modules.xwhj.haikang.service;
import com.jeeplus.modules.xwhj.haikang.HCNetSDK;
import com.jeeplus.modules.xwhj.haikang.Haikangimp;
import org.springframework.stereotype.Service;
import javax.swing.*;
import java.util.Timer;
import java.util.TimerTask;
@Service
public class Haikang {
static HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;
static HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//设备登录信息
static HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息
static String m_sDeviceIP="192.168.19.249";//已登录设备的IP地址
static String m_sUsername="admin";//设备用户名
static String m_sPassword="xwkj0713";//设备密码
static int lUserID;//用户句柄
static int lAlarmHandle;//报警布防句柄
static int lListenHandle;//报警监听句柄
/* FMSGCallBack fMSFCallBack;//报警回调函数实现
AlarmJavaDemoView.FMSGCallBack_V31 fMSFCallBack_V31;*///报警回调函数实现
public void logintext() {//GEN-FIRST:event_jButtonLoginActionPerformed
hCNetSDK.NET_DVR_Init();
//注册之前先注销已注册的用户,预览情况下不可注销
if (lUserID > -1) {
//先注销
hCNetSDK.NET_DVR_Logout(lUserID);
lUserID = -1;
}
//注册
m_sDeviceIP = "192.168.19.249";
m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());
m_sUsername = "admin";
m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());
m_sPassword ="xwkj0713";
m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());
m_strLoginInfo.wPort =8000;
lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
if (lUserID == -1) {
JOptionPane.showMessageDialog(null, "false,错误号:" + hCNetSDK.NET_DVR_GetLastError());
} else {
JOptionPane.showMessageDialog(null, "success");
}
}
/*public static void main(String[] args){
*//* while (1>0){
System.out.println("~");
}*//*
};*/
public void initMemberFlowUpload(){
// 初始化
hCNetSDK.NET_DVR_Init();
//设置连接时间与重连时间
hCNetSDK.NET_DVR_SetConnectTime(2000, 1);
hCNetSDK.NET_DVR_SetReconnect(10000, true);
// 注册设备-登录参数,包括设备地址、登录用户、密码等
m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());
m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());
m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());
m_strLoginInfo.wPort = 8000;
m_strLoginInfo.bUseAsynLogin = false; //是否异步登录:0- 否,1- 是
//设备信息, 输出参数
final int lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo,m_strDeviceInfo);
System.out.println("lUserID.size-->" + lUserID);
if(lUserID< 0){
System.out.println("hCNetSDK.NET_DVR_Login_V30()"+"\n" +hCNetSDK.NET_DVR_GetErrorMsg(null));
hCNetSDK.NET_DVR_Cleanup();
System.out.println("注册失败");
return;
}
//设置报警回调函数
boolean callflag = hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(new Haikangimp(),null );
if(callflag){
System.out.println("callback----success+设置回调函数成功");
}
//启用布防-其他报警布防参数不需要设置,不支持
HCNetSDK.NET_DVR_SETUPALARM_PARAM lpSetupParam = new HCNetSDK.NET_DVR_SETUPALARM_PARAM();
lpSetupParam.byLevel=0;
lpSetupParam.write();
final int lAlarmHandle = hCNetSDK.NET_DVR_SetupAlarmChan_V41(lUserID,lpSetupParam);
if (lAlarmHandle< 0)
{
System.out.println("NET_DVR_SetupAlarmChan_V41 error, %d\n"+hCNetSDK.NET_DVR_GetLastError());
hCNetSDK.NET_DVR_Logout(lUserID);
hCNetSDK.NET_DVR_Cleanup();
System.out.println("布防失败");
}
else {
System.out.println("bufangsuccess++布防成功");
}
//等待过程中,如果设备上传报警信息,在报警回调函数里面接收和处理报警信息
Timer timer =new Timer();// 实例化Timer类
timer.schedule(new TimerTask() {
public void run() {
//撤销布防上传通道
if (! hCNetSDK.NET_DVR_CloseAlarmChan_V30(lAlarmHandle))
{
System.out.println("! hCNetSDK.NET_DVR_CloseAlarmChan_V31(lAlarmHandle)\n"+ hCNetSDK.NET_DVR_GetLastError() +"\n" +hCNetSDK.NET_DVR_GetErrorMsg(null) );
hCNetSDK.NET_DVR_Logout(lUserID);
hCNetSDK. NET_DVR_Cleanup();
return;
}
//注销用户
hCNetSDK.NET_DVR_Logout(lUserID);
//释放SDK资源
hCNetSDK.NET_DVR_Cleanup();
this.cancel();
System.gc();//主动回收垃圾
}
}, 100 * 60 * 1000 );// 这里毫秒
}}
源码2报警回调函数实现
package com.jeeplus.modules.xwhj.haikang;
import com.jeeplus.common.utils.CacheUtils;
import com.jeeplus.modules.xwhj.familyinfo.entity.TFamilyinfo;
import com.sun.jna.Pointer;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Haikangimp implements HCNetSDK.FMSGCallBack_V31 {
@Override
public boolean invoke(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser ) {
TFamilyinfo tFamilyinfo=new TFamilyinfo();
String sAlarmType = new String();
String[] newRow = new String[3];
Date today = new Date();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String[] sIP = new String[2];
switch (lCommand){
case HCNetSDK.COMM_ID_INFO_ALARM: ///身份证信息*/
HCNetSDK.NET_DVR_ID_CARD_INFO_ALARM strIDCardInfo = new HCNetSDK.NET_DVR_ID_CARD_INFO_ALARM();
strIDCardInfo.write();
Pointer pIDCardInfo = strIDCardInfo.getPointer();
pIDCardInfo.write(0, pAlarmInfo.getByteArray(0, strIDCardInfo.size()), 0, strIDCardInfo.size());
strIDCardInfo.read();
sAlarmType = sAlarmType + ":门禁身份证刷卡信息,身份证号码:" + new String(strIDCardInfo.struIDCardCfg.byIDNum).trim() + ",姓名:" +
new String(strIDCardInfo.struIDCardCfg.byName).trim() + ",报警主类型:" + strIDCardInfo.dwMajor + ",报警次类型:" + strIDCardInfo.dwMinor;
String s =new String(strIDCardInfo.struIDCardCfg.byName).trim();
/*System.out.println(sAlarmType);*/
newRow[0] = dateFormat.format(today);
String name=new String(strIDCardInfo.struIDCardCfg.byName).trim();
String cardnum=new String(strIDCardInfo.struIDCardCfg.byIDNum).trim();
String address=new String(strIDCardInfo.struIDCardCfg.byAddr).trim();
tFamilyinfo.setHjyhm(name);
tFamilyinfo.setZjhm(cardnum);
tFamilyinfo.setJtmx(address);
//报警类型
newRow[1] = sAlarmType;
//报警设备IP地址
sIP = new String(pAlarmer.sDeviceIP).split("\0", 2);
newRow[2] = sIP[0];
//身份证图片
if (strIDCardInfo.dwPicDataLen > 0) {
SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
String newName = sf.format(new Date());
FileOutputStream fout;
try {
String filename ="D:\\Program Files\\TortoiseSVN\\bin\\xbhj\\userfiles\\1\\xwhj\\" +
newName + "_IDInfoPic.jpg";
fout = new FileOutputStream(filename);
//将字节写入文件
long offset = 0;
ByteBuffer buffers = strIDCardInfo.pPicData.getByteBuffer(offset, strIDCardInfo.dwPicDataLen);
byte[] bytes = new byte[strIDCardInfo.dwPicDataLen];
buffers.rewind();
buffers.get(bytes);
fout.write(bytes);
fout.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (strIDCardInfo.dwCapturePicDataLen > 0) {
SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
String newName = sf.format(new Date());
FileOutputStream fout;
try {
String filename = "D:\\Program Files\\TortoiseSVN\\bin\\xbhj\\userfiles\\1\\xwhj\\" +
newName + "_IDInfoCapturePic.jpg";
tFamilyinfo.setYhzp(filename);
fout = new FileOutputStream(filename);
//将字节写入文件
long offset = 0;
ByteBuffer buffers = strIDCardInfo.pCapturePicData.getByteBuffer(offset, strIDCardInfo.dwCapturePicDataLen);
byte[] bytes = new byte[strIDCardInfo.dwCapturePicDataLen];
buffers.rewind();
buffers.get(bytes);
fout.write(bytes);
fout.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
CacheUtils.put("hkidcard",tFamilyinfo);
}
break;
}
return true;
}}
以上就是全部的代码里 里面有我的项目里的一些实体类可以忽略不计。改成你自己的就好了 遇到问题的小伙伴可以看下 提供一个思路 ,毕竟对接的时候我也是一脸懵逼 研究了一段时间看到别人写的一些东西才调通设备,希望能给其他人一些帮助~~就这吧 加油了嘿嘿 = =