package com.ard.device.camera.service.impl; import com.ard.common.annotation.DataScope; import com.ard.common.constant.CacheConstants; import com.ard.common.constant.DeviceConstants; import com.ard.common.core.domain.entity.SysUser; import com.ard.common.core.redis.RedisCache; import com.ard.common.exception.ServiceException; import com.ard.common.utils.DateUtils; import com.ard.common.utils.SecurityUtils; import com.ard.common.utils.StringUtils; import com.ard.common.utils.bean.BeanValidators; import com.ard.common.utils.spring.SpringUtils; import com.ard.common.utils.uuid.IdUtils; import com.ard.device.camera.domain.ArdCamera; import com.ard.device.camera.domain.CameraCmd; import com.ard.device.camera.mapper.ArdCameraMapper; import com.ard.device.camera.service.IArdCameraService; import com.ard.device.channel.domain.ArdChannel; import com.ard.device.channel.service.IArdChannelService; import com.ard.device.component.sdk.common.GlobalVariable; import com.ard.device.component.sdk.event.LoginEvent; import com.ard.device.component.sdk.service.CameraSDKService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.validation.Validator; import java.util.*; import java.util.stream.Collectors; /** * 相机设备Service业务层处理 * * @author 刘苏义 * @date 2023-02-11 */ @Service @Slf4j public class ArdCameraServiceImpl implements IArdCameraService, ApplicationRunner { @Resource private ArdCameraMapper ardCameraMapper; @Resource private CameraSDKService cameraSDKService; @Resource private RedisCache redisService; @Resource private IArdChannelService ardChannelService; @Resource protected Validator validator; @Override public void run(ApplicationArguments args) { initCamera(); } public void initCamera() { //清空相机缓存 redisService.deleteObject(redisService.keys(getCacheKey("*"))); //重新加载相机到缓存 ardCameraMapper.selectArdCameraList(new ArdCamera()).forEach(ardCamera -> { ardCameraMapper.resetCameraLoginId(ardCamera); redisService.setCacheObject(getCacheKey(ardCamera.getId()), ardCamera); cameraSDKService.login(ardCamera); }); } /** * 设置cache key * * @param configKey 参数键 * @return 缓存键key */ private String getCacheKey(String configKey) { return CacheConstants.CAMERA_LIST_KEY + configKey; } /** * 查询相机设备 * * @param id 相机设备主键 * @return 相机设备 */ @Override public ArdCamera selectArdCameraById(String id) { return ardCameraMapper.selectArdCameraById(id); } /** * 查询相机设备 * * @param name 相机设备名称 * @return 相机设备 */ @Override public ArdCamera selectArdCameraByName(String name) { return ardCameraMapper.selectArdCameraByName(name); } /** * 查询相机设备列表 * * @param ardCamera 相机设备 * @return 相机设备 */ @Override @DataScope(deptAlias = "d", userAlias = "u") public List selectArdCameraList(ArdCamera ardCamera) { return ardCameraMapper.selectArdCameraList(ardCamera); } /** * 查询所有相机 * * @param ardCamera 相机设备 * @return 相机设备 */ @Override public List selectArdCameraListAll(ArdCamera ardCamera) { return ardCameraMapper.selectArdCameraList(ardCamera); } /** * 新增相机设备 * * @param ardCamera 相机设备 * @return 结果 */ @Override public int insertArdCamera(ArdCamera ardCamera) { ardCamera.setId(IdUtils.simpleUUID()); ardCamera.setCreateBy(SecurityUtils.getUsername()); ardCamera.setCreateTime(DateUtils.getNowDate()); ardCamera.setUserId(SecurityUtils.getUserId()); int res = ardCameraMapper.insertArdCamera(ardCamera); if (res > 0) { cameraSDKService.login(ardCamera);//sdk登录获取通道信息 } return res; } /** * 修改相机设备 * * @param ardCamera 相机设备 * @return 结果 */ @Override public int updateArdCamera(ArdCamera ardCamera) { ardCamera.setUpdateTime(DateUtils.getNowDate()); ardCamera.setUpdateBy(SecurityUtils.getUsername()); int res = ardCameraMapper.updateArdCamera(ardCamera); if (res > 0) { cameraSDKService.logout(ardCamera);//sdk注销 cameraSDKService.login(ardCamera);//sdk登录获取通道信息 } return res; } /** * 批量删除相机设备 * * @param ids 需要删除的相机设备主键 * @return 结果 */ @Override public int deleteArdCameraByIds(String[] ids) { for (String id : ids) { ArdCamera camera = ardCameraMapper.selectArdCameraById(id); if (camera != null) { //redis中删除 redisService.deleteObject(getCacheKey(id)); //删除当前相机的所有通道 ardChannelService.deleteArdChannelByDeviceId(id); //sdk注销 cameraSDKService.logout(camera); } } return ardCameraMapper.deleteArdCameraByIds(ids); } /** * 删除相机设备信息 * * @param id 相机设备主键 * @return 结果 */ @Override public int deleteArdCameraById(String id) { int i = ardCameraMapper.deleteArdCameraById(id); if (i > 0) { //redis中删除 redisService.deleteObject(getCacheKey(id)); //删除当前相机的所有通道 ardChannelService.deleteArdChannelByDeviceId(id); //sdk注销 cameraSDKService.logout(ArdCamera.builder().id(id).build()); } return i; } @Override public String importCamera(List ardCameraList, Boolean isUpdateSupport, String operatorName) { if (StringUtils.isNull(ardCameraList) || ardCameraList.isEmpty()) { throw new ServiceException("导入相机数据不能为空!"); } int successNum = 0; int failureNum = 0; StringBuilder successMsg = new StringBuilder(); StringBuilder failureMsg = new StringBuilder(); for (ArdCamera camera : ardCameraList) { try { //获取当前登录用户id Long userId = SecurityUtils.getUserId(); camera.setUserId(userId); // 验证是否存在这个用户 ArdCamera u = ardCameraMapper.selectArdCameraById(camera.getId()); if (StringUtils.isNull(u)) { BeanValidators.validateWithException(validator, camera); camera.setCreateBy(operatorName); this.insertArdCamera(camera); successNum++; successMsg.append("
" + successNum + "、相机ID " + camera.getId() + " 导入成功"); } else if (isUpdateSupport) { BeanValidators.validateWithException(validator, camera); checkCameraDataScope(camera.getUserId()); camera.setUpdateBy(operatorName); this.updateArdCamera(camera); successNum++; successMsg.append("
" + successNum + "、相机ID " + camera.getId() + " 更新成功"); } else { failureNum++; failureMsg.append("
" + failureNum + "、相机ID " + camera.getId() + " 已存在"); } } catch (Exception e) { failureNum++; String msg = "
" + failureNum + "、相机ID " + camera.getId() + " 导入失败:"; failureMsg.append(msg + e.getMessage()); log.error(msg, e); } } if (failureNum > 0) { failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); throw new ServiceException(failureMsg.toString()); } else { successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); } return successMsg.toString(); } /** * 校验用户是否有数据权限 * * @param userId 用户id */ @Override public void checkCameraDataScope(Long userId) { if (!SysUser.isAdmin(SecurityUtils.getUserId())) { ArdCamera camera = new ArdCamera(); camera.setUserId(userId); List cameras = SpringUtils.getAopProxy(this).selectArdCameraList(camera); if (StringUtils.isEmpty(cameras)) { throw new ServiceException("没有权限访问井数据!"); } } } /** * 校验相机是否唯一 * * @param camera 相机 * @return 结果 */ @Override public String checkCameraIpAndPortUnique(ArdCamera camera) { String id = camera.getId(); String ip = camera.getIp(); Integer port = camera.getPort(); ArdCamera info = ardCameraMapper.checkCameraIpAndPortUnique(ip, port); if (StringUtils.isNotNull(info) && !info.getId().equals(id)) { return DeviceConstants.NOT_UNIQUE; } return DeviceConstants.UNIQUE; } /** * 校验机场是否已关联相机 * * @param camera 相机 * @return 结果 */ @Override public ArdCamera checkAirportHasCamera(ArdCamera camera) { ArdCamera info = ardCameraMapper.checkAirportHasCamera(camera); if (StringUtils.isNotNull(info)&& !info.getId().equals(camera.getId())) { return info; } return null; } /** * 同步通道 * * @param oldArrayList 旧通道列表(库中) * @param newArrayList 新通道列表(sdk) * @author 刘苏义 * @date 2024/8/23 16:28 */ @Override public void asyncChannel(List oldArrayList, List newArrayList) { // 将列表转换为映射以提高性能 Map oldMap = oldArrayList.stream() .collect(Collectors.toMap(ArdChannel::getChanNo, channel -> channel)); Map newMap = newArrayList.stream() .collect(Collectors.toMap(ArdChannel::getChanNo, channel -> channel)); // 需要更新的数据 newArrayList.stream() .filter(channel -> { ArdChannel oldChannel = oldMap.get(channel.getChanNo()); return oldChannel != null && (!Objects.equals(channel.getName(), oldChannel.getName()) || !Objects.equals(channel.getVideoCode(), oldChannel.getVideoCode())); }) .forEach(channel -> { ArdChannel oldChannel = oldMap.get(channel.getChanNo()); channel.setId(oldChannel.getId()); ardChannelService.updateArdChannel(channel); }); // 需要删除的数据 oldArrayList.stream() .filter(channel -> !newMap.containsKey(channel.getChanNo())) .forEach(channel -> { ardChannelService.deleteArdChannelById(channel.getId()); }); // 需要新增的数据 newArrayList.stream() .filter(channel -> !oldMap.containsKey(channel.getChanNo())) .forEach(channel -> { if (ardChannelService.checkArdChannelUnique(channel)) { ardChannelService.insertArdChannel(channel); } }); } /** * 监听登录事件 * * @param loginEvent 登录事件 * @author 刘苏义 * @date 2024/8/23 15:42 */ @Async @EventListener(LoginEvent.class) public void LoginEventListener(LoginEvent loginEvent) { ArdCamera camera = loginEvent.getCamera(); ardCameraMapper.updateArdCamera(camera); // SDK 登录成功后写入 Redis redisService.setCacheObject(getCacheKey(camera.getId()), camera); } }