最近做门禁的集成,突然感觉海康这个东西挺有意思的,于是记录一下。
好了废话不多说,开始上环境、代码
本集成是海康-设备网络集成(以人为中心)
环境:windows
开发工具:IDEA
JDK版本:JDK-11.0.12
海康jar包:怎么引入都行(本地引入、maven上传到私服)
链接:https://pan.baidu.com/s/12limkwExPqn9q-vUc6zA6g?pwd=xr0s
提取码:xr0s
海康库:
windows环境:链接:https://pan.baidu.com/s/10iADLziw-jdxWd9Awmuu4Q?pwd=o26k
提取码:o26k
linux环境: 链接:https://pan.baidu.com/s/10iADLziw-jdxWd9Awmuu4Q?pwd=o26k
提取码:o26k
布防整体流程:
我们就以此流程开始:
/** * 海康设备提前操作方法(第一步) */ private Integer preparation(String ip, String user, String password, Integer port, Boolean isLogin) { // 创建操作类 createHkSdkInstance(); // 加载组件库 loadLinuxSystem(SystemHkSelect.isLinux()); // 初始话操作类 HK_NET_SDK.NET_DVR_Init(); log.info("海康设备初始化成功!"); // 操作完成,首先登录设备 return loginAccessHk(ip, user, password, ObjectUtils.isNotEmpty(port) ? Short.parseShort(port.toString()) : (short) 8000; }
参数解释:
ip:门禁设备的IP地址
user:门禁设备的管理员
password:管理员密码
port:端口 默认8000
isLogin:暂时无用
/** * 创建海康SDK操作类(第二步) */ private void createHkSdkInstance() { try { // 海康SDK操作类 if (HK_NET_SDK == null) { log.info("海康SDK操作类为空,开始创建海康SDK操作类"); HK_NET_SDK = (HCNetSDK) Native.loadLibrary(stringDllPath, HCNetSDK.class); log.info("海康SDK操作类创建成功"); } else { log.info("海康SDK操作类不为空,无需创建"); } } catch (Exception e) { throw exception(UNKNOWN_OPERATING_SYSTEM); } }
参数解释:
stringDllPath:海康库的加载地址(配置成海康库里HCNetSDK.dll这个文件的路径)
windows环境:C:\\Users\\PinRu\\Desktop\\CH-HCNetSDKV6.1.9.48_build20230410_win64\\lib\\HCNetSDK.dll
linux环境:C:\\Users\\PinRu\\Desktop\\CH-HCNetSDKV6.1.9.48_build20230410_linux64\\lib\\libhcnetsdk.so
/** * linux系统建议调用以下接口加载组件库(win下不需要操作)(第三步) */ private void loadLinuxSystem(Boolean isLinux) { // linux系统建议调用以下接口加载组件库(win下不需要操作) if (isLinux) { log.info("加载海康组件库" + isLinux); HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256); HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256); //这里是库的绝对路径,请根据实际情况修改,注意改路径必须有访问权限 // cry组件库 System.arraycopy(stringCryPath.getBytes(), 0, ptrByteArray1.byValue, 0, stringCryPath.length()); ptrByteArray1.write(); HK_NET_SDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer()); System.arraycopy(stringSslPath.getBytes(), 0, ptrByteArray2.byValue, 0, stringSslPath.length()); ptrByteArray2.write(); // ssl组件库 HK_NET_SDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer()); HCNetSDK.NET_DVR_LOCAL_SDK_PATH strComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH(); // lib组件库 System.arraycopy(stringLibPath.getBytes(), 0, strComPath.sPath, 0, stringLibPath.length()); strComPath.write(); HK_NET_SDK.NET_DVR_SetSDKInitCfg(2, strComPath.getPointer()); } }
参数解释:
isLinusx:是否是linux环境(win开发环境下,直接写成false)
stringCryPath:cry路径 默认路径:/lib/libcrypto.so.1.1
stringSslPath:ssl路径 默认路径:/lib/libssl.so.1.1
stringLibPath:lib库路径 默认路径:/lib/
public static Integer loginAccessHk(String deviceIp, String userName, String password, short port) { //注册(登录海康设备) //设备登录信息 HCNetSDK.NET_DVR_USER_LOGIN_INFO strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO(); //设备ip地址 strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN]; System.arraycopy(deviceIp.getBytes(), 0, strLoginInfo.sDeviceAddress, 0, deviceIp.length()); //设备用户名 strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN]; System.arraycopy(userName.getBytes(), 0, strLoginInfo.sUserName, 0, userName.length()); //设备密码 strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN]; System.arraycopy(password.getBytes(), 0, strLoginInfo.sPassword, 0, password.length()); //sdk端口 strLoginInfo.wPort = port; //是否异步登录:0- 否,1- 是 strLoginInfo.bUseAsynLogin = false; strLoginInfo.write(); //设备信息 HCNetSDK.NET_DVR_DEVICEINFO_V40 strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40(); AtomicInteger userId = new AtomicInteger(-1); userId.set(HK_NET_SDK.NET_DVR_Login_V40(strLoginInfo, strDeviceInfo)); if (userId.get() == -1) { return HK_NET_SDK.NET_DVR_GetLastError(); } else { log.info("设备登录成功,用户ID:" + userId); strDeviceInfo.read(); CHAR_ENCODE_TYPE = strDeviceInfo.byCharEncodeType; } return userId.get(); }
参数解释:
deviceIp:门禁设备的IP地址
userName:门禁设备的管理员
password:管理员密码
port:端口 默认8000
public Boolean equipmentRegistration() { // 设备准备工作(必须调用) try { Integer userId = preparation("", "", "", null, null); // 回调函数 if (callBack == null) { callBack = new HkEquipmentCallBack(); } // 设置回调 HK_NET_SDK.NET_DVR_SetDVRMessageCallBack_V50(0, callBack, null); //布防参数 HCNetSDK.NET_DVR_SETUPALARM_PARAM_V50 param = new HCNetSDK.NET_DVR_SETUPALARM_PARAM_V50(); param.dwSize = param.size(); //布防等级 param.byLevel = 0; // 智能交通报警信息上传类型:0- 老报警信息(NET_DVR_PLATE_RESULT),1- 新报警信息(NET_ITS_PLATE_RESULT) param.byAlarmInfoType = 1; //布防类型:0-客户端布防,1-实时布防 param.byDeployType = 1; param.write(); // 设备布防 int v41 = HK_NET_SDK.NET_DVR_SetupAlarmChan_V50(userId, param, null, 0); if (v41 < 0) { log.info("设备布防失败,布防结果:" + v41); // 布防失败 logout(userId); } } catch (Exception e) { log.error("门禁设备设置门禁布防失败!错误信息:", e); return Boolean.FALSE; } log.info("布防成功"); return Boolean.TRUE; }
HkEquipmentCallBack 布防回调:
import cn.hutool.extra.spring.SpringUtil; import com.sun.jna.Pointer; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; /** * 布防回调的入口 */ @Component @Slf4j public class HkEquipmentCallBack implements HCNetSDK.FMSGCallBack_V31 { @Override public boolean invoke(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlar, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) { log.info("hk alarm call back,type:{}", lCommand); // 轮询处理事件回调 switch (lCommand) { case HCNetSDK.COMM_ALARM: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_TRADEINFO: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_ALARM_V30: break; case HCNetSDK.COMM_ALARM_V40: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_ALARM_RULE: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_IPCCFG: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_UPLOAD_FACESNAP_RESULT: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_SNAP_MATCH_ALARM: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_ALARM_ACS: // 门禁设备主机报警 EquipmentHandle handle = SpringUtil.getBean(EquipmentHandle.class); handle.equipmentHandleMethod(pAlar, pAlarmInfo); break; case HCNetSDK.COMM_ID_INFO_ALARM: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_VCA_ALARM: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_ISAPI_ALARM: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_ALARMHOST_CID_ALARM: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_SWITCH_ALARM: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_ALARMHOST_EXCEPTION: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_ALARMHOST_OPERATEEVENT_ALARM: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_ALARMHOST_ALARMOUTSTATUS: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_UPLOAD_VIDEO_INTERCOM_EVENT: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_ALARM_VIDEO_INTERCOM: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_THERMOMETRY_ALARM: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_FIREDETECTION_ALARM: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_THERMOMETRY_DIFF_ALARM: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_UPLOAD_AIOP_VIDEO: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_UPLOAD_AIOP_POLLING_SNAP: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_UPLOAD_AIOP_POLLING_VIDEO: saveEquipmentLog(pAlar); break; case HCNetSDK.COMM_IPC_AUXALARM_RESULT: saveEquipmentLog(pAlar); break; default: break; } return false; } private void saveEquipmentLog(HCNetSDK.NET_DVR_ALARMER pAlar) { // 给个回调,嗨嗨嗨 log.info("此报警暂时不需要做何处理,休息一下吧~~~~"); } }
布防回调目前我这只用到主机报警
报警处理类EquipmentHandle :
import cn.hutool.core.codec.Base64Encoder; import cn.hutool.extra.spring.SpringUtil; import com.sun.jna.Pointer; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import java.nio.Buffer; import java.nio.ByteBuffer; /** * 门禁设备布防报警-回调的处理类 */ @Component @Slf4j public class EquipmentHandle { public void equipmentHandleMethod(HCNetSDK.NET_DVR_ALARMER pAlar, Pointer pAlarmInfo) { // 设备主机事件 HCNetSDK.NET_DVR_ACS_ALARM_INFO strAcsInfo = new HCNetSDK.NET_DVR_ACS_ALARM_INFO(); strAcsInfo.write(); Pointer pAcsInfo = strAcsInfo.getPointer(); pAcsInfo.write(0, pAlarmInfo.getByteArray(0, strAcsInfo.size()), 0, strAcsInfo.size()); strAcsInfo.read(); // 门禁事件的详细信息解析,通过主次类型的可以判断当前的具体门禁类型,例如(主类型:0X5 次类型:0x4b 表示人脸认证通过, // 主类型:0X5 次类型:0x4c 表示人脸认证失败) saveEquipmentLogAcs(pAlar, strAcsInfo); } private void saveEquipmentLogAcs(HCNetSDK.NET_DVR_ALARMER pAlar, HCNetSDK.NET_DVR_ACS_ALARM_INFO strAcsInfo) { // 获取事件的类型 String messageMain = HkEventEnum.getMessageByCode(strAcsInfo.dwMajor); String message = HkEventEnum.getMessageByCode(strAcsInfo.dwMinor); if (ObjectUtils.isEmpty(messageMain) && ObjectUtils.isEmpty(message)) { // 主级事件为null,则不记录 return; } if (HkEventEnum.Hk_Event_84.getEventType().equals(strAcsInfo.dwMinor) || HkEventEnum.Hk_Event_85.getEventType().equals(strAcsInfo.dwMinor) || HkEventEnum.Hk_Event_1024.getEventType().equals(strAcsInfo.dwMinor)) { // 屏蔽部分非法事件 return; } // 获取卡号 String byCardNo = new String(strAcsInfo.struAcsEventInfo.byCardNo).trim(); log.info("卡号:" + byCardNo); // 获取卡类型 人员类型(0:白名单,1:访客,2:黑名单) String byCardType = String.valueOf(strAcsInfo.struAcsEventInfo.byCardType); // 设备唯一编码 String byDeviceNo = String.valueOf(strAcsInfo.struAcsEventInfo.byDeviceNo); // 通进类型(0:入场,1:离场) String dwDoorNo = String.valueOf(strAcsInfo.struAcsEventInfo.dwDoorNo); // 给个回调,嗨嗨嗨 HkCallBackBuilderVo builder = new HkCallBackBuilderVo(pAlar); log.info("获取到的本机IP地址:{}", builder.sDeviceIpStr); // 人员工号,需要关联查询 if (ObjectUtils.isNotEmpty(builder.sDeviceIpStr)) { // 获取设备详情 // 取值类型 HkAdapter hkAdapter = SpringUtil.getBean(HkAdapter.class); log.info("当前回调的事件编号:{}", strAcsInfo.struAcsEventInfo.dwSerialNo); String employeeNo = hkAdapter.selectEmployeeNo(strAcsInfo.struAcsEventInfo.dwSerialNo, null); log.info("获取到的用户编码:{}", employeeNo); // 获取人员名称 if (ObjectUtils.isNotEmpty(employeeNo)) { String userName = hkAdapter.selectUserName(employeeNo); log.info("获取到的用户名称:{}", userName); } else { String cardNo = hkAdapter.selectEmployeeNo(strAcsInfo.struAcsEventInfo.dwSerialNo, EnableFlagEnum.ENABLE_STATUS_1.getCode()); log.info("获取到的用户卡号:{}", cardNo); } // 人脸图片数据 String dataBytes = null; if (strAcsInfo.dwPicDataLen > 0) { long offset = 0; Buffer buffers = strAcsInfo.pPicData.getByteBuffer(offset, strAcsInfo.dwPicDataLen); // 转换成64单独存储 dataBytes = assembleDataBytes(buffers, strAcsInfo.dwPicDataLen); } log.info("获取到的人脸图片数据:{}", dataBytes); } } private String assembleDataBytes(Buffer buffers, int dwSnapPicLen) { byte[] bytes = new byte[dwSnapPicLen]; buffers.rewind(); ((ByteBuffer) buffers).get(bytes); // 人脸图片数据 return (ObjectUtils.isNotEmpty(bytes) ? "data:image/jpg;base64," + Base64Encoder.encode(bytes) : StringUtils.EMPTY); }
EquipmentHandle - HkCallBackBuilderVo:
import lombok.Data; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import java.nio.charset.StandardCharsets; /** * description */ @Data public class HkCallBackBuilderVo { /** * userid是否有效 0-无效,1-有效 */ public byte byUserIdValid; /** * 序列号是否有效 0-无效,1-有效 */ public byte bySerialValid; /** * 版本号是否有效 0-无效,1-有效 */ public byte byVersionValid; /** * 设备名字是否有效 0-无效,1-有效 */ public byte byDeviceNameValid; /** * MAC地址是否有效 0-无效,1-有效 */ public byte byMacAddrValid; /** * login端口是否有效 0-无效,1-有效 */ public byte byLinkPortValid; /** * 设备IP是否有效 0-无效,1-有效 */ public byte byDeviceIpValid; /** * socket ip是否有效 0-无效,1-有效 */ public byte bySocketIpValid; /** * NET_DVR_Login()返回值, 布防时有效 */ public int lUserId; /** * 序列号 */ public String sSerialNumberStr; /** * 版本信息 高16位表示主版本,低16位表示次版本 */ public int dwDeviceVersion; /** * 设备名字 */ public String sDeviceNameStr; /** * MAC地址 */ public String byMacAddrStr; /** * link port */ public short wLinkPort; /** * IP地址 */ public String sDeviceIpStr; /** * 报警主动上传时的socket IP地址 */ public String sSocketIpStr; /** * Ip协议 0-IPV4, 1-IPV6 */ public byte byIpProtocol; /** * 主动推送 */ public String byRes2Str; public HkCallBackBuilderVo(HCNetSDK.NET_DVR_ALARMER pAlar) { byUserIdValid = pAlar.byUserIDValid; bySerialValid = pAlar.bySerialValid; byVersionValid = pAlar.byVersionValid; byDeviceNameValid = pAlar.byDeviceNameValid; byMacAddrValid = pAlar.byMacAddrValid; byLinkPortValid = pAlar.byLinkPortValid; byDeviceIpValid = pAlar.byDeviceIPValid; bySocketIpValid = pAlar.bySocketIPValid; lUserId = pAlar.lUserID; sSerialNumberStr = ObjectUtils.isNotEmpty(pAlar.sSerialNumber) ? StringUtils.toEncodedString(pAlar.sSerialNumber, StandardCharsets.UTF_8) : StringUtils.EMPTY; dwDeviceVersion = pAlar.dwDeviceVersion; sDeviceNameStr = ObjectUtils.isNotEmpty(pAlar.sDeviceName)? StringUtils.toEncodedString(pAlar.sDeviceName, StandardCharsets.UTF_8) : StringUtils.EMPTY; byMacAddrStr = ObjectUtils.isNotEmpty(pAlar.byMacAddr)? StringUtils.toEncodedString(pAlar.byMacAddr, StandardCharsets.UTF_8) : StringUtils.EMPTY; wLinkPort = pAlar.wLinkPort; sDeviceIpStr = ObjectUtils.isNotEmpty(pAlar.sDeviceIP)? StringUtils.toEncodedString(pAlar.sDeviceIP, StandardCharsets.UTF_8) : StringUtils.EMPTY; sSocketIpStr = ObjectUtils.isNotEmpty(pAlar.sSocketIP)? StringUtils.toEncodedString(pAlar.sSocketIP, StandardCharsets.UTF_8) : StringUtils.EMPTY; byIpProtocol = pAlar.byIpProtocol; byRes2Str = ObjectUtils.isNotEmpty(pAlar.byRes2)? StringUtils.toEncodedString(pAlar.byRes2, StandardCharsets.UTF_8) : StringUtils.EMPTY; }
海康适配器(包含设备注册-用户注册-用户登出-布防-查询用户-查询事件):
/** * 海康适配器 */ @Component @Slf4j public class HkAdapter { // 1. 海康的门禁 || 后端需要先引入海康操作库,目前不在项目内集成海康操作库,是通过海康开放平台 // 【https://open.hikvision.com/download/5cda567cf47ae80dd41a54b3?type=10】获取的操作库, // 不同的服务器须集成不同的操作库,否则会出现异常 // 2. Windows开发时需要将“库文件”文件夹中的HCNetSDK.dll、HCCore.dll、HCNetSDKCom文件夹、libssl-1_1-x64.dll、 // libcrypto-1_1-x64.dll、hlog.dll、hpr.dll、zlib1.dll等文件拷贝到lib文件夹下,HCNetSDKCom文件夹(包含里面的功能组件dll库文件) // 需要和HCNetSDK.dll、HCCore.dll一起加载,放在同一个目录下,且HCNetSDKCom文件夹名不能修改。如果自行开发软件不能正常实现相应功能, // 而且程序没有指定加载的dll库路径,请在程序运行的情况下尝试删除HCNetSDK.dll。如果可以删除,说明程序可能调用到系统盘 // Windows->System32目录下的dll文件,建议删除或者更新该目录下的相关dll文件;如果不能删除,dll文件右键选择属性确认SDK库版本。 // // 3. Linux开发时需要将“库文件”文件夹中libhcnetsdk.so、libHCCore.so、libcrypto.so.1.1、libssl.so.1.1、libhpr.so、 // libz.so等文件拷贝到lib文件夹下。HCNetSDKCom文件夹(包含里面的功能组件dll库文件)需要和libhcnetsdk.so、 // libHCCore.so一起加载,放在同一个目录下,且HCNetSDKCom文件夹名不能修改。如果库文件加载有问题,初始化失败, // 也可以尝试将SDK所在路径添加到LD_LIBRARY_PATH环境变量中。 // 4. 具体请参考海康的开发文档以及文件包结构 /** * 组件库路径 */ private String stringDllPath; /** * cry路径 */ private String stringCryPath; /** * ssl路径 */ private String stringSslPath; /** * lib路径 */ private String stringLibPath; /** * 海康SDK */ static HCNetSDK HK_NET_SDK = null; /** * 海康设备字符集 */ static int CHAR_ENCODE_TYPE = 0; /** * 全局回调 */ static HkEquipmentCallBack callBack; /** * 海康设备提前操作方法(定时任务登录认证使用) * * @param equipment 门禁基本信息 */ public Integer preparationScheduled(GuardEquipmentRespVO equipment) { try { // 设置回调 // 当返回值是true时,说明host是可用的,false则不可。 try { boolean status = InetAddress.getByName(equipment.getAddressIp()).isReachable(3000); if (!status) { return EntranceConstants.NET_DVR_NETWORK_FAIL_CONNECT; } } catch (IOException e) { return EntranceConstants.NET_DVR_NETWORK_FAIL_CONNECT; } return EntranceConstants.NET_DVR_NO_ERROR; } catch (Exception e) { log.error("海康设备加载失败!错误信息:", e); // 错误状态默认给离线 return EntranceConstants.NET_DVR_NETWORK_FAIL_CONNECT; } } /** * 海康设备提前操作方法(必须提前调用) * * @param equipment 门禁基本信息 */ private Integer preparation(String ip, String user, String password, Integer port, Boolean isLogin) { // 创建操作类 createHkSdkInstance(); // 加载组件库 loadLinuxSystem(SystemHkSelect.isLinux()); // 初始话操作类 HK_NET_SDK.NET_DVR_Init(); log.info("海康设备初始化成功!"); // 操作完成,首先登录设备 return loginAccessHk(ip, user, password, ObjectUtils.isNotEmpty(port) ? Short.parseShort(port.toString()) : (short) 8000); } /** * 创建海康SDK操作类,调用海康SDK接口 * 根据不同操作系统选择不同的库文件和库路径 * 固定方式不可更改 */ private void createHkSdkInstance() { try { // 海康SDK操作类 if (HK_NET_SDK == null) { log.info("海康SDK操作类为空,开始创建海康SDK操作类"); HK_NET_SDK = (HCNetSDK) Native.loadLibrary(stringDllPath, HCNetSDK.class); log.info("海康SDK操作类创建成功"); } else { log.info("海康SDK操作类不为空,无需创建"); } } catch (Exception e) { log.info("海康SDK操作类创建失败"); } } private void loadLinuxSystem(Boolean isLinux) { // linux系统建议调用以下接口加载组件库(win下不需要操作) if (isLinux) { log.info("加载海康组件库" + isLinux); HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256); HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256); //这里是库的绝对路径,请根据实际情况修改,注意改路径必须有访问权限 // cry组件库 System.arraycopy(stringCryPath.getBytes(), 0, ptrByteArray1.byValue, 0, stringCryPath.length()); ptrByteArray1.write(); HK_NET_SDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer()); System.arraycopy(stringSslPath.getBytes(), 0, ptrByteArray2.byValue, 0, stringSslPath.length()); ptrByteArray2.write(); // ssl组件库 HK_NET_SDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer()); HCNetSDK.NET_DVR_LOCAL_SDK_PATH strComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH(); // lib组件库 System.arraycopy(stringLibPath.getBytes(), 0, strComPath.sPath, 0, stringLibPath.length()); strComPath.write(); HK_NET_SDK.NET_DVR_SetSDKInitCfg(2, strComPath.getPointer()); } } public static Integer loginAccessHk(String deviceIp, String userName, String password, short port) { //注册(登录海康设备) //设备登录信息 HCNetSDK.NET_DVR_USER_LOGIN_INFO strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO(); //设备ip地址 strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN]; System.arraycopy(deviceIp.getBytes(), 0, strLoginInfo.sDeviceAddress, 0, deviceIp.length()); //设备用户名 strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN]; System.arraycopy(userName.getBytes(), 0, strLoginInfo.sUserName, 0, userName.length()); //设备密码 strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN]; System.arraycopy(password.getBytes(), 0, strLoginInfo.sPassword, 0, password.length()); //sdk端口 strLoginInfo.wPort = port; //是否异步登录:0- 否,1- 是 strLoginInfo.bUseAsynLogin = false; strLoginInfo.write(); //设备信息 HCNetSDK.NET_DVR_DEVICEINFO_V40 strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40(); AtomicInteger userId = new AtomicInteger(-1); userId.set(HK_NET_SDK.NET_DVR_Login_V40(strLoginInfo, strDeviceInfo)); if (userId.get() == -1) { return HK_NET_SDK.NET_DVR_GetLastError(); } else { log.info("设备登录成功,用户ID:" + userId); strDeviceInfo.read(); CHAR_ENCODE_TYPE = strDeviceInfo.byCharEncodeType; } return userId.get(); } /** * 登出(完成工作指令时,必须调用) */ public static void logout(Integer userId) { // 登出和清理设备操作缓存,释放SDK资源 if (userId >= 0) { if (!HK_NET_SDK.NET_DVR_Logout(userId)) { log.info("设备注销失败"); } log.info("设备注销成功,用户ID:" + userId); } // 释放SDK资源,防止一直占用内存 HK_NET_SDK.NET_DVR_Cleanup(); } /** * 查询人员信息(预留) */ public String eventUserInfo(Integer userId, String equipmentNo) { //数组 HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(1024); //字符串拷贝到数组中 System.arraycopy(USER_INFO.getBytes(), 0, ptrByteArray.byValue, 0, USER_INFO.length()); ptrByteArray.write(); int lHandler = HK_NET_SDK.NET_DVR_StartRemoteConfig(userId, HCNetSDK.NET_DVR_JSON_CONFIG, ptrByteArray.getPointer(), USER_INFO.length(), null, null); if (lHandler < 0) { log.info("SearchUserInfo失败,错误码为" + HK_NET_SDK.NET_DVR_GetLastError()); } else { //组装查询的JSON报文,这边查询的是所有的人员 JSONObject jsonObject = new JSONObject(); JSONObject jsonSearchCond = new JSONObject(); // 查询指定的工号人员信息 JSONArray jsonArray = new JSONArray(); if (ObjectUtils.isNotEmpty(equipmentNo)) { jsonArray.put(new JSONObject().set("employeeNo", equipmentNo)); } jsonSearchCond.set("EmployeeNoList", jsonArray); jsonSearchCond.set("searchID", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN)); jsonSearchCond.set("searchResultPosition", 0); jsonSearchCond.set("maxResults", 50); jsonObject.set("UserInfoSearchCond", jsonSearchCond); String toString = jsonObject.toString(); log.info("查询的json报文:" + toString); //把string传递到Byte数组中,后续用.getPointer()方法传入指针地址中。 HCNetSDK.BYTE_ARRAY byteArray = new HCNetSDK.BYTE_ARRAY(toString.length()); System.arraycopy(toString.getBytes(), 0, byteArray.byValue, 0, toString.length()); byteArray.write(); //定义接收结果的结构体 HCNetSDK.BYTE_ARRAY ptrOutBuff = new HCNetSDK.BYTE_ARRAY(10 * 1024); IntByReference pInt = new IntByReference(0); while (true) { int dwState = HK_NET_SDK.NET_DVR_SendWithRecvRemoteConfig(lHandler, byteArray.getPointer(), toString.length(), ptrOutBuff.getPointer(), 20 * 1024, pInt); if (dwState == -1) { break; } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEED_WAIT) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) { log.error("查询人员失败"); break; } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) { log.error("查询人员异常"); break; } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) { ptrOutBuff.read(); String trim = new String(ptrOutBuff.byValue).trim(); // 得到的人员信息 try { ObjectMapper objectMapper = new ObjectMapper(); JsonNode rootNode = objectMapper.readTree(trim); JsonNode userInfoSearch = rootNode.get("UserInfoSearch"); JsonNode userInfo = userInfoSearch.get("UserInfo"); JsonNode userInfoOne = userInfo.get(0); JsonNode name = userInfoOne.get("name"); return name.asText(); } catch (JsonProcessingException e) { return StringUtils.EMPTY; } } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) { log.error("获取人员完成"); break; } } if (!HK_NET_SDK.NET_DVR_StopRemoteConfig(lHandler)) { log.error("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + HK_NET_SDK.NET_DVR_GetLastError()); } else { log.info("NET_DVR_StopRemoteConfig接口成功"); } } return null; } public String selectEmployeeNo(Integer dwSerialNo, Integer isCard) { // 设备准备工作(必须调用) Integer userId = preparation("", "", "", null, null); // 通过事件类型拿到人员工号 String event = searchAllEvent(userId, dwSerialNo, isCard); // 句柄完成,登出设备(必须调用) logout(userId); return event; } public String selectUserName(String employeeNo) { // 设备准备工作(必须调用) Integer userId = preparation("", "", "", null, null); // 通过事件类型拿到人员工号 String event = eventUserInfo(userId, employeeNo); // 句柄完成,登出设备(必须调用) logout(userId); return event; } public static String searchAllEvent(int userId, Integer dwSerialNo, Integer isCard) { //事件条数 int i = 0; HCNetSDK.NET_DVR_ACS_EVENT_COND strAcsEventCond = new HCNetSDK.NET_DVR_ACS_EVENT_COND(); strAcsEventCond.read(); strAcsEventCond.dwSize = strAcsEventCond.size(); // 查询全部主次类型的报警 strAcsEventCond.dwMajor = 0; // 查询次事件报警类型 strAcsEventCond.dwMinor = 0; strAcsEventCond.dwBeginSerialNo = dwSerialNo; strAcsEventCond.dwEndSerialNo = dwSerialNo; strAcsEventCond.write(); Pointer condPointer = strAcsEventCond.getPointer(); int remoteConfig = HK_NET_SDK.NET_DVR_StartRemoteConfig(userId, HCNetSDK.NET_DVR_GET_ACS_EVENT, condPointer, strAcsEventCond.size(), null, null); if (remoteConfig <= -1) { log.info("NET_DVR_StartRemoteConfig调用失败,错误信息:" +HK_NET_SDK.NET_DVR_GetLastError()); } HCNetSDK.NET_DVR_ACS_EVENT_CFG eventCfg = new HCNetSDK.NET_DVR_ACS_EVENT_CFG(); eventCfg.read(); eventCfg.dwSize = eventCfg.size(); eventCfg.write(); Pointer cfgPointer = eventCfg.getPointer(); while (true) { int dwEventSearch = HK_NET_SDK.NET_DVR_GetNextRemoteConfig(remoteConfig, cfgPointer, eventCfg.size()); if (dwEventSearch == HCNetSDK.NET_SDK_NEXT_STATUS__FINISH) { break; } else if (dwEventSearch == HCNetSDK.NET_SDK_GET_NEXT_STATUS_FAILED) { break; } else if (dwEventSearch == HCNetSDK.NET_SDK_GET_NEXT_STATUS_SUCCESS) { eventCfg.read(); //获取的事件信息通过eventCfg结构体进行解析 if (ObjectUtils.isNotEmpty(isCard)) { return new String(eventCfg.struAcsEventInfo.byCardNo).trim() .replace(new String(new char[]{160}), StringUtils.EMPTY); } return new String(eventCfg.struAcsEventInfo.byEmployeeNo).trim() .replace(new String(new char[]{160}), StringUtils.EMPTY); } i++; } return null; } }
好了,这就是海康布防回调、获取用户信息、获取事件类型的所有了,写的比较粗糙,有错误的地方希望大家能指正。