前言
最近朋友的需求, 是需要使用 海康sdk 连接海康设备, 进行数据的获取, 比如 进出车辆, 进出人员
这一部分是 对接海康人脸设备 获取相关事件, 并进行入库 的相关处理
测试用例
主要的处理如下
1. 设备登陆, 不同的设备可能兼容的 登陆方式不一样, 我这里设备需要使用 NET_DRV_Login_V30
2. 初始化事件查询参数, 初始化开始时间为最近的时间+1秒
3. 初始化事件查询参数, 初始化结束时间为今天的 23:59:59
4. 对设备记录事件进行迭代, 入库处理
5. 完成迭代, 退出登录, 进入 下一个循环
private static void attachPeopleDeviceAndReadAllEvent(String devPrefix) {int attachDeviceAndMonitor = getIntConfigByDevPreference("global", "attachDeviceAndReadAllEvent", 0);if (attachDeviceAndMonitor == 0) {return;}try {int sleepInMillis = getIntConfigByDevPreference(devPrefix, "peopleReadEventWaitSleepInMs", 10000);while (isRunning) {int lUserID = -1;try {//---------------------------------------// 注册设备//登录参数,包括设备地址、登录用户、密码等NET_DVR_USER_LOGIN_INFO struLoginInfo = new NET_DVR_USER_LOGIN_INFO();struLoginInfo.bUseAsynLogin = false; //同步登录方式String host = getStrConfigByDevPreference(devPrefix, "ip", "192.168.1.13");short port = (short) getIntConfigByDevPreference(devPrefix, "port", 8000);String sUserName = getStrConfigByDevPreference(devPrefix, "username", "admin"); //设备登录用户名String sPassword = getStrConfigByDevPreference(devPrefix, "password", "abcd1234"); //设备登录密码//设备信息, 输出参数String devLogPrefix = getVehicleLogPrefix(devPrefix, host);NET_DVR_DEVICEINFO_V30 struDeviceInfoV30 = new NET_DVR_DEVICEINFO_V30();lUserID = hCNetSDK.NET_DVR_Login_V30(host, port, sUserName, sPassword, struDeviceInfoV30);System.out.println(devLogPrefix + "登陆结果为 : " + lUserID);if (lUserID < 0) {System.out.println(devLogPrefix + "登录失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());Thread.sleep(sleepInMillis);continue;}int peopleDevFetchCountPerLogin = getIntConfigByDevPreference(devPrefix, "peopleDevFetchCountPerLogin", 10);for (int i = 0; i < peopleDevFetchCountPerLogin; i++) {if (!isRunning) {break;}int remoteConfig = -1;try {System.out.println(devLogPrefix + "开始准备读取事件数据, 当前时间 : " + DateFormatUtils.format(new Date()));HCNetSDK.NET_DVR_ACS_EVENT_COND struAcsEventCond = new HCNetSDK.NET_DVR_ACS_EVENT_COND();struAcsEventCond.read();struAcsEventCond.dwSize = struAcsEventCond.size();struAcsEventCond.dwMajor = ConfigUtils.getInt("peopleDevFetchMajor", 0); // 查询所有主事件类型struAcsEventCond.dwMinor = ConfigUtils.getInt("peopleDevFetchMinor", 0); // 查询所有次事件类型// 配置时间Calendar calendarNow = Calendar.getInstance();initDrvAcsEventStartTime(struAcsEventCond, host, calendarNow);initDrvAcsEventEndTime(struAcsEventCond, host, calendarNow);struAcsEventCond.write();remoteConfig = hCNetSDK.NET_DVR_StartRemoteConfig(lUserID, HCNetSDK.NET_DVR_GET_ACS_EVENT, struAcsEventCond.getPointer(), struAcsEventCond.size(), null, null);System.out.println(devLogPrefix + "NET_DVR_StartRemoteConfig接口调用, 开始时间 : " + DateFormatUtils.formatYYYYMMSSHHMMSS(struAcsEventCond.struStartTime)+ ", 结束时间 : " + DateFormatUtils.formatYYYYMMSSHHMMSS(struAcsEventCond.struEndTime) + ",结果:" + remoteConfig + ", last ERROR " + hCNetSDK.NET_DVR_GetLastError());if (remoteConfig >= 0) {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();Date now = new Date();boolean isWaitLogged = false;while (true) {int dwEventSearch = hCNetSDK.NET_DVR_GetNextRemoteConfig(remoteConfig, cfgPointer, eventCfg.size());if ((!isWaitLogged) || dwEventSearch != HCNetSDK.NET_SDK_GET_NEXT_STATUS_NEED_WAIT) {System.out.println(devLogPrefix + "NET_DVR_GetNextRemoteConfig接口调用,结果:" + dwEventSearch + ", last ERROR " + hCNetSDK.NET_DVR_GetLastError());isWaitLogged = true;}if (dwEventSearch < 0) {break; // 服务异常} else if (dwEventSearch == HCNetSDK.NET_SDK_NEXT_STATUS__FINISH) {break; // 所有事件查询完成} else if (dwEventSearch == HCNetSDK.NET_SDK_GET_NEXT_STATUS_SUCCESS) {recordPeopleFlowLog(eventCfg, devPrefix, host, now);}}}Thread.sleep(sleepInMillis);} catch (Exception e) {e.printStackTrace();} finally {if (remoteConfig >= 0) {if (!hCNetSDK.NET_DVR_StopRemoteConfig(remoteConfig)) {System.out.println("NET_DVR_StopRemoteConfig接口调用失败,错误码:" + hCNetSDK.NET_DVR_GetLastError());}}}}} finally {//注销用户if (lUserID >= 0) {hCNetSDK.NET_DVR_Logout(lUserID);}}}} catch (Exception e) {e.printStackTrace();} finally {hCNetSDK.NET_DVR_Cleanup();}}private static void recordPeopleFlowLog(NET_DVR_ACS_EVENT_CFG eventCfg, String devPrefix, String host, Date now) {long startTs = System.currentTimeMillis();int insertResult = -1;StatsPeopleFlowLog peopleFlowLog = new StatsPeopleFlowLog();String devLogPrefix = getVehicleLogPrefix(devPrefix, host);String tableName = getStrConfigByDevPreference(devPrefix, "tableName", "stats_people_flow_log"); //存储明细表名try {eventCfg.read(); // 读取事件信息peopleFlowLog.setTheDay(DateFormatUtils.formatYYYYMMSS(eventCfg.struTime));peopleFlowLog.setVehiclePrefix(devPrefix);peopleFlowLog.setHost(host);peopleFlowLog.setSerialNo(String.valueOf(eventCfg.struAcsEventInfo.dwSerialNo));peopleFlowLog.setMajor(String.valueOf(eventCfg.dwMajor));peopleFlowLog.setMinor(String.valueOf(eventCfg.dwMinor));peopleFlowLog.setBizTime(DateFormatUtils.formatYYYYMMSSHHMMSS(eventCfg.struTime));peopleFlowLog.setFullInfo(JSON.toJSONString(eventCfg));peopleFlowLog.setRemark("");peopleFlowLog.setCreatedAt(DateFormatUtils.format(now));System.out.println(devLogPrefix + " 人脸识别设备读取到事件 : " + peopleFlowLog.toString());String insertSql = MysqlUtils.assembleInsertSql(tableName, peopleFlowLog.toJSON());insertResult = MysqlUtils.executeUpdate(insertSql);} catch (Exception e) {e.printStackTrace();} finally {long spentTs = System.currentTimeMillis() - startTs;System.out.println(String.format(devLogPrefix + " 人脸识别设备读取到事件 : %s, 接收时间 : %s, 入库结果 : %s, 开销 : %s", peopleFlowLog.toString(), DateFormatUtils.format(new Date()), insertResult, spentTs));}}
初始化事件查询参数 处理如下
private static void initDrvAcsEventStartTime(NET_DVR_ACS_EVENT_COND struAcsEventCond, String host, Calendar calendarNow) {String queryLastSql = String.format("SELECT * FROM stats_people_flow_log where host = '%s' ORDER BY biz_time DESC LIMIT 1;", host);List<StatsPeopleFlowLog> list = MysqlUtils.executeQuery(queryLastSql, MysqlUtils.MY_STATISTICS_PEOPLE_FLOW_LOG_EXTRACTOR);// 默认从今天 0点开始if (list == null || list.isEmpty()) {struAcsEventCond.struStartTime.dwYear = calendarNow.get(Calendar.YEAR);struAcsEventCond.struStartTime.dwMonth = calendarNow.get(Calendar.MONTH) + 1; // 注意:月份从0开始struAcsEventCond.struStartTime.dwDay = calendarNow.get(Calendar.DAY_OF_MONTH);struAcsEventCond.struStartTime.dwHour = 0;struAcsEventCond.struStartTime.dwMinute = 0;struAcsEventCond.struStartTime.dwSecond = 0;return;}StatsPeopleFlowLog lastRecord = list.get(0);String lastBizTime = lastRecord.getBizTime();int idx = 0;String year = lastBizTime.substring(idx, idx + 4);idx += 5;String month = lastBizTime.substring(idx, idx + 2);idx += 3;String day = lastBizTime.substring(idx, idx + 2);idx += 3;String hour = lastBizTime.substring(idx, idx + 2);idx += 3;String minute = lastBizTime.substring(idx, idx + 2);idx += 3;String second = lastBizTime.substring(idx, idx + 2);struAcsEventCond.struStartTime.dwYear = Integer.parseInt(year);struAcsEventCond.struStartTime.dwMonth = Integer.parseInt(month);struAcsEventCond.struStartTime.dwDay = Integer.parseInt(day);struAcsEventCond.struStartTime.dwHour = Integer.parseInt(hour);struAcsEventCond.struStartTime.dwMinute = Integer.parseInt(minute);struAcsEventCond.struStartTime.dwSecond = Integer.parseInt(second) + 1;// 粗粒度处理, 常见情况if (struAcsEventCond.struStartTime.dwSecond >= 60) {struAcsEventCond.struStartTime.dwSecond = 0;struAcsEventCond.struStartTime.dwMinute++;if (struAcsEventCond.struStartTime.dwMinute >= 60) {struAcsEventCond.struStartTime.dwMinute = 0;struAcsEventCond.struStartTime.dwHour++;}}}private static void initDrvAcsEventEndTime(NET_DVR_ACS_EVENT_COND struAcsEventCond, String host, Calendar calendarNow) {struAcsEventCond.struEndTime.dwYear = calendarNow.get(Calendar.YEAR);struAcsEventCond.struEndTime.dwMonth = calendarNow.get(Calendar.MONTH) + 1;struAcsEventCond.struEndTime.dwDay = calendarNow.get(Calendar.DAY_OF_MONTH);struAcsEventCond.struEndTime.dwHour = 23;struAcsEventCond.struEndTime.dwMinute = 59;struAcsEventCond.struEndTime.dwSecond = 59;}
最终拿到数据如下
完