wisdomisite-java/src/main/java/com/zhgd/xmgl/async/AsyncHikvision.java

1083 lines
43 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.zhgd.xmgl.async;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zhgd.jeecg.common.execption.OpenPromptException;
import com.zhgd.jeecg.common.util.SpringContextUtils;
import com.zhgd.jeecg.common.util.pass.HttpUtils;
import com.zhgd.redis.lock.RedisRepository;
import com.zhgd.xmgl.call.HikvisionCall;
import com.zhgd.xmgl.constant.Cts;
import com.zhgd.xmgl.modules.basicdata.entity.Notice;
import com.zhgd.xmgl.modules.basicdata.service.INoticeService;
import com.zhgd.xmgl.modules.car.entity.CarInfo;
import com.zhgd.xmgl.modules.car.service.impl.CarInfoServiceImpl;
import com.zhgd.xmgl.modules.project.entity.Project;
import com.zhgd.xmgl.modules.project.entity.vo.ProjectInfoExtVo;
import com.zhgd.xmgl.modules.project.mapper.ProjectMapper;
import com.zhgd.xmgl.modules.project.service.IProjectUfaceConfigService;
import com.zhgd.xmgl.modules.project.service.impl.ProjectServiceImpl;
import com.zhgd.xmgl.modules.video.mapper.ProjectVideoHkVqdMapper;
import com.zhgd.xmgl.modules.video.mapper.VideoItemMapper;
import com.zhgd.xmgl.modules.worker.entity.*;
import com.zhgd.xmgl.modules.worker.mapper.EnterpriseInfoMapper;
import com.zhgd.xmgl.modules.worker.service.impl.WorkerInfoServiceImpl;
import com.zhgd.xmgl.modules.xz.entity.XzHikvisionSync;
import com.zhgd.xmgl.modules.xz.mapper.XzHikvisionCompareDataMapper;
import com.zhgd.xmgl.modules.xz.mapper.XzHikvisionSyncMapper;
import com.zhgd.xmgl.modules.xz.service.impl.XzHikvisionCompareDataServiceImpl;
import com.zhgd.xmgl.security.entity.UserInfo;
import com.zhgd.xmgl.util.*;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.Future;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 异步海康
*/
@Slf4j
@Component
public class AsyncHikvision {
public static final String XZ_HIKVISION_SYNC_TIME = "xzHikvisionSyncTime";
public static final int MAX_PAGE_SIZE = 1000;
@Lazy
@Autowired
public CarInfoServiceImpl carInfoService;
@Autowired
@Lazy
public WorkerInfoServiceImpl workerInfoService;
@Autowired
@Lazy
public IProjectUfaceConfigService projectUfaceConfigService;
@Autowired
@Lazy
HikvisionCall hikvisionCall;
@Lazy
@Autowired
ProjectMapper projectMapper;
@Lazy
@Autowired
VideoItemMapper videoItemMapper;
@Lazy
@Autowired
ProjectVideoHkVqdMapper projectVideoHkVqdMapper;
@Lazy
@Autowired
EnterpriseInfoMapper enterpriseInfoMapper;
@Lazy
@Autowired
ProjectServiceImpl projectService;
@Lazy
@Autowired
private INoticeService noticeService;
@Lazy
@Autowired
private AsyncHikvision asyncHikvision;
@Lazy
@Autowired
private XzHikvisionSyncMapper xzHikvisionSyncMapper;
@Lazy
@Autowired
private XzHikvisionCompareDataMapper xzHikvisionCompareDataMapper;
@Lazy
@Autowired
private XzHikvisionCompareDataServiceImpl xzHikvisionCompareDataService;
@Autowired
private RedisRepository redisRepository;
/**
* 获取下发的时间,如果不存在就新建
*
* @return
*/
public static Date getSyncTimeWithInitIfAbsent() {
Date now = ThreadLocalUtil.getNotNull().getDate(XZ_HIKVISION_SYNC_TIME);
if (now == null) {
now = new Date();
ThreadLocalUtil.addInKey(XZ_HIKVISION_SYNC_TIME, now);
}
return now;
}
/**
* 获取下发的时间,如果不存在就新建,并删除同步表中对应的数据
*
* @param bigType 1人员2车辆
* @param tableId
* @return
*/
public static Date getSyncTimeWithInitAndDeleteSyncIfAbsent(int bigType, Long tableId) {
Date now = ThreadLocalUtil.getNotNull().getDate(XZ_HIKVISION_SYNC_TIME);
if (now == null) {
//首次执行,清空以前同步记录
now = new Date();
ThreadLocalUtil.addInKey(XZ_HIKVISION_SYNC_TIME, now);
SpringContextUtils.getBean(XzHikvisionSyncMapper.class).delete(new LambdaQueryWrapper<XzHikvisionSync>()
.eq(XzHikvisionSync::getBigType, bigType)
.eq(XzHikvisionSync::getWhoId, tableId)
);
}
return now;
}
/**
* 获取同步时间
*
* @return
*/
public static Date getSyncTime() {
return ThreadLocalUtil.getNotNull().getDate(XZ_HIKVISION_SYNC_TIME);
}
/**
* 异步添加人员和权限
*
* @param workerInfo
* @param isSaveWorker
* @param isSaveWorkerFace
* @return
*/
@Async("workerHkExecutor")
public Future addWorkerAndAuthAsync(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) {
this.addWorkerAsync(workerInfo, true, true);
projectUfaceConfigService.addWorkerInfo(workerInfo);
return null;
}
/**
* 添加劳务人员-海康
*
* @param workerInfo
* @param isSaveWorker
* @param isSaveWorkerFace
*/
@Async("workerHkExecutor")
public void addWorkerAsync(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) {
try {
hikvisionCall.saveWorker(workerInfo, isSaveWorker, isSaveWorkerFace);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForWorker(workerInfo, e, "添加");
}
}
/**
* 添加人员
*
* @param workerInfo
* @param isSaveWorker
* @param isSaveWorkerFace
*/
public void addWorker(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) {
this.addWorkerAsync(workerInfo, isSaveWorker, isSaveWorkerFace);
}
/**
* 编辑人员和权限
*
* @param workerInfo
* @param isSaveWorker
* @param isSaveWorkerFace
*/
@Async("workerHkExecutor")
public void editWorkerAndAuthAsync(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) {
this.saveWorkerAsync(workerInfo, true, true);
projectUfaceConfigService.updateWorkerInfo(workerInfo, workerInfo);
}
/**
* 保存人员
*
* @param workerInfo
* @param isSaveWorker
* @param isSaveWorkerFace
*/
public void saveWorker(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) {
this.saveWorkerAsync(workerInfo, isSaveWorker, isSaveWorkerFace);
}
/**
* 异步保存人员
*
* @param workerInfo
* @param isSaveWorker
* @param isSaveWorkerFace
*/
@Async("workerHkExecutor")
public void saveWorkerAsync(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) {
try {
hikvisionCall.saveWorker(workerInfo, isSaveWorker, isSaveWorkerFace);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForWorker(workerInfo, e, "更新");
}
}
/**
* 编辑人员
*
* @param workerInfo
* @param isSaveWorker
* @param isSaveWorkerFace
*/
public void editWorker(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) {
this.saveWorkerAsync(workerInfo, isSaveWorker, isSaveWorkerFace);
}
/**
* 为人员发送通知和设置下发状态
*
* @param workerInfo
* @param e
* @param action
*/
private void sendNoticeForWorker(WorkerInfo workerInfo, Exception e, String action) {
String title = action + "人员到海康isc失败";
String type = "23";
String msg;
if (HttpUtils.isTimeOut(e)) {
msg = "同步失败,人员名称:" + workerInfo.getWorkerName() + ",身份证号:" + workerInfo.getIdCard() + "。失败原因平台连接isc网络异常";
} else if (e instanceof OpenPromptException) {
msg = "同步失败,人员名称:" + workerInfo.getWorkerName() + ",身份证号:" + workerInfo.getIdCard() + "。失败原因:" + e.getMessage();
} else {
msg = "同步失败,人员名称:" + workerInfo.getWorkerName() + ",身份证号:" + workerInfo.getIdCard() + "。失败原因:下发异常";
}
if (ThreadLocalUtil.getByKey(Cts.TL_AUTH_USER, UserInfo.class) != null) {
noticeService.addUserNotice(ThreadLocalUtil.getByKey(Cts.TL_AUTH_USER, UserInfo.class).getUserId(), title, msg, type);
}
hikvisionCall.updateAllFailStatusIfNull(workerInfo.getProjectSn(), workerInfo.getId(), 1);
}
/**
* 异步删除人员
*
* @param uniqueId
* @param workerInfo
*/
@Async("workerHkExecutor")
public void deleteWorkerForHikvisionAsync(String uniqueId, WorkerInfo workerInfo) {
try {
hikvisionCall.deleteWorkerForHikvision(uniqueId, workerInfo, true);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForWorker(workerInfo, e, "删除");
}
}
/**
* 删除人员
*
* @param uniqueId
* @param workerInfo
*/
public void deleteWorkerForHikvision(String uniqueId, WorkerInfo workerInfo) {
this.deleteWorkerForHikvisionAsync(uniqueId, workerInfo);
}
/**
* 异步添加车辆
*
* @param carInfo
*/
@Async("carInfoExecutor")
public void addCarInfoForHikvisionAsync(CarInfo carInfo) {
try {
hikvisionCall.saveCarInfoFromHikvision(carInfo);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForCar(carInfo, e, "添加");
}
}
/**
* 添加车辆
*
* @param carInfo
*/
public void addCarInfoForHikvision(CarInfo carInfo) {
this.addCarInfoForHikvisionAsync(carInfo);
}
/**
* 为车辆发送通知和设置下发状态
*
* @param carInfo
* @param e
* @param action
*/
private void sendNoticeForCar(CarInfo carInfo, Exception e, String action) {
String title = action + "车辆到海康isc失败";
String type = "24";
String msg = null;
if (HttpUtils.isTimeOut(e)) {
msg = "同步失败,车牌号:" + carInfo.getCarNumber() + "。失败原因平台连接isc网络异常";
} else if (e instanceof OpenPromptException) {
msg = "同步失败,车牌号:" + carInfo.getCarNumber() + "。失败原因:" + e.getMessage();
} else {
msg = "同步失败,车牌号:" + carInfo.getCarNumber() + "。失败原因:下发异常";
}
if (ThreadLocalUtil.getByKey(Cts.TL_AUTH_USER, UserInfo.class) != null) {
noticeService.addUserNotice(ThreadLocalUtil.getByKey(Cts.TL_AUTH_USER, UserInfo.class).getUserId(), title, msg, type);
}
hikvisionCall.updateAllFailStatusIfNull(carInfo.getProjectSn(), carInfo.getId(), 2);
}
/**
* 异步编辑车辆
*
* @param carInfo
* @param old
*/
@Async("carInfoExecutor")
public void editCarInfoForHikvisionAsync(CarInfo carInfo, CarInfo old) {
try {
hikvisionCall.editCarInfoForHikvision(carInfo, old);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForCar(carInfo, e, "编辑");
}
}
/**
* 编辑车辆
*
* @param carInfo
* @param old
*/
public void editCarInfoForHikvision(CarInfo carInfo, CarInfo old) {
this.editCarInfoForHikvisionAsync(carInfo, old);
}
/**
* 异步删除车辆并设置车辆黑名单状态
*
* @param carInfo
* @param isSetBlack
*/
@Async("carInfoExecutor")
public void deleteCarInfoAndSetBlackForHikvisionAsync(CarInfo carInfo, boolean isSetBlack) {
try {
hikvisionCall.deleteCarInfoForHikvision(carInfo, isSetBlack);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForCar(carInfo, e, "删除");
}
}
/**
* 删除车辆并设置车辆黑名单状态
*
* @param carInfo
* @param isSetBlack
*/
public void deleteCarInfoAndSetBlackForHikvision(CarInfo carInfo, boolean isSetBlack) {
this.deleteCarInfoAndSetBlackForHikvisionAsync(carInfo, isSetBlack);
}
/**
* 添加企业
*
* @param enterpriseInfo
*/
@Async("carInfoExecutor")
public void addEnterpriseInfoForHikvision(EnterpriseInfo enterpriseInfo) {
try {
hikvisionCall.addEnterpriseInfoForHikvision(enterpriseInfo);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForOrg(enterpriseInfo.getEnterpriseName(), e, "新增");
}
}
/**
* 为组织发送通知和设置下发状态
*
* @param name
* @param e
* @param action
*/
private void sendNoticeForOrg(String name, Exception e, String action) {
String title = action + "组织到海康isc失败";
String type = "23";
String msg;
if (HttpUtils.isTimeOut(e)) {
msg = "同步失败,组织名称:" + name + "。失败原因平台连接isc网络异常";
} else if (e instanceof OpenPromptException) {
msg = "同步失败,组织名称:" + name + "。失败原因:" + e.getMessage();
} else {
msg = "同步失败,组织名称:" + name + "。失败原因:下发异常";
}
if (ThreadLocalUtil.getByKey(Cts.TL_AUTH_USER, UserInfo.class) != null) {
noticeService.addUserNotice(ThreadLocalUtil.getByKey(Cts.TL_AUTH_USER, UserInfo.class).getUserId(), title, msg, type);
}
xzHikvisionCompareDataService.compareRetryFail();
}
/**
* 编辑企业
*
* @param enterpriseInfo
*/
@Async("carInfoExecutor")
public void editEnterpriseInfoForHikvision(EnterpriseInfo enterpriseInfo) {
try {
hikvisionCall.editEnterpriseInfoForHikvision(enterpriseInfo);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForOrg(enterpriseInfo.getEnterpriseName(), e, "编辑");
}
}
/**
* 删除企业
*
* @param projectSn
* @param enterpriseName
*/
@Async("carInfoExecutor")
public void deleteEnterpriseInfoForHikvision(String projectSn, String enterpriseName) {
try {
hikvisionCall.deleteEnterpriseInfoForHikvision(projectSn, enterpriseName);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForOrg(enterpriseName, e, "删除");
}
}
/**
* 异步编辑班组
*
* @param teamInfo
*/
@Async("carInfoExecutor")
public void editTeamInfoForHikvision(TeamInfo teamInfo) {
try {
hikvisionCall.editTeamInfoForHikvision(teamInfo);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForOrg(teamInfo.getTeamName(), e, "编辑");
}
}
/**
* 异步删除班组
*
* @param id
* @param teamInfo
*/
@Async("carInfoExecutor")
public void deleteTeamInfoForHikvision(String id, TeamInfo teamInfo) {
try {
hikvisionCall.deleteTeamInfoForHikvision(id, teamInfo);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForOrg(teamInfo.getTeamName(), e, "删除");
}
}
/**
* 异步添加班组
*
* @param teamInfo
*/
@Async("carInfoExecutor")
public void addTeamInfoForHikvision(TeamInfo teamInfo) {
try {
hikvisionCall.addTeamInfoForHikvision(teamInfo);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForOrg(teamInfo.getTeamName(), e, "新增");
}
}
/**
* 异步编辑部门
*
* @param teamInfo
*/
@Async("carInfoExecutor")
public void editDepartmentInfoForHikvision(DepartmentInfo teamInfo) {
try {
hikvisionCall.editDepartmentInfoForHikvision(teamInfo);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForOrg(teamInfo.getDepartmentName(), e, "编辑");
}
}
/**
* 异步添加部门
*
* @param teamInfo
*/
@Async("carInfoExecutor")
public void addDepartmentInfoForHikvision(DepartmentInfo teamInfo) {
try {
hikvisionCall.addDepartmentInfoForHikvision(teamInfo);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForOrg(teamInfo.getDepartmentName(), e, "新增");
}
}
/**
* 异步删除部门
*
* @param uniqueId
* @param departmentInfo
*/
@Async("carInfoExecutor")
public void deleteDepartmentInfoForHikvision(String uniqueId, DepartmentInfo departmentInfo) {
try {
hikvisionCall.deleteDepartmentInfoForHikvision(uniqueId, departmentInfo);
} catch (Exception e) {
log.error("海康:", e);
sendNoticeForOrg(departmentInfo.getDepartmentName(), e, "删除");
}
}
/**
* 异步编辑项目
*
* @param project
*/
@Async("carInfoExecutor")
public void editProjectForHikvision(Project project) {
try {
hikvisionCall.editProjectForHikvision(project);
} catch (Exception e) {
log.error("海康:", e);
}
}
/**
* 异步获取车辆通行数据
*
* @param paramMap
*/
@Async("getRecordForHikvisionTask")
public void getCrossRecordsAsync(HashMap<String, Object> paramMap) {
hikvisionCall.getCrossRecords(paramMap);
}
/**
* 异步获取人员通行数据
*
* @param paramMap
*/
@Async("getRecordForHikvisionTask")
public void getDoorEventsAsync(HashMap<String, Object> paramMap) {
hikvisionCall.getDoorEvents(paramMap);
}
/**
* 批量下发人员
*
* @param allDevList
* @param workerList 下发的人员
* @param workerAndDevSnList 构建的下发的人员和设备的关系
* @param userId 批量下发的通知的人
* @param checkEditWorkers
* @param sendNotice
* @param flowStartUser
*/
@Async("workerAuthHkExecutor")
public void sendBatchWorkerInfoAsync(List<UfaceDev> allDevList, List<WorkerInfo> workerList, List<JSONObject> workerAndDevSnList, Long userId, String projectSn, boolean checkEditWorkers, boolean sendNotice, Long flowStartUser) {
try {
if (CollUtil.isNotEmpty(workerAndDevSnList)) {
ProjectInfoExtVo project = projectService.getProjectInfoBySn(projectSn);
//判断人员的图片存在isc
Map<String, WorkerInfo> workerIdMap = workerList.stream().collect(Collectors.toMap(workerInfo -> workerInfo.getId() + "", Function.identity()));
ArrayList<Future> futures = new ArrayList<>();
if (checkEditWorkers) {
ArrayList<WorkerInfo> needEditWorkers = getNeedEditWorkers(workerList, project, workerIdMap);
if (CollUtil.isNotEmpty(needEditWorkers)) {
for (WorkerInfo workerInfo : needEditWorkers) {
Future future = workerInfoService.editWorkerAsyncForSendBatchAuth(workerInfo);
futures.add(future);
}
}
for (Future future : futures) {
future.get();
}
}
Map<String, UfaceDev> devSnMap = allDevList.stream().collect(Collectors.toMap(UfaceDev::getDevSn, Function.identity()));
JSONObject gdvJo = HikvisionUtil.getDoorsV2(project, HikvisionUtil.addPageParamIfAbsent(new JSONObject()));
JSONObject gdvDataJo = HikvisionUtil.getJsonObjectData(gdvJo);
//门禁设备编号parentIndexCode门禁点编号indexCode门禁设备资源通道号channelNo
Map<String, JSONObject> devSnToIscDevSnMap = gdvDataJo.getJSONArray("list").stream().collect(Collectors.toMap(o -> ((JSONObject) o).getString("indexCode"), o -> (JSONObject) o));
workerAndDevSnList = this.addNeedSimpleAuthProp(workerAndDevSnList, devSnToIscDevSnMap, project);
Map<String, List<JSONObject>> devSnToJoMap = workerAndDevSnList.stream().collect(Collectors.groupingBy(jsonObject -> jsonObject.getString("devSn")));
futures = new ArrayList<>();
for (Map.Entry<String, List<JSONObject>> entry : devSnToJoMap.entrySet()) {
JSONObject iscDevSnObj = devSnToIscDevSnMap.get(entry.getKey());
Future future = asyncHikvision.sendBatchWorkersForOneDevAsync(devSnMap.get(entry.getKey()), entry, workerIdMap, workerList, project, projectSn, sendNotice, flowStartUser, iscDevSnObj);
futures.add(future);
}
for (Future future : futures) {
future.get();
}
}
//下发完成
if (userId != null) {
java.text.DateFormat format1 = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String redNotice = "";
List<String> redNameList = workerList.stream().filter(w -> NumberUtils.lt(w.getSafeScore(), PropertiesUtil.getWorkerInfoRedScore())).map(WorkerInfo::getWorkerName).collect(Collectors.toList());
if (CollUtil.isNotEmpty(redNameList)) {
redNotice = StrUtil.format("{}是红码不下发", StrUtil.join(Cts.COMMA, redNameList));
}
Notice notice = new Notice();
notice.setAccountId(userId);
notice.setMsg(StrUtil.format("已经完成批量向设备下发{}个人{}", workerList.size() - redNameList.size(), redNotice));
notice.setTitle("人员批量下发设备提醒");
notice.setSendTime(format1.format(new Date()));
notice.setType("1");
noticeService.addNotice(notice, true);
}
} catch (Exception e) {
log.error("批量下发权限失败:", e);
hikvisionCall.updateAllFailStatusIfNullForAuth(projectSn, workerList, 1, 1);
hikvisionCall.updateAllFailStatusIfNullForAuth(projectSn, workerList, 1, 3);
sendExcNotice(e, workerList, null, projectSn, flowStartUser, new ArrayList<>());
}
}
/**
* 添加需要简单权限删除的标志
*
* @param workerAndDevSnList
* @param devSnToIscDevSnMap
* @param project
* @return
*/
private List<JSONObject> addNeedSimpleAuthProp(List<JSONObject> workerAndDevSnList, Map<String, JSONObject> devSnToIscDevSnMap, Project project) throws Exception {
JSONArray rtJa = new JSONArray();
List<String> workerIds = workerAndDevSnList.stream().filter(o -> !o.getBoolean(Cts.IS_ADD_AUTH)).map(o -> o.getString("workerId")).distinct().collect(Collectors.toList());
Map<String, JSONObject> iscDevMap = new HashMap<>();
if (CollUtil.isNotEmpty(workerIds)) {
Set<Map.Entry<String, JSONObject>> iscDevEntries = devSnToIscDevSnMap.entrySet();
for (List<String> splitList : CollUtil.splitList(workerIds, MAX_PAGE_SIZE)) {
JSONObject qaiJo = getQueryAuthItemParam(splitList, iscDevEntries.stream().map(e -> {
return new JoBuilder()
.put("resourceIndexCode", e.getValue().getString("parentIndexCode"))
.put("resourceType", "acsDevice")
.put("channelNos", Collections.singletonList(e.getValue().getString("channelNo")))
.build();
}).collect(Collectors.toList()));
JSONObject qaiRtJo = HikvisionUtil.getJsonObjectData(HikvisionUtil.queryAuthItem(project, qaiJo));
JSONArray qaiList = qaiRtJo.getJSONArray("list");
if (CollUtil.isNotEmpty(qaiList)) {
rtJa.addAll(qaiList);
}
}
List<JSONObject> simpleDeleteAuths = rtJa.stream().filter(o -> {
JSONArray ja = ((JSONObject) o).getJSONArray("templateConfigInfos");
if (CollUtil.isNotEmpty(ja)) {
JSONObject jo = ja.getJSONObject(0);
if (jo != null) {
return Objects.equals(jo.getInteger("dimension"), 1);
}
}
return false;
}).map(o -> ((JSONObject) o)).collect(Collectors.toList());
iscDevMap = simpleDeleteAuths.stream().collect(Collectors.toMap(o -> o.getString("resourceIndexCode") + Cts.COMMA + o.getString("channelNo"), Function.identity()));
}
for (JSONObject jo : workerAndDevSnList) {
String devSn = jo.getString("devSn");
JSONObject iscDevJo = devSnToIscDevSnMap.get(devSn);
JSONObject have = iscDevMap.get(iscDevJo.get("parentIndexCode") + Cts.COMMA + iscDevJo.get("channelNo"));
if (have != null) {
jo.put(Cts.IS_SIMPLE_DELETE_AUTH, true);
} else {
jo.put(Cts.IS_SIMPLE_DELETE_AUTH, false);
}
}
return workerAndDevSnList;
}
/**
* 发送异常通知
*
* @param e
* @param workerList
* @param dev
* @param projectSn
* @param flowStartUser
*/
private void sendExcNotice(Exception e, List<WorkerInfo> workerList, UfaceDev dev, String projectSn, Long flowStartUser, List<String> deleteAuthWorkerIds) {
String exc;
if (HttpUtils.isTimeOut(e)) {
exc = "连接ISC网络异常";
} else {
exc = ",下发异常";
}
if (CollUtil.isNotEmpty(workerList)) {
List<WorkerInfo> failWorkers = workerInfoService.list(Wrappers.<WorkerInfo>lambdaQuery()
.eq(WorkerInfo::getProjectSn, projectSn)
.ne(WorkerInfo::getSendSuccessStatus, 1)
.in(WorkerInfo::getId, workerList.stream().map(WorkerInfo::getId).collect(Collectors.toList()))
);
for (WorkerInfo workerInfo : failWorkers) {
Set<Long> noticeUserIds = hikvisionCall.getNoticeUserIds(flowStartUser, workerInfo.getProjectSn());
for (Long noticeUserId : noticeUserIds) {
noticeService.addUserNotice(noticeUserId,
"人员下发设备提醒", StrUtil.format("[{}]{}下发{}设备权限失败{}", workerInfo.getWorkerName(), deleteAuthWorkerIds.contains(workerInfo.getId() + "") ? "取消" : "", (dev != null ? "[" + dev.getDevName() + "]" : "有些"), exc),
"1");
}
}
}
}
/**
* 获取需要编辑的人员
*
* @param workerList
* @param project
* @param workerIdMap
* @return
* @throws Exception
*/
private ArrayList<WorkerInfo> getNeedEditWorkers(List<WorkerInfo> workerList, ProjectInfoExtVo project, Map<String, WorkerInfo> workerIdMap) throws Exception {
ArrayList<WorkerInfo> needEditWorkers = new ArrayList<>();
JSONArray plListJa = getPersonListByWorkerList(workerList, project);
HashSet<String> iscPersonIds = new HashSet<>();
for (int i = 0; i < plListJa.size(); i++) {
JSONObject jo = plListJa.getJSONObject(i);
JSONArray personPhotoJa = jo.getJSONArray("personPhoto");
WorkerInfo workerInfo = workerIdMap.get(jo.getString("personId"));
if (CollUtil.isEmpty(personPhotoJa)) {
//不存在就编辑人员
needEditWorkers.add(workerInfo);
}
iscPersonIds.add(String.valueOf(workerInfo.getId()));
}
for (WorkerInfo workerInfo : workerList) {
if (!iscPersonIds.contains(workerInfo.getId() + "")) {
needEditWorkers.add(workerInfo);
}
}
return needEditWorkers;
}
/**
* 根据人员列表获取isc人员列表
*
* @param workerList
* @param project
* @return
* @throws Exception
*/
private JSONArray getPersonListByWorkerList(List<WorkerInfo> workerList, ProjectInfoExtVo project) throws Exception {
JSONArray rtJa = new JSONArray();
for (List<WorkerInfo> splitList : CollUtil.splitList(workerList, MAX_PAGE_SIZE)) {
JSONObject plJo = HikvisionUtil.queryPersonList(project, new JoBuilder()
.put("personIds", StrUtil.join(Cts.COMMA, splitList.stream().map(WorkerInfo::getId).collect(Collectors.toList())))
.put("pageNo", 1)
.put("pageSize", MAX_PAGE_SIZE)
.build());
JSONObject plDataJo = HikvisionUtil.getJsonObjectData(plJo);
JSONArray plListJa = plDataJo.getJSONArray("list");
rtJa.addAll(plListJa);
}
return rtJa;
}
/**
* 一个设备批量下发人员
*
* @param dev
* @param devSnToJoEntry
* @param workerIdMap
* @param workerList
* @param project
* @param sendNotice
* @param flowStartUser
* @param iscDevSnObj
*/
@Async("workerBeWaitHkExecutor")
public Future sendBatchWorkersForOneDevAsync(UfaceDev dev, Map.Entry<String, List<JSONObject>> devSnToJoEntry, Map<String, WorkerInfo> workerIdMap, List<WorkerInfo> workerList, ProjectInfoExtVo project, String projectSn, boolean sendNotice, Long flowStartUser, JSONObject iscDevSnObj) {
String devSn = devSnToJoEntry.getKey();
List<String> addAuthWorkerIds = devSnToJoEntry.getValue().stream().filter(jo -> jo.getBoolean(Cts.IS_ADD_AUTH)).map(jsonObject -> jsonObject.getString("workerId")).collect(Collectors.toList());
List<String> deleteAuthWorkerIds = devSnToJoEntry.getValue().stream().filter(jo -> !jo.getBoolean(Cts.IS_ADD_AUTH) && !jo.getBoolean(Cts.IS_SIMPLE_DELETE_AUTH)).map(jsonObject -> jsonObject.getString("workerId")).collect(Collectors.toList());
List<String> deleteSimpleAuthWorkerIds = devSnToJoEntry.getValue().stream().filter(jo -> !jo.getBoolean(Cts.IS_ADD_AUTH) && jo.getBoolean(Cts.IS_SIMPLE_DELETE_AUTH)).map(jsonObject -> jsonObject.getString("workerId")).collect(Collectors.toList());
try {
if (CollUtil.isNotEmpty(deleteSimpleAuthWorkerIds)) {
//需要简单删除权限方法
for (String workerId : deleteSimpleAuthWorkerIds) {
Future future = asyncHikvision.simpleDeletePersonAuthAsync(workerId, dev, project, flowStartUser, workerIdMap, iscDevSnObj);
future.get();
}
}
//【添加权限配置】(人员列表,设备列表),这个接口只要没报错,你就直接去下一步就行了。
if (CollUtil.isEmpty(addAuthWorkerIds) && CollUtil.isEmpty(deleteAuthWorkerIds)) {
log.error("无权限添加或删除,跳过");
return null;
}
if (CollUtil.isNotEmpty(addAuthWorkerIds)) {
addAuthByWorkerList(project, addAuthWorkerIds, iscDevSnObj);
}
if (CollUtil.isNotEmpty(deleteAuthWorkerIds)) {
deleteAuthByWorkerList(project, deleteAuthWorkerIds, iscDevSnObj);
}
//然后调用【根据出入权限配置快捷下载】(设备列表)(【添加权限配置】+【快捷下发】这是一个流程,你添加了几个权限,下发成功之后,就清零了)
JSONObject daJo = HikvisionUtil.downloadAuth(project, getQueryDownloadProgressParam(iscDevSnObj));
JSONObject daRtJo = HikvisionUtil.getJsonObjectData(daJo);
//然后调用【查询下载任务进度】(上面那个的任务)
int totalPercent = 0;
do {
JSONObject qdpJo = HikvisionUtil.queryDownloadProgress(project, new JoBuilder()
.put("taskId", daRtJo.getString("taskId"))
.build());
totalPercent = HikvisionUtil.getJsonObjectData(qdpJo).getInteger("totalPercent");
Thread.sleep(MAX_PAGE_SIZE);
} while (totalPercent != 100);
//权限下发后进度100后用【查询权限条目列表】人员列表设备列表接口去查返回参数有权限状态返回已下载的就是有权限
List<String> workerIds = devSnToJoEntry.getValue().stream().map(jsonObject -> jsonObject.getString("workerId")).collect(Collectors.toList());
JSONArray qaiList = queryAuthItemByWorkerList(project, workerIds, getDevRqParam(iscDevSnObj));
Set<String> rtWorkerIdSet;
if (CollUtil.isNotEmpty(qaiList)) {
for (int i = 0; i < qaiList.size(); i++) {
handlerBatchWorkersResult(workerIdMap, addAuthWorkerIds, sendNotice, dev, flowStartUser, qaiList.getJSONObject(i));
}
rtWorkerIdSet = qaiList.stream().map(o -> ((JSONObject) o).getString("personId")).collect(Collectors.toSet());
} else {
rtWorkerIdSet = new HashSet<>();
}
//处理删除权限的结果的
//1. 删除权限配置,还没删除的时候,权限变成 2更新待删除
//2. 删除以后,删除的权限状态是 4未配置
//3. 这个人的权限都没了以后,你就查不到这个权限条目了
//handlerBatchWorkersResultForDeleteAuth();
if (sendNotice && CollUtil.isNotEmpty(deleteAuthWorkerIds)) {
for (String workerId : deleteAuthWorkerIds) {
if (rtWorkerIdSet.contains(workerId)) {
//已经处理过了
continue;
}
hikvisionCall.updateSuccessStatus(projectSn, Long.valueOf(workerId), 3, 3, devSn);
Set<Long> noticeUserIds = hikvisionCall.getNoticeUserIds(flowStartUser, projectSn);
for (Long noticeUserId : noticeUserIds) {
noticeService.addUserNotice(noticeUserId,
"人员下发设备提醒", StrUtil.format("[{}]取消下发到[{}]{}",
workerIdMap.get(workerId).getWorkerName(),
dev.getDevName(),
"成功"),
"1");
}
}
}
} catch (Exception e) {
log.error("批量下发权限失败:", e);
hikvisionCall.updateAllFailStatusIfNullForAuth(projectSn, new ArrayList<>(workerIdMap.values()), 1, 1);
hikvisionCall.updateAllFailStatusIfNullForAuth(projectSn, new ArrayList<>(workerIdMap.values()), 1, 3);
List<String> dawis = BeanUtil.copyToList(deleteAuthWorkerIds, String.class);
if (CollUtil.isNotEmpty(deleteSimpleAuthWorkerIds)) {
dawis.addAll(deleteSimpleAuthWorkerIds);
}
sendExcNotice(e, workerList, dev, projectSn, flowStartUser, dawis);
}
return null;
}
@Async("hkSimpleAuthExecutor")
public Future simpleDeletePersonAuthAsync(String workerId, UfaceDev dev, ProjectInfoExtVo project, Long flowStartUser, Map<String, WorkerInfo> workerIdMap, JSONObject iscDevSnObj) throws Exception {
hikvisionCall.simpleDeletePersonAuth(workerId, dev, project, flowStartUser, workerIdMap, iscDevSnObj);
return null;
}
/**
* 为人员列表查询权限列表
*
* @param project
* @param workerIds
* @param devRqParam
* @return
* @throws Exception
*/
private JSONArray queryAuthItemByWorkerList(ProjectInfoExtVo project, List<String> workerIds, @NotNull List<JSONObject> devRqParam) throws Exception {
JSONArray rtJa = new JSONArray();
for (List<String> splitList : CollUtil.splitList(workerIds, MAX_PAGE_SIZE)) {
JSONObject qaiJo = HikvisionUtil.queryAuthItem(project, getQueryAuthItemParam(splitList, devRqParam));
JSONObject qaiRtJo = HikvisionUtil.getJsonObjectData(qaiJo);
JSONArray qaiList = qaiRtJo.getJSONArray("list");
if (CollUtil.isNotEmpty(qaiList)) {
rtJa.addAll(qaiList);
}
}
return rtJa;
}
/**
* 为人员列表删除权限
*
* @param project
* @param deleteAuthWorkerIds
* @param jsonObject
* @throws Exception
*/
private void deleteAuthByWorkerList(ProjectInfoExtVo project, List<String> deleteAuthWorkerIds, JSONObject jsonObject) throws Exception {
for (List<String> splitWorkerIds : CollUtil.splitList(deleteAuthWorkerIds, MAX_PAGE_SIZE)) {
JSONObject jo = HikvisionUtil.deleteAuth(project, getAddOrDeleteAuthParam(splitWorkerIds, jsonObject));
HikvisionUtil.getJsonObjectData(jo);
}
}
/**
* 为人员列表添加权限
*
* @param project
* @param addAuthWorkerIds
* @param jsonObject
* @throws Exception
*/
private void addAuthByWorkerList(ProjectInfoExtVo project, List<String> addAuthWorkerIds, JSONObject jsonObject) throws Exception {
for (List<String> splitWorkerIds : CollUtil.splitList(addAuthWorkerIds, MAX_PAGE_SIZE)) {
JSONObject jo = HikvisionUtil.addAuth(project, getAddOrDeleteAuthParam(splitWorkerIds, jsonObject));
HikvisionUtil.getJsonObjectData(jo);
}
}
/**
* 处理结果:一个设备批量下发人员
*
* @param workerIdMap
* @param addAuthWorkerIds
* @param sendNotice
* @param dev
* @param flowStartUser
*/
public void handlerBatchWorkersResult(Map<String, WorkerInfo> workerIdMap, List<String> addAuthWorkerIds, boolean sendNotice, UfaceDev dev, Long flowStartUser, JSONObject jo) {
String projectSn = dev.getProjectSn();
String personId = jo.getString("personId");
//人脸状态
//0已配置未下载
//1更新待下载
//2更新待删除
//3已下载
//4未配置
//1. 删除权限配置,还没删除的时候,权限变成 2更新待删除
//2. 删除以后,删除的权限状态是 4未配置
//3. 这个人的权限都没了以后,你就查不到这个权限条目了
Integer faceStatus = jo.getInteger("faceStatus");
if (sendNotice) {
if (addAuthWorkerIds.contains(personId)) {
//添加权限
int addAuth = 3;
if (Objects.equals(faceStatus, addAuth)) {
hikvisionCall.updateSuccessStatus(projectSn, Long.valueOf(personId), 3, 1, dev.getDevSn());
Long syncId = ThreadLocalUtil.getByKey(Cts.TL_HK_SYNC_ID, Long.class);
if (syncId != null) {
redisRepository.set(Cts.HK_SYNC_AUTH_SUCCESS_KEY + syncId, 1, 60L);
}
} else {
hikvisionCall.updateFailStatus(projectSn, Long.valueOf(personId), 3, 1, dev.getDevSn());
}
Set<Long> noticeUserIds = hikvisionCall.getNoticeUserIds(flowStartUser, projectSn);
for (Long noticeUserId : noticeUserIds) {
noticeService.addUserNotice(noticeUserId,
"人员下发设备提醒", StrUtil.format("[{}]下发到[{}]{}",
workerIdMap.get(personId).getWorkerName(),
dev.getDevName(),
Objects.equals(faceStatus, 3) ? "成功" : "失败,下发异常"),
"1");
}
} else {
//删除权限
int deleteAuth = 4;
if (Objects.equals(faceStatus, deleteAuth)) {
hikvisionCall.updateSuccessStatus(projectSn, Long.valueOf(personId), 3, 3, dev.getDevSn());
} else {
hikvisionCall.updateFailStatus(projectSn, Long.valueOf(personId), 3, 3, dev.getDevSn());
}
Set<Long> noticeUserIds = hikvisionCall.getNoticeUserIds(flowStartUser, projectSn);
for (Long noticeUserId : noticeUserIds) {
noticeService.addUserNotice(noticeUserId,
"人员下发设备提醒", StrUtil.format("[{}]取消下发到[{}]{}",
workerIdMap.get(personId).getWorkerName(),
dev.getDevName(),
Objects.equals(faceStatus, deleteAuth) ? "成功" : "失败,下发异常"),
"1");
}
}
}
}
/**
* 获取添加或删除权限的参数
*
* @param workerIds
* @param jsonObject
* @return
*/
@NotNull
private JSONObject getAddOrDeleteAuthParam(List<String> workerIds, JSONObject jsonObject) {
JSONObject aaJo = new JSONObject();
aaJo.put("personDatas", Collections.singletonList(new MapBuilder<String, Object>()
.put("indexCodes", workerIds)
.put("personDataType", "person")
.build()));
aaJo.put("resourceInfos", getDevRqParam(jsonObject));
return aaJo;
}
/**
* 获取《删除权限配置》接口的设备请求的参数
*
* @param jsonObject
* @return
*/
@NotNull
private List<JSONObject> getDevRqParam(JSONObject jsonObject) {
return Collections.singletonList(new JoBuilder()
.put("resourceIndexCode", jsonObject.getString("parentIndexCode"))
.put("resourceType", "acsDevice")
.put("channelNos", Collections.singletonList(jsonObject.getString("channelNo")))
.build());
}
/**
* 获取《根据出入权限配置快捷下载》接口的请求的参数
*
* @param jsonObject
* @return
*/
private JSONObject getQueryDownloadProgressParam(JSONObject jsonObject) {
JSONObject aaJo = new JSONObject();
aaJo.put("taskType", 4);
aaJo.put("resourceInfos", getDevRqParam(jsonObject));
return aaJo;
}
/**
* 获取《查询权限条目列表》的请求参数
*
* @param workerIds
* @param devRqParam
* @return
*/
private JSONObject getQueryAuthItemParam(List<String> workerIds, @NotNull List<JSONObject> devRqParam) {
JSONObject aaJo = new JSONObject();
aaJo.put("personIds", workerIds);
aaJo.put("resourceInfos", devRqParam);
aaJo.put("queryType", "acsDevice");
aaJo.put("pageNo", 1);
aaJo.put("pageSize", MAX_PAGE_SIZE);
return aaJo;
}
}