package com.zhgd.xmgl.call; 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.conditions.update.LambdaUpdateWrapper; import com.zhgd.jeecg.common.execption.OpenAlertException; import com.zhgd.jeecg.common.util.pass.HttpUtils; import com.zhgd.redis.lock.RedisRepository; import com.zhgd.xmgl.call.api.PoliceCameraManufacturer; import com.zhgd.xmgl.call.util.Mcs8Util; import com.zhgd.xmgl.modules.policecamera.entity.PoliceCameraItem; import com.zhgd.xmgl.modules.policecamera.entity.PoliceCameraItemFile; import com.zhgd.xmgl.modules.policecamera.entity.ProjectPoliceCameraConfig; import com.zhgd.xmgl.modules.policecamera.entity.WorkTicketHistory; import com.zhgd.xmgl.modules.policecamera.entity.bo.Mcs8FileBo; import com.zhgd.xmgl.modules.policecamera.entity.bo.Mcs8FileSignedUrlBo; import com.zhgd.xmgl.modules.policecamera.entity.vo.WorkTicketVo; import com.zhgd.xmgl.modules.policecamera.service.IPoliceCameraItemFileService; import com.zhgd.xmgl.modules.policecamera.service.IPoliceCameraItemService; import com.zhgd.xmgl.modules.policecamera.service.IWorkTicketHistoryService; import com.zhgd.xmgl.util.PathUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.io.File; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @Slf4j @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class Mcs8Call implements PoliceCameraManufacturer { @Lazy @Autowired private Mcs8Call mcs8Call; private ProjectPoliceCameraConfig config; @Lazy @Autowired private IPoliceCameraItemFileService policeCameraItemFileService; @Lazy @Autowired private IPoliceCameraItemService policeCameraItemService; @Lazy @Autowired private IWorkTicketHistoryService workTicketHistoryService; @Value("${mcs8.download.http.type:pubUrl}") private String downloadType; @Lazy @Autowired private RedisRepository redisRepository; public void setConfig(ProjectPoliceCameraConfig config) { this.config = config; } @Override public void beginWork(WorkTicketVo ticket, String workNo, int no) { if (CollUtil.isEmpty(ticket.getItemList())) { throw new OpenAlertException("请先绑定设备"); } try { Mcs8Util.addTask(config, StrUtil.format("{}-{}-{}", ticket.getConstructionAreaNames(), ticket.getWorkTicketNumber(), "第" + no + "次作业"), workNo, true); String taskId = Mcs8Util.getTaskIdByWorkNo(config, workNo, true); Mcs8Util.updateTaskDest(config, ticket.getItemList(), taskId); // Mcs8Util.updateTaskStatus(config, 1, taskId); } catch (OpenAlertException e) { throw e; } catch (Exception e) { log.error("err", e); throw new OpenAlertException("开启设备录像失败,请检查调度台服务器配置"); } } @Override public void endWork(WorkTicketVo ticket, String workNo) { if (CollUtil.isEmpty(ticket.getItemList())) { throw new OpenAlertException("请先绑定设备"); } try { String taskId = Mcs8Util.getTaskIdByWorkNo(config, workNo, true); Mcs8Util.updateTaskStatus(config, 2, taskId, true); } catch (OpenAlertException e) { throw e; } catch (Exception e) { log.error("err", e); throw new OpenAlertException("关闭设备录像失败,请检查调度台服务器配置"); } } @Override public void pullFile(Date begin, Date end) { Map cameraItemMap = policeCameraItemService.list(null).stream().collect(Collectors.toMap(PoliceCameraItem::getDevSn, Function.identity(), (o1, o2) -> o1)); int page = 1; int pageSize = 1000; List bos = new ArrayList<>(); do { JSONObject jsonObject = Mcs8Util.getRecordFileList(config, page, pageSize, begin, end, true); bos = BeanUtil.copyToList(jsonObject.getJSONArray("data"), Mcs8FileBo.class); for (Mcs8FileBo bo : bos) { if (!Objects.equals(bo.getFType(),3)) { downloadFileAndSave(bo, cameraItemMap); } } page++; } while (CollUtil.isNotEmpty(bos) && bos.size() == pageSize); } public void downloadFileAndSave(Mcs8FileBo bo, Map cameraItemMap) { int count = policeCameraItemFileService.count(new LambdaQueryWrapper() .eq(PoliceCameraItemFile::getExternalId, bo.getId())); if (count > 0) { return; } Mcs8FileSignedUrlBo signedUrl = Mcs8Util.getSignedUrl(config, bo.getId(), true); PoliceCameraItem item = cameraItemMap.get(bo.getDevId()); WorkTicketHistory history = workTicketHistoryService.getById(bo.getWorkNo()); if (item != null) { HashMap headers = new HashMap<>(); headers.put("token", Mcs8Util.getToken(Mcs8Util.getHost(config), config.getPort(), config.getAccount(), config.getPassword())); String pubUrl = getUrl(signedUrl); File downloadFile = HttpUtils.downloadFile(pubUrl, PathUtil.getBasePath(), headers); if (downloadFile != null) { PoliceCameraItemFile file = new PoliceCameraItemFile(); file.setItemId(item.getItemId()); file.setHistoryId(Optional.ofNullable(history).map(WorkTicketHistory::getId).orElse(null)); file.setExternalId(bo.getId()); file.setProjectSn(item.getProjectSn()); file.setFileType(bo.getFType()); file.setUploadTime(bo.getUpLoadTime()); file.setFileName(bo.getFileName()); file.setFileUrl(downloadFile.getName()); file.setFileTime(bo.getFileTime()); file.setFileLen(bo.getFileLen()); file.setDuration(bo.getDuration()); file.setStartTime(bo.getStartTime()); file.setEndTime(bo.getEndTime()); count = policeCameraItemFileService.count(new LambdaQueryWrapper() .eq(PoliceCameraItemFile::getExternalId, bo.getId())); if (count > 0) { return; } policeCameraItemFileService.save(file); } } } private String getUrl(Mcs8FileSignedUrlBo bo) { String pubUrl; if (Objects.equals("pubUrl", downloadType)) { pubUrl = bo.getPubUrl(); } else if (Objects.equals("privateUrl", downloadType)) { pubUrl = bo.getPrivateUrl(); } else if (Objects.equals("httpPubUrl", downloadType)) { pubUrl = bo.getHttpPubUrl(); } else { pubUrl = bo.getHttpPrivateUrl(); } return pubUrl; } @Override public void updateStatus(Long cacheSeconds) { if (configIsBlank()) { return; } List itemList = policeCameraItemService.getListByProjectSn(config.getProjectSn()); Integer page = 1; int pageSize = 1000; JSONArray devList = new JSONArray(); JSONArray tempList = new JSONArray(); // 生成缓存key String cacheKey = null; if (cacheSeconds != null && cacheSeconds > 0) { cacheKey = "mcs8:devList:full:" + Mcs8Util.getHost(config) + ":" + config.getPort() + ":" + config.getAccount() + ":" + config.getPassword(); // 尝试从缓存获取完整设备列表 try { String cachedData = (String) redisRepository.get(cacheKey); if (StringUtils.isNotBlank(cachedData)) { devList = JSONArray.parseArray(cachedData); log.debug("从缓存获取完整设备列表,数量: {}", devList.size()); // 直接使用缓存数据更新设备状态 updateDeviceStatus(itemList, devList); return; } } catch (Exception e) { log.warn("从缓存获取设备列表失败,继续从接口获取", e); } } // 缓存不存在或禁用缓存,从接口获取数据 do { tempList = Mcs8Util.getDevList(config, page, pageSize, true); devList.addAll(tempList); page++; } while (CollUtil.isNotEmpty(tempList) && tempList.size() == pageSize); // 如果启用缓存,将完整设备列表存入缓存 if (cacheSeconds != null && cacheSeconds > 0 && cacheKey != null && CollUtil.isNotEmpty(devList)) { try { redisRepository.setExpire(cacheKey, devList.toJSONString(), cacheSeconds); log.debug("设备列表已缓存,数量: {}, 缓存时间: {}s", devList.size(), cacheSeconds); } catch (Exception e) { log.warn("设备列表缓存失败", e); } } // 更新设备状态 updateDeviceStatus(itemList, devList); } /** * 从接口数据更新设备状态 */ private void updateDeviceStatus(List itemList, JSONArray devList) { Map devSnMap = devList.stream() .collect(Collectors.toMap( o -> ((JSONObject) o).getString("deviceId"), o -> (JSONObject) o, (o1, o2) -> o1 )); // 分组处理:在线设备和离线设备 List onlineIds = new ArrayList<>(); List offlineIds = new ArrayList<>(); for (PoliceCameraItem item : itemList) { JSONObject jsonObject = devSnMap.get(item.getDevSn()); Integer newState = (jsonObject != null && jsonObject.getInteger("status") == 1) ? 1 : 2; Integer oldState = item.getDeviceState(); if (oldState == null || !oldState.equals(newState)) { if (newState == 1) { onlineIds.add(item.getItemId()); } else { offlineIds.add(item.getItemId()); } } } // 批量更新在线设备 if (CollUtil.isNotEmpty(onlineIds)) { policeCameraItemService.update(new LambdaUpdateWrapper() .set(PoliceCameraItem::getDeviceState, 1) .in(PoliceCameraItem::getItemId, onlineIds) ); } // 批量更新离线设备 if (CollUtil.isNotEmpty(offlineIds)) { policeCameraItemService.update(new LambdaUpdateWrapper() .set(PoliceCameraItem::getDeviceState, 2) .in(PoliceCameraItem::getItemId, offlineIds) ); } } public boolean configIsBlank() { return StrUtil.isBlank(config.getIp()) || StrUtil.isBlank(config.getPort()) || StrUtil.isBlank(config.getAccount()) || StrUtil.isBlank(config.getPassword()); } }