02 使用 海康SDK 对人脸识别设备读取事件
前言
最近朋友的需求, 是需要使用 海康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;
}
最终拿到数据如下
完