项目需求:
需要获取刷脸的流水记录,参考是主动获取设备事件SDK
步骤流程
连接设备----建立获取设备事件长连接------成功后就可以获取到设备事件进行其余的逻辑处理
1、连接设备
注意:HCNetSDK.java 的第33行[大概在这个位置]
HCNetSDK INSTANCE = (HCNetSDK) Native.loadLibrary(HCNetDevicePro.initHcnetsdkDllPath(), HCNetSDK.class);
/** * HCNetSDK.dll初始化 * @return HCNETSDK_DLL_PATH */ public static String initHcnetsdkDllPath(){ String path = (HCNetDeviceUtil.class.getResource("/HCNetSDK/HCNetSDK.dll").getPath()) .replaceAll("%20", " ").substring(1).replace("/","\\"); try { HCNETSDK_DLL_PATH = java.net.URLDecoder.decode(path, "utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } System.out.println(HCNETSDK_DLL_PATH); return HCNETSDK_DLL_PATH; }
这个是加载HCNetSDK.dll文件使用,根据个人项目存放的实际路径进行配置
设备连接方法
其中我把设备连接需要的ip、port、username、password全部写死初始化[因为我是测试阶段]
/** * 初始化连接设备所需要的信息 */ HCNDeviceEntity hcnDeviceEntity = new HCNDeviceEntity();
/** * 设备登陆方法 * @return true代表连接设备成功 false代表连接设备失败 */ public boolean loginDevice(){ //初始化HCNetSDK boolean status = hcNetSDK.NET_DVR_Init(); if (status){ System.out.println("初始化成功!"); }else{ System.out.println("初始化失败:"+hcNetSDK.NET_DVR_GetCardLastError_Card()); } // 设备信息的参数结构体 HCNetSDK.NET_DVR_DEVICEINFO_V30 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30(); NativeLong lDeviceID = hcNetSDK.NET_DVR_Login_V30(hcnDeviceEntity.getIp(),hcnDeviceEntity.getPort(),hcnDeviceEntity.getUsername(),hcnDeviceEntity.getPassword(),m_strDeviceInfo); lUserID = lDeviceID.intValue(); if (lUserID == -1){ System.out.println("=============设备登陆失败========lUserID:"+lUserID); // 获取错误码 [具体查看HCNetSDK.java 全局错误码] int error = hcNetSDK.NET_DVR_GetLastError(); if (error == 7){ System.out.println("连接服务器失败"); } return false; } // HCNetSDK.NET_DVR_WORKSTATE_V30 devwork=new HCNetSDK.NET_DVR_WORKSTATE_V30(); // if(!hcNetSDK.NET_DVR_GetDVRWorkState_V30(lDeviceID, devwork)){ // //返回Boolean值,判断是否获取设备能力 // System.out.println("返回设备状态失败"); // return false; // } // System.out.println("------------正确-----------------"); return true; }
然后就是建立长连接
/** * 调用设备事件 */ public void getDeviceCase() { Map<String,String> eventMap;// 储存事件信息的map // 调用获取设备事件长连接 HCNetSDK.NET_DVR_ACS_EVENT_COND_V50 struAcsEventCond = new HCNetSDK.NET_DVR_ACS_EVENT_COND_V50(); struAcsEventCond.read(); struAcsEventCond.dwSize = struAcsEventCond.size(); struAcsEventCond.dwMajor = 5;// 5代表event事件 struAcsEventCond.dwMinor = 0x4b;// 代表刷脸成功 struAcsEventCond.struStartTime = getDvrStruTime(StruTimeEnum.STRAT.toString());// ****必须要 struAcsEventCond.struEndTime = getDvrStruTime(StruTimeEnum.END.toString());// ***必须要 struAcsEventCond.write(); Pointer ptrStruEventCond = struAcsEventCond.getPointer(); lHandle = hcNetSDK.NET_DVR_StartRemoteConfig(lUserID,HCNetSDK.NET_DVR_GET_ACS_EVENT,ptrStruEventCond,struAcsEventCond.size(),null,null); if (lHandle == -1){ System.out.println("建立获取设备事件长连接失败,错误码为"+hcNetSDK.NET_DVR_GetLastError()); return; }else{ System.out.println("建立获取设备事件连接成功!"+lHandle); } // 获取设备详细事件开始 HCNetSDK.NET_DVR_ACS_EVENT_CFG_V50 struEventCFG = new HCNetSDK.NET_DVR_ACS_EVENT_CFG_V50(); struEventCFG.read(); struEventCFG.dwSize = struEventCFG.size(); struEventCFG.write(); while(true){ dwState = hcNetSDK. NET_DVR_GetNextRemoteConfig(lHandle, struEventCFG.getPointer(), struEventCFG.size()); struEventCFG.read(); if (dwState == -1){ System.out.println("NET_DVR_GetNextRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError()); continue; }else if (dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_NEED_WAIT){ // 配置等待 System.out.println("==========配置等待=============="); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } continue; }else if (dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_FAILED){ // 获取事件失败 System.out.println("===============获取设备事件失败======================="); break; } else if(dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_EXCEPTION) { // 获取事件异常 System.out.println("===============获取设备事件异常======================="); break; }else if (dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_SUCCESS){ // 获取设备事件成功 eventMap = new HashMap<>(16); eventMap.put("employeeNo",byteArrayToStr(struEventCFG.struAcsEventInfo.byEmployeeNo)); eventMap.put("cardNo",byteArrayToStr(struEventCFG.struAcsEventInfo.byCardNo)); eventMap.put("struTime",changeTimeFormat(struEventCFG.struTime)); eventList.add(eventMap); continue; }else if(dwState == HCNetSDK.NET_SDK_GET_NEXT_STATUS_FINISH) { // 获取设备事件信息完成 System.out.println("=============获取设备事件完成================"); break; } } }
获取设备事件完成后需要断开长连接,释放sdk资源
/** * 停止长连接 */ public void stopRemote(){ if(!hcNetSDK.NET_DVR_StopRemoteConfig(lHandle)){ System.out.println("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + hcNetSDK.NET_DVR_GetLastError()); } else{ System.out.println("NET_DVR_StopRemoteConfig接口成功"); } boolean cleanUp = hcNetSDK.NET_DVR_Cleanup(); if (cleanUp){ System.out.println("释放SDK成功"); }else{ System.out.println("释放SDK失败"); } }
其中的一些结构体放在HCNetSDK里面
//NET_DVR_Login_V30()参数结构 public static class NET_DVR_DEVICEINFO_V30 extends Structure { public byte[] sSerialNumber = new byte[SERIALNO_LEN]; //序列号 public byte byAlarmInPortNum; //报警输入个数 public byte byAlarmOutPortNum; //报警输出个数 public byte byDiskNum; //硬盘个数 public byte byDVRType; //设备类型, 1:DVR 2:ATM DVR 3:DVS ...... public byte byChanNum; //模拟通道个数 public byte byStartChan; //起始通道号,例如DVS-1,DVR - 1 public byte byAudioChanNum; //语音通道数 public byte byIPChanNum; //最大数字通道个数 public byte[] byRes1 = new byte[24]; //保留 }
int NET_DVR_GET_ACS_EVENT = 2514;// 设备事件获取[命令码] public static final int NET_SDK_EMPLOYEE_NO_LEN = 32; // 编号长度 //状态码 int NET_SDK_GET_NEXT_STATUS_SUCCESS = 1000;// 成功读取到数据,处理完本次数据后需要再次调用NET_DVR_GetNextRemoteConfig获取下一条数据 int NET_SDK_GET_NEXT_STATUS_NEED_WAIT = 1001;// 需等待设备发送数据,继续调用NET_DVR_GetNextRemoteConfig int NET_SDK_GET_NEXT_STATUS_FINISH = 1002; // 数据全部读取完,可调用NET_DVR_StopRemoteConfig结束长连接 int NET_SDK_GET_NEXT_STATUS_FAILED = 1003; // 读取失败,可调用NET_DVR_StopRemoteConfig结束长连接 int NET_SDK_GET_NEXT_STATUS_EXCEPTION = 1004;// 读取异常,可调用NET_DVR_StopRemoteConfig结束长连接 /* V50参数版本 [设备时间主结构体]*/ class NET_DVR_ACS_EVENT_COND_V50 extends Structure{ public int dwSize; public int dwMajor; //报警主类型,参考事件上传宏定义,0-全部 public int dwMinor; //报警次类型,参考事件上传宏定义,0-全部 public NET_DVR_TIME struStartTime; //开始时间 public NET_DVR_TIME struEndTime; //结束时间 public byte[] byCardNo = new byte[ACS_CARD_NO_LEN]; //卡号 public byte[] byName = new byte[NAME_LEN]; //持卡人姓名 public byte byPicEnable; //是否带图片,0-不带图片,1-带图片 public byte[] byRes2 = new byte[3]; //保留 public int dwBeginSerialNo; //起始流水号(为0时默认全部) public int dwEndSerialNo; //结束流水号(为0时默认全部) public byte[] byRes = new byte[244]; //保留 } /*设备事件详细信息结构体*/ class NET_DVR_ACS_EVENT_DETAIL_V50 extends Structure{ public int dwSize; public byte[] byCardNo = new byte[ACS_CARD_NO_LEN]; //卡号(mac地址),为0无效 public byte byCardType; //卡类型,1-普通卡,2-残疾人卡,3-黑名单卡,4-巡更卡,5-胁迫卡,6-超级卡,7-来宾卡,8-解除卡,为0无效 public byte byWhiteListNo; //白名单单号,1-8,为0无效 public byte byReportChannel; //报告上传通道,1-布防上传,2-中心组1上传,3-中心组2上传,为0无效 public byte byCardReaderKind; //读卡器属于哪一类,0-无效,1-IC读卡器,2-身份证读卡器,3-二维码读卡器,4-指纹头 public int dwCardReaderNo; //读卡器编号,为0无效 public int dwDoorNo; //门编号(楼层编号),为0无效 public int dwVerifyNo; //多重卡认证序号,为0无效 public int dwAlarmInNo; //报警输入号,为0无效 public int dwAlarmOutNo; //报警输出号,为0无效 public int dwCaseSensorNo; //事件触发器编号 public int dwRs485No; //RS485通道号,为0无效 public int dwMultiCardGroupNo; //群组编号 public short wAccessChannel; //人员通道号 public byte byDeviceNo; //设备编号,为0无效(有效范围1-255) public byte byDistractControlNo;//分控器编号,为0无效 public int dwEmployeeNo; //工号,为0无效 public short wLocalControllerID; //就地控制器编号,0-门禁主机,1-64代表就地控制器 public byte byInternetAccess; //网口ID:(1-上行网口1,2-上行网口2,3-下行网口1) public byte byType; //防区类型,0:即时防区,1-24小时防区,2-延时防区 ,3-内部防区,4-钥匙防区 5-火警防区 6-周界防区 7-24小时无声防区 8-24小时辅助防区,9-24小时震动防区,10-门禁紧急开门防区,11-门禁紧急关门防区 0xff-无 public byte[] byMACAddr = new byte[MACADDR_LEN]; //物理地址,为0无效 public byte bySwipeCardType;//刷卡类型,0-无效,1-二维码 public byte byRes2; public int dwSerialNo; public byte byChannelControllerID; public byte byChannelControllerLampID; public byte byChannelControllerIRAdaptorID; public byte byChannelControllerIREmitterID; public int dwRecordChannelNum; public Pointer pRecordChannelData; public byte byUserType; public byte byCurrentVerifyMode; public byte[] byRe2 = new byte[2]; public byte[] byEmployeeNo = new byte[NET_SDK_EMPLOYEE_NO_LEN]; public byte[] byRes = new byte[64]; } /*设备事件信息结构体*/ class NET_DVR_ACS_EVENT_CFG_V50 extends Structure{ public int dwSize; public int dwMajor; //报警主类型,参考宏定义 public int dwMinor; //报警次类型,参考宏定义 public NET_DVR_TIME struTime; //时间 public byte[] sNetUser = new byte[MAX_NAMELEN];//网络操作的用户名 public NET_DVR_IPADDR_V50 struRemoteHostAddr;//远程主机地址 public NET_DVR_ACS_EVENT_DETAIL_V50 struAcsEventInfo; //详细参数 public int dwPicDataLen; //图片数据大小,不为0是表示后面带数据 public Pointer pPicData; public short wInductiveEventType; public byte byTimeType; public byte[] byRes = new byte[61]; } class NET_DVR_IPADDR_V50 extends Structure { public byte[] sIpV4 = new byte[16]; public byte[] byIPv6 = new byte[128]; public String toString() { return "NET_DVR_IPADDR.sIpV4: " + new String(sIpV4) + "\n" + "NET_DVR_IPADDR.byIPv6: " + new String(byIPv6) + "\n"; } }