海康下发人员信息和人脸信息,采用的是两个接口,需要先下发人员信息,然后在下发人脸。
文中登录 退出登录 长连接和海康hCNetSDK等接口 见文章 初始SDK和登录
camera 设备信息含 设备账号 和IP端口
faceList 用户信息 包含人员信息和base64人脸图
/**
* 批量添加人脸
*
* @param camera 摄像头信息
* @param faceList 人脸参数
* @return
*/
@Override
public List<IotCommDataResult> addFace(IotCameraParam camera, List<IotAddFaceParam> faceList) {
//登录
int lUserID = login_V40(camera.getIp(), new Short(String.valueOf(camera.getPort())), camera.getUsername(), camera.getPassword());
if (lUserID == -1) {
log.warn("登录失败,错误码为 :{}", hCNetSDK.NET_DVR_GetLastError());
return faceList.stream().map(user -> IotCommDataResult.FAIL_RESULT(user.getUserId())).collect(Collectors.toList());
}
//添加用户信息
List<IotCommDataResult> userInfoResults = this.addUserInfo(faceList, lUserID);
try {
Thread.sleep(500);
} catch (Exception e) {
log.error("休眠异常", e);
}
//添加人脸
List<IotCommDataResult> userFaceResults = this.addUserFace(faceList, lUserID);
//处理集合数据 用户成功 人脸成功才是成功
if (CollUtil.isEmpty(userFaceResults) || CollUtil.isEmpty(userInfoResults)) {
log.warn("添加人脸失败 userInfoResults:{} ,userFaceResults:{}", userInfoResults.size(), userFaceResults.size());
return faceList.stream().map(user -> IotCommDataResult.FAIL_RESULT(user.getUserId())).collect(Collectors.toList());
}
Map<Long, IotCommDataResult> userFaceMap = userFaceResults.stream().collect(AbsCollector.toMap(IotCommDataResult::getId));
//退出登录
logout(lUserID);
List<Long> delUserIds = new ArrayList<>();
// IotCommDataResult 自定义类用来获取执行结果
List<IotCommDataResult> userInfoResultList = userInfoResults.stream().map(user -> {
IotCommDataResult result = new IotCommDataResult();
if (userFaceMap.get(user.getId()) != null) {
IotCommDataResult dataResult = userFaceMap.get(user.getId());
if (dataResult.getCode() == 500) {
delUserIds.add(user.getId());
result.setId(user.getId());
result.setCode(500);
result.setMsg(dataResult.getMsg());
} else {
result.setId(user.getId());
result.setCode(200);
result.setMsg("添加成功");
}
} else {
result.setId(user.getId());
result.setCode(500);
result.setMsg("添加失败");
}
return result;
}).collect(Collectors.toList());
if (CollUtil.isNotEmpty(delUserIds)) {
// 删除人员信息,删除人员信息下发成功且人脸信息下发失败的用户信息
deleteFace(camera, delUserIds);
}
return userInfoResultList;
}
/**
* 添加用户信息
* employeeNo 设备中用户编号唯一,文中采用的是用户id
*/
private List<IotCommDataResult> addUserInfo(List<IotAddFaceParam> paramList, int lUserID) {
//创建连接
String strUserInBuffer = "PUT /ISAPI/AccessControl/UserInfo/SetUp?format=json";
// 创建长连接
int startUserRemoteConfig = getLongConnt(strUserInBuffer, IotHikNetConstant.NET_DVR_JSON_CONFIG, lUserID);
List<IotCommDataResult> resultList = new ArrayList<>();
for (int i = 0; i < paramList.size(); i++) {
IotAddFaceParam param = paramList.get(i);
IotCommDataResult result = new IotCommDataResult();
result.setId(param.getUserId());
if (startUserRemoteConfig < 0) {
log.warn("AddUserInfo NET_DVR_StartRemoteConfig 失败,错误码为 : {}", hCNetSDK.NET_DVR_GetLastError());
result.setCode(500);
result.setMsg("添加用户失败");
continue;
}
try {
//下发用户信息
byte[] Name = param.getUserName().getBytes("utf-8"); //根据iCharEncodeType判断,如果iCharEncodeType返回6,则是UTF-8编码。
//如果是0或者1或者2,则是GBK编码
//将中文字符编码之后用数组拷贝的方式,避免因为编码导致的长度问题
String strInBuffer1 = "{\n" + " \"UserInfo\":{\n" + " \"employeeNo\":\"" + param.getUserId() + "\",\n" + " \"name\":\"";
String strInBuffer2 = "\",\n" + " \"userType\":\"normal\",\n" + " \"Valid\":{\n" + " \"enable\":false,\n" + " \"beginTime\":\"2019-08-01T17:30:08\",\n" + " \"endTime\":\"2030-08-01T17:30:08\",\n" + " \"timeType\":\"local\"\n" + " },\n" + " \"belongGroup\":\"1\",\n" + " \"doorRight\":\"1\",\n" + " \"RightPlan\":[\n" + " {\n" + " \"doorNo\":1,\n" + " \"planTemplateNo\":\"1\"\n" + " }\n" + " ]\n" + " }\n" + "}";
int iStringSize = Name.length + strInBuffer1.length() + strInBuffer2.length();
BYTE_ARRAY ptrByte = new BYTE_ARRAY(iStringSize);
System.arraycopy(strInBuffer1.getBytes(), 0, ptrByte.byValue, 0, strInBuffer1.length());
System.arraycopy(Name, 0, ptrByte.byValue, strInBuffer1.length(), Name.length);
System.arraycopy(strInBuffer2.getBytes(), 0, ptrByte.byValue, strInBuffer1.length() + Name.length, strInBuffer2.length());
ptrByte.write();
log.info("添加参数:{}", new String(ptrByte.byValue));
BYTE_ARRAY ptrOutuff = new BYTE_ARRAY(1024);
IntByReference pInt = new IntByReference(0);
int dwState = hCNetSDK.NET_DVR_SendWithRecvRemoteConfig(startUserRemoteConfig, ptrByte.getPointer(), iStringSize, ptrOutuff.getPointer(), 1024, pInt);
if (dwState == -1) {
log.error("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:{}", hCNetSDK.NET_DVR_GetLastError());
result.setCode(500);
result.setMsg("添加用户失败");
continue;
}
//读取返回的json并解析
ptrOutuff.read();
String strResult = new String(ptrOutuff.byValue).trim();
log.info("addUserInfo dwState: {} ,strResult:{}", dwState, strResult);
JSONObject jsonResult = JSONUtil.parseObj(strResult);
int statusCode = jsonResult.getInt("statusCode");
String statusString = jsonResult.getStr("statusString");
responStatusMsg(dwState, param.getUserId(), statusCode, strResult);
if (dwState == IotHikNetConstant.NET_SDK_CONFIG_STATUS_SUCCESS) {//返回NET_SDK_CONFIG_STATUS_SUCCESS代表流程走通了,但并不代表下发成功,比如有些设备可能因为人员已存在等原因下发失败,所以需要解析Json报文
if (statusCode != 1) {
result.setCode(500);
result.setMsg("添加用户失败");
} else {
result.setCode(200);
result.setMsg("添加用户成功");
}
} else {
result.setCode(500);
result.setMsg("添加用户失败");
}
} catch (Exception e) {
log.error("添加用户异常:", e);
result.setCode(500);
result.setMsg("添加用户失败");
}
resultList.add(result);
}
//关闭长连接,释放资源
if (!hCNetSDK.NET_DVR_StopRemoteConfig(startUserRemoteConfig)) {
log.warn("NET_DVR_StopRemoteConfig接口调用失败,错误码:{}", hCNetSDK.NET_DVR_GetLastError());
} else {
log.info("NET_DVR_StopRemoteConfig接口成功");
}
return resultList;
}
/**
* 添加人脸
* 根据工号添加人脸
*/
private List<IotCommDataResult> addUserFace(List<IotAddFaceParam> paramList, int lUserID) {
//创建长连接
String strFaceInBuffer = "PUT /ISAPI/Intelligent/FDLib/FDSetUp?format=json";
// String strFaceInBuffer = "POST /ISAPI/Intelligent/FDLib/FaceDataRecord?format=json";
int startFaceRemoteConfig = this.getLongConnt(strFaceInBuffer, IotHikNetConstant.NET_DVR_FACE_DATA_RECORD, lUserID);
FileInputStream picfile = null;
//下发人脸
List<IotCommDataResult> resultList = new ArrayList<>();
for (int i = 0; i < paramList.size(); i++) {
IotAddFaceParam faceParam = paramList.get(i);
IotCommDataResult result = new IotCommDataResult();
result.setId(faceParam.getUserId());
if (startFaceRemoteConfig < 0) {
log.warn("addUserFace NET_DVR_StartRemoteConfig 失败,错误码为 : {}", hCNetSDK.NET_DVR_GetLastError());
result.setCode(500);
result.setMsg("添加人脸失败");
} else {
try {
BYTE_ARRAY ptrByteArray = new BYTE_ARRAY(1024); //数组
NET_DVR_JSON_DATA_CFG struAddFaceDataCfg = new NET_DVR_JSON_DATA_CFG();
struAddFaceDataCfg.read();
JSONObject jsonObject = new JSONObject();
jsonObject.set("faceLibType", "blackFD");
jsonObject.set("FDID", "1");
jsonObject.set("FPID", String.valueOf(faceParam.getUserId()));//人脸下发关联的工号
String strJsonData = jsonObject.toString();
System.arraycopy(strJsonData.getBytes(), 0, ptrByteArray.byValue, 0, strJsonData.length());//字符串拷贝到数组中
ptrByteArray.write();
struAddFaceDataCfg.dwSize = struAddFaceDataCfg.size();
struAddFaceDataCfg.lpJsonData = ptrByteArray.getPointer();
struAddFaceDataCfg.dwJsonDataSize = strJsonData.length();
/*****************************************
* 从本地文件里面读取JPEG图片二进制数据
*****************************************/
//将base64 转为二进制
String fileName = IdWorker.getId() + ".jpg";
String downloadImgPath = downloadImg(faceParam.getFaceImage(), fileName);
if (StrUtil.isEmpty(downloadImgPath)) {
log.warn("图片解析失败");
result.setCode(500);
result.setMsg("添加人脸失败");
continue;
}
int picdataLength = 0;
picfile = new FileInputStream(new File(downloadImgPath));
picdataLength = picfile.available();
if (picdataLength < 0) {
log.warn("input file dataSize < 0");
}
BYTE_ARRAY ptrpicByte = new BYTE_ARRAY(picdataLength);
picfile.read(ptrpicByte.byValue);
ptrpicByte.write();
struAddFaceDataCfg.dwPicDataSize = picdataLength;
struAddFaceDataCfg.lpPicData = ptrpicByte.getPointer();
struAddFaceDataCfg.write();
BYTE_ARRAY ptrOutuff = new BYTE_ARRAY(1024);
IntByReference pInt = new IntByReference(0);
int dwState = hCNetSDK.NET_DVR_SendWithRecvRemoteConfig(startFaceRemoteConfig, struAddFaceDataCfg.getPointer(), struAddFaceDataCfg.dwSize, ptrOutuff.getPointer(), 1024, pInt);
if (dwState == -1) {
log.warn("NET_DVR_SendWithRecvRemoteConfig接口调用失败,错误码:{}", hCNetSDK.NET_DVR_GetLastError());
result.setCode(500);
continue;
}
//读取返回的json并解析
ptrOutuff.read();
String strResult = new String(ptrOutuff.byValue).trim();
log.info("addUserFace dwState: {} ,strResult: {}", dwState, strResult);
if (StrUtil.isNotEmpty(strResult) && JSONUtil.isJson(strResult)) {
JSONObject jsonResult = JSONUtil.parseObj(strResult);
int statusCode = jsonResult.getInt("statusCode");
String statusString = jsonResult.getStr("statusString");
responStatusMsg(dwState, faceParam.getUserId(), statusCode, strResult);
if (dwState == IotHikNetConstant.NET_SDK_CONFIG_STATUS_SUCCESS) {//返回NET_SDK_CONFIG_STATUS_SUCCESS代表流程走通了,但并不代表下发成功,比如有些设备可能因为人员已存在等原因下发失败,所以需要解析Json报文
if (statusCode != 1) {
result.setCode(500);
result.setMsg("添加人脸失败");
} else {
result.setCode(200);
result.setMsg("添加用户成功");
}
} else {
result.setCode(500);
result.setMsg("添加人脸失败");
}
} else {
result.setCode(500);
result.setMsg("添加人脸失败");
}
} catch (Exception e) {
log.error("下发人脸异常:", e);
result.setCode(500);
}
}
resultList.add(result);
}
//关闭长连接,释放资源
if (!hCNetSDK.NET_DVR_StopRemoteConfig(startFaceRemoteConfig)) {
log.warn("NET_DVR_StopRemoteConfig接口调用失败,错误码:{}", hCNetSDK.NET_DVR_GetLastError());
} else {
log.info("NET_DVR_StopRemoteConfig接口成功");
}
if (picfile != null) {
try {
picfile.close();
} catch (IOException ioException) {
log.info("FileInputStream 关闭异常");
}
}
return resultList;
}