增加人员聚集,非法停车自动指派操作
This commit is contained in:
@@ -8,7 +8,7 @@ import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
|||||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||||
import org.dromara.sis.rocketmq.RocketMqConstants;
|
import org.dromara.sis.rocketmq.RocketMqConstants;
|
||||||
import org.dromara.sis.rocketmq.domain.FaceCapture;
|
import org.dromara.sis.rocketmq.domain.FaceCapture;
|
||||||
import org.dromara.sis.service.IZeroSensationPassageService;
|
import org.dromara.sis.service.IEventAlarmReportService;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,14 +27,14 @@ import org.springframework.stereotype.Component;
|
|||||||
)
|
)
|
||||||
public class FaceCaptureConsumer implements RocketMQListener<MessageExt> {
|
public class FaceCaptureConsumer implements RocketMQListener<MessageExt> {
|
||||||
|
|
||||||
private final IZeroSensationPassageService zeroSensationPassageService;
|
private final IEventAlarmReportService eventAlarmReportService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(MessageExt ext) {
|
public void onMessage(MessageExt ext) {
|
||||||
log.info("消费人脸抓拍数据,数据长度={}", ext.getBody().length);
|
log.info("消费人脸抓拍数据,数据长度={}", ext.getBody().length);
|
||||||
try {
|
try {
|
||||||
FaceCapture capture = JSONObject.parseObject(ext.getBody(), FaceCapture.class);
|
FaceCapture capture = JSONObject.parseObject(ext.getBody(), FaceCapture.class);
|
||||||
zeroSensationPassageService.pass(capture.getDeviceIp(), capture.getSmallImg(), capture.getBigImg());
|
eventAlarmReportService.handleCaptureImg(capture.getDeviceIp(), capture.getSmallImg(), capture.getBigImg());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("消费人脸抓拍数据处理失败,", e);
|
log.error("消费人脸抓拍数据处理失败,", e);
|
||||||
}
|
}
|
||||||
|
@@ -23,4 +23,14 @@ public interface IEventAlarmReportService {
|
|||||||
* @param density 上报信息
|
* @param density 上报信息
|
||||||
*/
|
*/
|
||||||
void handleHighDensity(HighDensity density);
|
void handleHighDensity(HighDensity density);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理人像抓拍
|
||||||
|
*
|
||||||
|
* @param deviceIp 设备ip
|
||||||
|
* @param smallImg 小图
|
||||||
|
* @param bigImg 大图
|
||||||
|
*/
|
||||||
|
void handleCaptureImg(String deviceIp, byte[] smallImg, byte[] bigImg);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,21 +0,0 @@
|
|||||||
package org.dromara.sis.service;
|
|
||||||
|
|
||||||
public interface IZeroSensationPassageService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无感通行服务
|
|
||||||
*
|
|
||||||
* @param deviceIp 设备ip
|
|
||||||
* @param smallImp 人脸小图
|
|
||||||
* @param bigImg 背景图片
|
|
||||||
*/
|
|
||||||
void pass(String deviceIp, byte[] smallImp, byte[] bigImg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电梯外部按键触发
|
|
||||||
*
|
|
||||||
* @param deviceIp 设备ip
|
|
||||||
*/
|
|
||||||
void handleEleOut(String deviceIp);
|
|
||||||
|
|
||||||
}
|
|
@@ -1,16 +1,38 @@
|
|||||||
package org.dromara.sis.service.impl;
|
package org.dromara.sis.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.context.mock.SaTokenContextMockUtil;
|
||||||
|
import cn.hutool.core.codec.Base64Encoder;
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.date.TimeInterval;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.dubbo.config.annotation.DubboReference;
|
||||||
|
import org.dromara.property.api.RemoteAttendanceService;
|
||||||
|
import org.dromara.property.api.RemoteFloorService;
|
||||||
|
import org.dromara.property.api.domain.vo.RemoteAttendanceUserGroupVo;
|
||||||
|
import org.dromara.property.api.domain.vo.RemoteFloorVo;
|
||||||
import org.dromara.sis.domain.SisAlarmEvents;
|
import org.dromara.sis.domain.SisAlarmEvents;
|
||||||
|
import org.dromara.sis.domain.bo.alarm.AlarmAssignmentBo;
|
||||||
|
import org.dromara.sis.domain.enums.ControlTypeEnum;
|
||||||
import org.dromara.sis.domain.enums.EventSmallTypeEnum;
|
import org.dromara.sis.domain.enums.EventSmallTypeEnum;
|
||||||
|
import org.dromara.sis.domain.enums.RosterTypeEnum;
|
||||||
|
import org.dromara.sis.domain.vo.*;
|
||||||
import org.dromara.sis.rocketmq.domain.HighDensity;
|
import org.dromara.sis.rocketmq.domain.HighDensity;
|
||||||
import org.dromara.sis.rocketmq.domain.ParkingReport;
|
import org.dromara.sis.rocketmq.domain.ParkingReport;
|
||||||
import org.dromara.sis.service.IEventAlarmReportService;
|
import org.dromara.sis.sdk.e8.E8PlatformApi;
|
||||||
import org.dromara.sis.service.ISisAlarmEventsService;
|
import org.dromara.sis.sdk.e8.domain.accessControl.req.RemoteOpenDoorReq;
|
||||||
|
import org.dromara.sis.sdk.hik.HikApiService;
|
||||||
|
import org.dromara.sis.sdk.huawei.HuaWeiBoxApi;
|
||||||
|
import org.dromara.sis.sdk.huawei.domain.HWResult;
|
||||||
|
import org.dromara.sis.sdk.smartDevices.utils.ElevatorControlTcpUtil;
|
||||||
|
import org.dromara.sis.service.*;
|
||||||
|
import org.dromara.system.api.RemoteUserService;
|
||||||
|
import org.dromara.system.api.domain.vo.RemoteUserVo;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理设备告警上报服务
|
* 处理设备告警上报服务
|
||||||
@@ -23,6 +45,23 @@ import java.util.List;
|
|||||||
public class EventAlarmReportServiceImpl implements IEventAlarmReportService {
|
public class EventAlarmReportServiceImpl implements IEventAlarmReportService {
|
||||||
|
|
||||||
private final ISisAlarmEventsService alarmEventsService;
|
private final ISisAlarmEventsService alarmEventsService;
|
||||||
|
private final HuaWeiBoxApi huaWeiBoxApi;
|
||||||
|
private final ISisAuthRecordService authRecordService;
|
||||||
|
private final ISisElevatorInfoService elevatorInfoService;
|
||||||
|
private final ISisAuthGroupRefService authGroupRefService;
|
||||||
|
private final ISisDeviceBindRefService deviceBindRefService;
|
||||||
|
private final ISisAccessControlService accessControlService;
|
||||||
|
private final ISisElevatorFloorRefService elevatorFloorRefService;
|
||||||
|
private final ISisElevatorFloorChannelRefService elevatorFloorChannelRefService;
|
||||||
|
private final E8PlatformApi e8PlatformApi;
|
||||||
|
private final HikApiService hikApiService;
|
||||||
|
|
||||||
|
@DubboReference
|
||||||
|
private RemoteFloorService remoteFloorService;
|
||||||
|
@DubboReference
|
||||||
|
private RemoteAttendanceService remoteAttendanceService;
|
||||||
|
@DubboReference
|
||||||
|
private RemoteUserService remoteUserService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleParking(ParkingReport report) {
|
public void handleParking(ParkingReport report) {
|
||||||
@@ -34,6 +73,169 @@ public class EventAlarmReportServiceImpl implements IEventAlarmReportService {
|
|||||||
handleAlarm(density.getDeviceIp(), density.getImg(), 2, EventSmallTypeEnum.SMART_REPORT_RYJJ, "人员聚集报警");
|
handleAlarm(density.getDeviceIp(), density.getImg(), 2, EventSmallTypeEnum.SMART_REPORT_RYJJ, "人员聚集报警");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCaptureImg(String deviceIp, byte[] smallImg, byte[] bigImg) {
|
||||||
|
TimeInterval interval = new TimeInterval();
|
||||||
|
// 抓拍小图
|
||||||
|
String smallImgBase64Str = Base64Encoder.encode(smallImg);
|
||||||
|
HWResult<Long> result = huaWeiBoxApi.findPerson(smallImgBase64Str);
|
||||||
|
if (result.getCode() != 200) {
|
||||||
|
log.info("华为盒子比对失败,msg={}", result.getMessage());
|
||||||
|
// 产生告警数据 人脸比对失败,默认为
|
||||||
|
handleAlarm(deviceIp, smallImg, bigImg, 2, EventSmallTypeEnum.SMART_REPORT_ZJCR, "人脸比对失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.info("人脸比对执行完成,耗时:{}ms", interval.intervalMs());
|
||||||
|
Long person = result.getData();
|
||||||
|
// 验证当前人原是否存在授权记录
|
||||||
|
SisAuthRecordVo authRecord = authRecordService.checkAuth(person);
|
||||||
|
log.info("查询人员权限记录完成,耗时={}ms", interval.intervalMs());
|
||||||
|
if (authRecord == null) {
|
||||||
|
log.info("人员[{}]没有授权记录,判定为陌生人", person);
|
||||||
|
// 不是内部人员 产生紧急的告警信息
|
||||||
|
handleAlarm(deviceIp, smallImg, bigImg, 2, EventSmallTypeEnum.SMART_REPORT_ZJCR, "陌生人员入内");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (Objects.equals(authRecord.getRosterType(), RosterTypeEnum.BLACK_LIST.getCode())) {
|
||||||
|
log.info("黑名单人员[{}]。", person);
|
||||||
|
handleAlarm(deviceIp, smallImg, bigImg, 3, EventSmallTypeEnum.BLACK_PERSON, "黑名单人员");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Date now = new Date();
|
||||||
|
if (DateUtil.compare(now, authRecord.getEndDate()) > 0) {
|
||||||
|
handleAlarm(deviceIp, smallImg, bigImg, 1, EventSmallTypeEnum.AUTHORIZATION_EXPIRED, "人员授权信息已过期");
|
||||||
|
log.info("当前人脸已过期。person={}", person);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 获取当前设备的绑定设备信息
|
||||||
|
List<SisDeviceBindRefVo> bindRefList = deviceBindRefService.queryByDeviceIp(deviceIp);
|
||||||
|
log.info("查询设备绑定的梯控/门禁完成,耗时={}ms", interval.intervalMs());
|
||||||
|
|
||||||
|
if (CollUtil.isEmpty(bindRefList)) {
|
||||||
|
log.info("当前报警设备未绑定门禁/梯控,不做处理!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 授权设备列表
|
||||||
|
List<SisAuthGroupRefVo> authGroupRefVos = authGroupRefService.queryListByGroupId(authRecord.getGroupId());
|
||||||
|
// 验证当前设备的绑定门禁和梯控是否有使用权限
|
||||||
|
bindRefList.forEach(item -> {
|
||||||
|
SisAuthGroupRefVo r = null;
|
||||||
|
for (SisAuthGroupRefVo ref : authGroupRefVos) {
|
||||||
|
if (Objects.equals(item.getBindId(), ref.getDeviceId())) {
|
||||||
|
r = ref;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (r == null) {
|
||||||
|
log.info("人员[{}]不存在门禁/电梯[{}]的通行权限", person, item.getBindId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 判断绑定设备类型,走不同的处理方法
|
||||||
|
if (Objects.equals(item.getControlType(), ControlTypeEnum.ACCESS_CONTROL.getCode())) { // 门禁
|
||||||
|
handleAc(item.getBindId());
|
||||||
|
} else if (item.getControlType().equals(ControlTypeEnum.ELEVATOR_OUT_CONTROL.getCode())) { // 电梯外面面板权限
|
||||||
|
// handleEle(item.getBindId(), r.getAuthGroupId(), ControlTypeEnum.ELEVATOR_OUT_CONTROL.getCode(), item.getDeviceFloorId());
|
||||||
|
} else if (item.getControlType().equals(ControlTypeEnum.ELEVATOR_IN_CONTROL.getCode())) { // 电梯里面的面板
|
||||||
|
// handleEle(item.getBindId(), r.getAuthGroupId(), ControlTypeEnum.ELEVATOR_IN_CONTROL.getCode(), 0L);
|
||||||
|
} else {
|
||||||
|
log.info("设备绑定了未知的控制类型[{}],不处理", item.getControlType());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
log.info("权限下发执行完成,耗时:{}ms", interval.intervalMs());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证电梯权限
|
||||||
|
*/
|
||||||
|
public void handleEle(Long deviceId, Long groupId, Integer controlType, Long deviceFloorId) {
|
||||||
|
|
||||||
|
// 获取当前电梯信息
|
||||||
|
SisElevatorInfoVo ele = elevatorInfoService.queryById(deviceId);
|
||||||
|
// 当前电梯不允许控制
|
||||||
|
if (!ele.getIsControl()) return;
|
||||||
|
|
||||||
|
|
||||||
|
// 获取权限组下电梯⇄楼层关联信息
|
||||||
|
List<SisElevatorFloorRefVo> groupRef = elevatorFloorRefService.queryByAuthGroupId(groupId);
|
||||||
|
if (CollUtil.isEmpty(groupRef)) return;
|
||||||
|
|
||||||
|
// 取出当前电梯的楼层授权信息
|
||||||
|
List<SisElevatorFloorRefVo> eleRef = groupRef.stream().filter(o -> Objects.equals(o.getElevatorId(), deviceId)).toList();
|
||||||
|
if (ObjectUtil.isEmpty(eleRef)) return;
|
||||||
|
|
||||||
|
if (Objects.equals(controlType, ControlTypeEnum.ELEVATOR_OUT_CONTROL.getCode())) {
|
||||||
|
log.info("开始下发外部面板梯控权限....");
|
||||||
|
for (SisElevatorFloorRefVo ref : eleRef) {
|
||||||
|
if (ref.getUpChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)) {
|
||||||
|
hikApiService.controlGateway(ele.getControlIp(), ref.getUpChannel().intValue(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref.getDownChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)) {
|
||||||
|
hikApiService.controlGateway(ele.getControlIp(), ref.getDownChannel().intValue(), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模拟上下文
|
||||||
|
List<RemoteFloorVo> floorList = SaTokenContextMockUtil.setMockContext(() -> remoteFloorService.queryByBuildingId(ele.getBuildingId()));
|
||||||
|
if (CollUtil.isEmpty(floorList)) return;
|
||||||
|
|
||||||
|
if (Objects.equals(controlType, ControlTypeEnum.ELEVATOR_IN_CONTROL.getCode())) {
|
||||||
|
SisElevatorFloorRefVo vo;
|
||||||
|
List<Integer> num = new ArrayList<>();
|
||||||
|
for (int i = 1; i < floorList.size(); i++) {
|
||||||
|
int finalI = i;
|
||||||
|
// 取出权限楼层id与实际楼层id相等的数据
|
||||||
|
vo = eleRef.stream().filter(o -> Objects.equals(o.getFloorId(), floorList.get(finalI - 1).getId())).findFirst().orElse(null);
|
||||||
|
// 存在权限楼层,添加到num中,梯控模块从1开始
|
||||||
|
if (vo != null) {
|
||||||
|
num.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CollUtil.isEmpty(num)) return;
|
||||||
|
|
||||||
|
ElevatorControlTcpUtil.getInstance().sendManualCommand(num);
|
||||||
|
}
|
||||||
|
log.info("梯控下发权限完成");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理门禁
|
||||||
|
*/
|
||||||
|
public void handleAc(Long deviceId) {
|
||||||
|
if (deviceId != null) {
|
||||||
|
SisAccessControlVo ac = accessControlService.queryById(deviceId);
|
||||||
|
log.info("调用门禁服务远程开门,doorName:{}", ac.getAccessName());
|
||||||
|
RemoteOpenDoorReq req = new RemoteOpenDoorReq();
|
||||||
|
req.setType(0);
|
||||||
|
RemoteOpenDoorReq.ControlData data = new RemoteOpenDoorReq.ControlData();
|
||||||
|
data.setDeviceId(Long.parseLong(ac.getOutCode()));
|
||||||
|
data.setDoorId(Long.parseLong(ac.getOutCode()));
|
||||||
|
req.setControlList(List.of(data));
|
||||||
|
Boolean flag = e8PlatformApi.remoteOpenDoor(req);
|
||||||
|
log.info("远程开门结果,result={}", flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理告警信息
|
||||||
|
*
|
||||||
|
* @param deviceIp 设备ip
|
||||||
|
* @param smallImg 人脸小图
|
||||||
|
* @param bigImg 人脸大图
|
||||||
|
* @param smallType 事件类型
|
||||||
|
*/
|
||||||
|
private void handleAlarm(String deviceIp, byte[] smallImg, byte[] bigImg, Integer level, EventSmallTypeEnum smallType, String desc) {
|
||||||
|
List<byte[]> ls = new ArrayList<>(2);
|
||||||
|
ls.add(smallImg);
|
||||||
|
ls.add(bigImg);
|
||||||
|
// 生成告警记录
|
||||||
|
SisAlarmEvents alarmRecord = alarmEventsService.createAlarmRecord(deviceIp, level, smallType, desc, ls);
|
||||||
|
autoAssign(alarmRecord.getId(), deviceIp);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理告警信息
|
* 处理告警信息
|
||||||
*
|
*
|
||||||
@@ -44,8 +246,40 @@ public class EventAlarmReportServiceImpl implements IEventAlarmReportService {
|
|||||||
private void handleAlarm(String deviceIp, byte[] img, Integer level, EventSmallTypeEnum smallType, String desc) {
|
private void handleAlarm(String deviceIp, byte[] img, Integer level, EventSmallTypeEnum smallType, String desc) {
|
||||||
// 生成告警记录
|
// 生成告警记录
|
||||||
SisAlarmEvents alarmRecord = alarmEventsService.createAlarmRecord(deviceIp, level, smallType, desc, List.of(img));
|
SisAlarmEvents alarmRecord = alarmEventsService.createAlarmRecord(deviceIp, level, smallType, desc, List.of(img));
|
||||||
|
autoAssign(alarmRecord.getId(), deviceIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void autoAssign(Long alarmId, String deviceIp) {
|
||||||
|
SaTokenContextMockUtil.setMockContext(() -> {
|
||||||
|
// 如果当前设备区域存在排班人员,那么惊醒自动指派操作
|
||||||
|
List<RemoteAttendanceUserGroupVo> userGroupVos = remoteAttendanceService.queryAttendByCurrDateAndDeviceIp(new Date(), deviceIp);
|
||||||
|
if (CollUtil.isEmpty(userGroupVos)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 进行自动指派操作
|
||||||
|
RemoteAttendanceUserGroupVo currHandlePerson = null;
|
||||||
|
if (userGroupVos.size() == 1) {
|
||||||
|
currHandlePerson = userGroupVos.get(0);
|
||||||
|
} else {
|
||||||
|
// 生成一个排班人员课表的随机数
|
||||||
|
Random random = new Random();
|
||||||
|
int randomIndex = random.nextInt(userGroupVos.size());
|
||||||
|
currHandlePerson = userGroupVos.get(randomIndex);
|
||||||
|
}
|
||||||
|
// 获取当前指派人员的详细信息
|
||||||
|
RemoteUserVo userInfo = remoteUserService.getUserInfoById(currHandlePerson.getEmployeeId());
|
||||||
|
// 任务指派操作
|
||||||
|
AlarmAssignmentBo bo = new AlarmAssignmentBo();
|
||||||
|
bo.setAlarmId(alarmId);
|
||||||
|
bo.setSolveId(userInfo.getUserId());
|
||||||
|
bo.setSolveName(userInfo.getUserName());
|
||||||
|
bo.setSolvePhone(userInfo.getPhonenumber());
|
||||||
|
bo.setSolveEmail(userInfo.getEmail());
|
||||||
|
bo.setRemark("系统自动指派");
|
||||||
|
alarmEventsService.taskAssignment(bo);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,296 +0,0 @@
|
|||||||
package org.dromara.sis.service.impl;
|
|
||||||
|
|
||||||
import cn.dev33.satoken.context.mock.SaTokenContextMockUtil;
|
|
||||||
import cn.hutool.core.codec.Base64Encoder;
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
|
||||||
import cn.hutool.core.date.TimeInterval;
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.dubbo.config.annotation.DubboReference;
|
|
||||||
import org.dromara.property.api.RemoteAttendanceService;
|
|
||||||
import org.dromara.property.api.RemoteFloorService;
|
|
||||||
import org.dromara.property.api.domain.vo.RemoteAttendanceUserGroupVo;
|
|
||||||
import org.dromara.property.api.domain.vo.RemoteFloorVo;
|
|
||||||
import org.dromara.sis.domain.SisAlarmEvents;
|
|
||||||
import org.dromara.sis.domain.bo.alarm.AlarmAssignmentBo;
|
|
||||||
import org.dromara.sis.domain.enums.ControlTypeEnum;
|
|
||||||
import org.dromara.sis.domain.enums.EventSmallTypeEnum;
|
|
||||||
import org.dromara.sis.domain.enums.RosterTypeEnum;
|
|
||||||
import org.dromara.sis.domain.vo.*;
|
|
||||||
import org.dromara.sis.sdk.e8.E8PlatformApi;
|
|
||||||
import org.dromara.sis.sdk.e8.domain.accessControl.req.RemoteOpenDoorReq;
|
|
||||||
import org.dromara.sis.sdk.hik.HikApiService;
|
|
||||||
import org.dromara.sis.sdk.huawei.HuaWeiBoxApi;
|
|
||||||
import org.dromara.sis.sdk.huawei.domain.HWResult;
|
|
||||||
import org.dromara.sis.sdk.smartDevices.utils.ElevatorControlTcpUtil;
|
|
||||||
import org.dromara.sis.service.*;
|
|
||||||
import org.dromara.system.api.RemoteUserService;
|
|
||||||
import org.dromara.system.api.domain.vo.RemoteUserVo;
|
|
||||||
import org.springframework.scheduling.annotation.Async;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 无感通行业务服务实现
|
|
||||||
*
|
|
||||||
* @author lxj, lsm
|
|
||||||
* @since 2025-08-04
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageService {
|
|
||||||
|
|
||||||
private final HuaWeiBoxApi huaWeiBoxApi;
|
|
||||||
private final ISisAuthRecordService authRecordService;
|
|
||||||
private final ISisElevatorInfoService elevatorInfoService;
|
|
||||||
private final ISisAuthGroupRefService authGroupRefService;
|
|
||||||
private final ISisDeviceBindRefService deviceBindRefService;
|
|
||||||
private final ISisAccessControlService accessControlService;
|
|
||||||
private final ISisElevatorFloorRefService elevatorFloorRefService;
|
|
||||||
private final ISisElevatorFloorChannelRefService elevatorFloorChannelRefService;
|
|
||||||
private final E8PlatformApi e8PlatformApi;
|
|
||||||
private final ISisAlarmEventsService alarmEventsService;
|
|
||||||
private final HikApiService hikApiService;
|
|
||||||
|
|
||||||
@DubboReference
|
|
||||||
private RemoteFloorService remoteFloorService;
|
|
||||||
@DubboReference
|
|
||||||
private RemoteAttendanceService remoteAttendanceService;
|
|
||||||
@DubboReference
|
|
||||||
private RemoteUserService remoteUserService;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Async
|
|
||||||
public void pass(String deviceIp, byte[] smallImg, byte[] bigImg) {
|
|
||||||
TimeInterval interval = new TimeInterval();
|
|
||||||
// 抓拍小图
|
|
||||||
String smallImgBase64Str = Base64Encoder.encode(smallImg);
|
|
||||||
HWResult<Long> result = huaWeiBoxApi.findPerson(smallImgBase64Str);
|
|
||||||
if (result.getCode() != 200) {
|
|
||||||
log.info("华为盒子比对失败,msg={}", result.getMessage());
|
|
||||||
// 产生告警数据 人脸比对失败,默认为
|
|
||||||
handleAlarm(deviceIp, smallImg, bigImg, 2, EventSmallTypeEnum.SMART_REPORT_ZJCR, "人脸比对失败");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log.info("人脸比对执行完成,耗时:{}ms", interval.intervalMs());
|
|
||||||
Long person = result.getData();
|
|
||||||
// 验证当前人原是否存在授权记录
|
|
||||||
SisAuthRecordVo authRecord = authRecordService.checkAuth(person);
|
|
||||||
log.info("查询人员权限记录完成,耗时={}ms", interval.intervalMs());
|
|
||||||
if (authRecord == null) {
|
|
||||||
log.info("人员[{}]没有授权记录,判定为陌生人", person);
|
|
||||||
// 不是内部人员 产生紧急的告警信息
|
|
||||||
handleAlarm(deviceIp, smallImg, bigImg, 2, EventSmallTypeEnum.SMART_REPORT_ZJCR, "陌生人员入内");
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (Objects.equals(authRecord.getRosterType(), RosterTypeEnum.BLACK_LIST.getCode())) {
|
|
||||||
log.info("黑名单人员[{}]。", person);
|
|
||||||
handleAlarm(deviceIp, smallImg, bigImg, 3, EventSmallTypeEnum.BLACK_PERSON, "黑名单人员");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Date now = new Date();
|
|
||||||
if (DateUtil.compare(now, authRecord.getEndDate()) > 0) {
|
|
||||||
handleAlarm(deviceIp, smallImg, bigImg, 1, EventSmallTypeEnum.AUTHORIZATION_EXPIRED, "人员授权信息已过期");
|
|
||||||
log.info("当前人脸已过期。person={}", person);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 获取当前设备的绑定设备信息
|
|
||||||
List<SisDeviceBindRefVo> bindRefList = deviceBindRefService.queryByDeviceIp(deviceIp);
|
|
||||||
log.info("查询设备绑定的梯控/门禁完成,耗时={}ms", interval.intervalMs());
|
|
||||||
|
|
||||||
if (CollUtil.isEmpty(bindRefList)) {
|
|
||||||
log.info("当前报警设备未绑定门禁/梯控,不做处理!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 授权设备列表
|
|
||||||
List<SisAuthGroupRefVo> authGroupRefVos = authGroupRefService.queryListByGroupId(authRecord.getGroupId());
|
|
||||||
// 验证当前设备的绑定门禁和梯控是否有使用权限
|
|
||||||
bindRefList.forEach(item -> {
|
|
||||||
SisAuthGroupRefVo r = null;
|
|
||||||
for (SisAuthGroupRefVo ref : authGroupRefVos) {
|
|
||||||
if (Objects.equals(item.getBindId(), ref.getDeviceId())) {
|
|
||||||
r = ref;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (r == null) {
|
|
||||||
log.info("人员[{}]不存在门禁/电梯[{}]的通行权限", person, item.getBindId());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 判断绑定设备类型,走不同的处理方法
|
|
||||||
if (Objects.equals(item.getControlType(), ControlTypeEnum.ACCESS_CONTROL.getCode())) { // 门禁
|
|
||||||
handleAc(item.getBindId());
|
|
||||||
} else if (item.getControlType().equals(ControlTypeEnum.ELEVATOR_OUT_CONTROL.getCode())) { // 电梯外面面板权限
|
|
||||||
// handleEle(item.getBindId(), r.getAuthGroupId(), ControlTypeEnum.ELEVATOR_OUT_CONTROL.getCode(), item.getDeviceFloorId());
|
|
||||||
} else if (item.getControlType().equals(ControlTypeEnum.ELEVATOR_IN_CONTROL.getCode())) { // 电梯里面的面板
|
|
||||||
// handleEle(item.getBindId(), r.getAuthGroupId(), ControlTypeEnum.ELEVATOR_IN_CONTROL.getCode(), 0L);
|
|
||||||
} else {
|
|
||||||
log.info("设备绑定了未知的控制类型[{}],不处理", item.getControlType());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
log.info("权限下发执行完成,耗时:{}ms", interval.intervalMs());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理告警信息
|
|
||||||
*
|
|
||||||
* @param deviceIp 设备ip
|
|
||||||
* @param smallImg 人脸小图
|
|
||||||
* @param bigImg 人脸大图
|
|
||||||
* @param smallType 事件类型
|
|
||||||
*/
|
|
||||||
private void handleAlarm(String deviceIp, byte[] smallImg, byte[] bigImg, Integer level, EventSmallTypeEnum smallType, String desc) {
|
|
||||||
List<byte[]> ls = new ArrayList<>(2);
|
|
||||||
ls.add(smallImg);
|
|
||||||
ls.add(bigImg);
|
|
||||||
// 生成告警记录
|
|
||||||
SisAlarmEvents alarmRecord = alarmEventsService.createAlarmRecord(deviceIp, level, smallType, desc, ls);
|
|
||||||
SaTokenContextMockUtil.setMockContext(() -> {
|
|
||||||
// 如果当前设备区域存在排班人员,那么惊醒自动指派操作
|
|
||||||
List<RemoteAttendanceUserGroupVo> userGroupVos = remoteAttendanceService.queryAttendByCurrDateAndDeviceIp(new Date(), deviceIp);
|
|
||||||
if (CollUtil.isEmpty(userGroupVos)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 进行自动指派操作
|
|
||||||
RemoteAttendanceUserGroupVo currHandlePerson = null;
|
|
||||||
if (userGroupVos.size() == 1) {
|
|
||||||
currHandlePerson = userGroupVos.get(0);
|
|
||||||
} else {
|
|
||||||
// 生成一个排班人员课表的随机数
|
|
||||||
Random random = new Random();
|
|
||||||
int randomIndex = random.nextInt(userGroupVos.size());
|
|
||||||
currHandlePerson = userGroupVos.get(randomIndex);
|
|
||||||
}
|
|
||||||
// 获取当前指派人员的详细信息
|
|
||||||
RemoteUserVo userInfo = remoteUserService.getUserInfoById(currHandlePerson.getEmployeeId());
|
|
||||||
// 任务指派操作
|
|
||||||
AlarmAssignmentBo bo = new AlarmAssignmentBo();
|
|
||||||
bo.setAlarmId(alarmRecord.getId());
|
|
||||||
bo.setSolveId(userInfo.getUserId());
|
|
||||||
bo.setSolveName(userInfo.getUserName());
|
|
||||||
bo.setSolvePhone(userInfo.getPhonenumber());
|
|
||||||
bo.setSolveEmail(userInfo.getEmail());
|
|
||||||
bo.setRemark("系统自动指派");
|
|
||||||
alarmEventsService.taskAssignment(bo);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 电梯外部按键触发
|
|
||||||
*
|
|
||||||
* @param deviceIp 设备ip
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void handleEleOut(String deviceIp) {
|
|
||||||
TimeInterval interval = new TimeInterval();
|
|
||||||
// 获取当前设备的绑定设备信息
|
|
||||||
List<SisDeviceBindRefVo> bindRefList = deviceBindRefService.queryByDeviceIp(deviceIp);
|
|
||||||
List<SisDeviceBindRefVo> outRefList = bindRefList.stream().filter(item -> Objects.equals(item.getControlType(), ControlTypeEnum.ELEVATOR_OUT_CONTROL.getCode())).toList();
|
|
||||||
|
|
||||||
outRefList.forEach(item -> {
|
|
||||||
// 获取当前电梯信息
|
|
||||||
SisElevatorInfoVo ele = elevatorInfoService.queryById(item.getBindId());
|
|
||||||
|
|
||||||
List<SisElevatorFloorChannelRefVo> channelRef = elevatorFloorChannelRefService.queryByFloorIds(List.of(item.getDeviceFloorId()));
|
|
||||||
SisElevatorFloorChannelRefVo channelRefVo = channelRef.stream().filter(o -> Objects.equals(o.getElevatorId(), item.getBindId())).findFirst().orElse(null);
|
|
||||||
|
|
||||||
if (channelRefVo != null) {
|
|
||||||
if (channelRefVo.getDownChannel() != null) {
|
|
||||||
hikApiService.controlGateway(ele.getControlIp(), channelRefVo.getDownChannel().intValue(), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channelRefVo.getUpChannel() != null) {
|
|
||||||
hikApiService.controlGateway(ele.getControlIp(), channelRefVo.getUpChannel().intValue(), 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
log.info("处理电梯外部按键完成,耗时:{}ms", interval.intervalMs());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成告警事件
|
|
||||||
*/
|
|
||||||
public void createAlarmRecord(String deviceIp, Integer level, Integer type, String msg, byte[] smallImg, byte[] bigImg) {
|
|
||||||
// alarmEventsService.createAlarmRecord(deviceIp, level, type, msg, smallImg, bigImg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理门禁
|
|
||||||
*/
|
|
||||||
public void handleAc(Long deviceId) {
|
|
||||||
if (deviceId != null) {
|
|
||||||
SisAccessControlVo ac = accessControlService.queryById(deviceId);
|
|
||||||
log.info("调用门禁服务远程开门,doorName:{}", ac.getAccessName());
|
|
||||||
RemoteOpenDoorReq req = new RemoteOpenDoorReq();
|
|
||||||
req.setType(0);
|
|
||||||
RemoteOpenDoorReq.ControlData data = new RemoteOpenDoorReq.ControlData();
|
|
||||||
data.setDeviceId(Long.parseLong(ac.getOutCode()));
|
|
||||||
data.setDoorId(Long.parseLong(ac.getOutCode()));
|
|
||||||
req.setControlList(List.of(data));
|
|
||||||
Boolean flag = e8PlatformApi.remoteOpenDoor(req);
|
|
||||||
log.info("远程开门结果,result={}", flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证电梯权限
|
|
||||||
*/
|
|
||||||
public void handleEle(Long deviceId, Long groupId, Integer controlType, Long deviceFloorId) {
|
|
||||||
|
|
||||||
// 获取当前电梯信息
|
|
||||||
SisElevatorInfoVo ele = elevatorInfoService.queryById(deviceId);
|
|
||||||
// 当前电梯不允许控制
|
|
||||||
if (!ele.getIsControl()) return;
|
|
||||||
|
|
||||||
|
|
||||||
// 获取权限组下电梯⇄楼层关联信息
|
|
||||||
List<SisElevatorFloorRefVo> groupRef = elevatorFloorRefService.queryByAuthGroupId(groupId);
|
|
||||||
if (CollUtil.isEmpty(groupRef)) return;
|
|
||||||
|
|
||||||
// 取出当前电梯的楼层授权信息
|
|
||||||
List<SisElevatorFloorRefVo> eleRef = groupRef.stream().filter(o -> Objects.equals(o.getElevatorId(), deviceId)).toList();
|
|
||||||
if (ObjectUtil.isEmpty(eleRef)) return;
|
|
||||||
|
|
||||||
if (Objects.equals(controlType, ControlTypeEnum.ELEVATOR_OUT_CONTROL.getCode())) {
|
|
||||||
log.info("开始下发外部面板梯控权限....");
|
|
||||||
for (SisElevatorFloorRefVo ref : eleRef) {
|
|
||||||
if (ref.getUpChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)) {
|
|
||||||
hikApiService.controlGateway(ele.getControlIp(), ref.getUpChannel().intValue(), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ref.getDownChannel() != null && Objects.equals(ref.getFloorId(), deviceFloorId)) {
|
|
||||||
hikApiService.controlGateway(ele.getControlIp(), ref.getDownChannel().intValue(), 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 模拟上下文
|
|
||||||
List<RemoteFloorVo> floorList = SaTokenContextMockUtil.setMockContext(() -> remoteFloorService.queryByBuildingId(ele.getBuildingId()));
|
|
||||||
if (CollUtil.isEmpty(floorList)) return;
|
|
||||||
|
|
||||||
if (Objects.equals(controlType, ControlTypeEnum.ELEVATOR_IN_CONTROL.getCode())) {
|
|
||||||
SisElevatorFloorRefVo vo;
|
|
||||||
List<Integer> num = new ArrayList<>();
|
|
||||||
for (int i = 1; i < floorList.size(); i++) {
|
|
||||||
int finalI = i;
|
|
||||||
// 取出权限楼层id与实际楼层id相等的数据
|
|
||||||
vo = eleRef.stream().filter(o -> Objects.equals(o.getFloorId(), floorList.get(finalI - 1).getId())).findFirst().orElse(null);
|
|
||||||
// 存在权限楼层,添加到num中,梯控模块从1开始
|
|
||||||
if (vo != null) {
|
|
||||||
num.add(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CollUtil.isEmpty(num)) return;
|
|
||||||
|
|
||||||
ElevatorControlTcpUtil.getInstance().sendManualCommand(num);
|
|
||||||
}
|
|
||||||
log.info("梯控下发权限完成");
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user