package com.ycl.platform.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ycl.platform.domain.entity.WorkOrder; import com.ycl.platform.domain.entity.YwThreshold; import com.ycl.platform.domain.excel.PointExport; import com.ycl.platform.domain.result.HK.FaceDeviceInspectionResult; import com.ycl.platform.domain.result.HK.VehicleDeviceInspectionResult; import com.ycl.platform.domain.vo.DynamicColumnVO; import com.ycl.platform.mapper.YwThresholdMapper; import com.ycl.platform.service.IYwThresholdService; import com.ycl.platform.service.WorkOrderService; import com.ycl.system.Result; import com.ycl.utils.ip.PingUtil; import com.ycl.utils.poi.EasyExcelImportUtils; import com.ycl.utils.uuid.IdUtils; import constant.PointHeaderConstant; import constant.YwThreadConstants; import enumeration.CompareType; import enumeration.ErrorType; import enumeration.general.BusinessTypeEnum; import enumeration.general.WorkOrderStatusEnum; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.web.multipart.MultipartFile; import utils.DateUtils; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** * 运维阈值Service业务层处理 * * @author gonghl * @date 2024-07-19 */ @Service @Slf4j public class YwThresholdServiceImpl extends ServiceImpl implements IYwThresholdService { @Autowired private YwThresholdMapper ywThresholdMapper; @Autowired private WorkOrderService workOrderService; /** * 查询运维阈值 * * @param id 运维阈值主键 * @return 运维阈值 */ @Override public YwThreshold selectYwThresholdById(Long id) { return ywThresholdMapper.selectYwThresholdById(id); } /** * 查询运维阈值列表 * * @param ywThreshold 运维阈值 * @return 运维阈值 */ @Override public Map> selectYwThresholdList(YwThreshold ywThreshold) { List ywThresholds = ywThresholdMapper.selectYwThresholdList(ywThreshold); Map> map = ywThresholds.stream().collect(Collectors.groupingBy(YwThreshold::getMonitorType)); return map; } /** * 新增运维阈值 * * @param ywThreshold 运维阈值 * @return 结果 */ @Override public int insertYwThreshold(YwThreshold ywThreshold) { ywThreshold.setCreateTime(DateUtils.getNowDate()); return ywThresholdMapper.insertYwThreshold(ywThreshold); } /** * 修改运维阈值 * * @param list 运维阈值 * @return 结果 */ @Override public Boolean updateYwThreshold(List list) { list.forEach(item -> item.setCreateTime(new Date())); return updateBatchById(list); } /** * 批量删除运维阈值 * * @param ids 需要删除的运维阈值主键 * @return 结果 */ @Override public int deleteYwThresholdByIds(Long[] ids) { return ywThresholdMapper.deleteYwThresholdByIds(ids); } /** * 删除运维阈值信息 * * @param id 运维阈值主键 * @return 结果 */ @Override public int deleteYwThresholdById(Long id) { return ywThresholdMapper.deleteYwThresholdById(id); } /** * 判断视频阈值是否满足下发条件 * * @param list */ @Override public void videoCheck(List list) { } @Override public void errorTypeCheckUY(List list) { // 平台离线故障检测 if (CollectionUtils.isEmpty(list)) { Boolean ping = PingUtil.ping("", 5); if (! ping) { } } // 设备离线故障检测 // 信号缺失故障检测 // 画面偏色故障检测 // 雪花干扰故障检测 // 条纹干扰故障检测 // 画面遮挡故障检测 // 清晰度异常检测 // 亮度异常故障检测 } @Override public Result importData(MultipartFile file) { List> list = EasyExcelImportUtils.makeData(file); List dataList = new ArrayList<>(); for (Map map : list) { PointExport pointExport = new PointExport(); pointExport.setPointName(map.get(PointHeaderConstant.Point_Name)); pointExport.setSerialNumber(map.get(PointHeaderConstant.Serial_Number)); dataList.add(pointExport); } workOrderService.batchImportWhite(dataList); return Result.ok("导入成功"); } /** * 判断人脸阈值是否满足下发条件 * * @param list */ @Override public void faceCheck(List list) { Map thresholdMap = getYwThresholdMap(BusinessTypeEnum.FACE.name()); //准备下发工单集合 List distributeList = new ArrayList<>(); //准备自动生成工单集合 List workOrderList = new ArrayList<>(); //处理接口数据 for (FaceDeviceInspectionResult result : list) { if (result == null) { log.error("人脸对象数据为空"); continue; } WorkOrder workOrder = new WorkOrder(); //检查时钟准确率 Float clockPercent = result.getSnapClock().getClockPercent(); check(YwThreadConstants.Face_ClockPercent, clockPercent, result.getExternalIndexCode(), thresholdMap, workOrder, CompareType.LESS_THAN_EQ, ErrorType.CLOCK_RIGHT.getValue()); //检查数据及时率 Float timelyPercent = result.getSnapTimely().getTimelyPercent(); check(YwThreadConstants.Face_TimelyPercent, timelyPercent, result.getExternalIndexCode(), thresholdMap, workOrder, CompareType.LESS_THAN_EQ, ErrorType.DATA_TIMELY_ERROR.getValue()); //检查持续无数据天数 Integer continueNoDataCount = result.getContinueNoDataCount(); check(YwThreadConstants.Face_ContinueNoDataCount, continueNoDataCount, result.getExternalIndexCode(), thresholdMap, workOrder, CompareType.MORE_THAN_EQ, ErrorType.LONG_DAY_NO_DATA.getValue()); //检查不唯一数据量 Integer nouniqueCount = result.getSnapUnique().getNouniqueCount(); check(YwThreadConstants.Face_NouniqueCount, nouniqueCount, result.getExternalIndexCode(), thresholdMap, workOrder, CompareType.MORE_THAN_EQ, ErrorType.NOT_UNIQUE_DATA_VOLUME.getValue()); //检查人脸低评分率 Float lowScorePercent = result.getSnapValidity().getLowScorePercent(); check(YwThreadConstants.Face_LowScorePercent, lowScorePercent, result.getExternalIndexCode(), thresholdMap, workOrder, CompareType.MORE_THAN_EQ, ErrorType.FACE_LOW.getValue()); //检查建模失败率 Float failPercent = result.getSnapValidity().getFailPercent(); check(YwThreadConstants.Face_FailPercent, failPercent, result.getExternalIndexCode(), thresholdMap, workOrder, CompareType.MORE_THAN_EQ, ErrorType.MODELING_FAIL.getValue()); // 点位在线率 if (2 == result.getSnapResult()) { workOrder.setSerialNumber(result.getExternalIndexCode()); workOrder.setStatus(WorkOrderStatusEnum.DISTRIBUTED); if (CollectionUtils.isEmpty(workOrder.getErrorTypeList())) { workOrder.setErrorTypeList(new ArrayList<>()); workOrder.getErrorTypeList().add(ErrorType.DEVICE_OFFLINE.getValue()); } else { workOrder.getErrorTypeList().add(ErrorType.DEVICE_OFFLINE.getValue()); } } if (WorkOrderStatusEnum.WAIT_DISTRIBUTE.equals(workOrder.getStatus())) { workOrderList.add(workOrder); } else if (WorkOrderStatusEnum.DISTRIBUTED.equals(workOrder.getStatus())) { distributeList.add(workOrder); } } /** 添加工单 */ workOrderService.innerAddWorkOrder(workOrderList); workOrderService.innerAddWorkOrder(distributeList); } /** * 判断车辆阈值是否满足下发条件 * * @param list */ @Override public void carCheck(List list) { Map thresholdMap = getYwThresholdMap(BusinessTypeEnum.CAR.name()); //准备下发工单集合 List distributeList = new ArrayList<>(); //准备自动生成工单集合 List workOrderList = new ArrayList<>(); //处理接口数据 for (VehicleDeviceInspectionResult result : list) { if (result == null) { log.error("车辆对象数据为空"); continue; } WorkOrder workOrder = new WorkOrder(); //检查持续无数据天数 Integer continueNoDataCount = result.getContinueNoDataCount(); check(YwThreadConstants.Car_ContinueNoDataCount, continueNoDataCount, result.getExternalIndexCode(), thresholdMap, workOrder, CompareType.MORE_THAN_EQ, ErrorType.LONG_DAY_NO_DATA.getValue()); //检查时钟准确率 Float clockPercent = result.getSnapClock().getClockPercent(); check(YwThreadConstants.Car_ClockPercent, clockPercent, result.getExternalIndexCode(), thresholdMap, workOrder, CompareType.LESS_THAN_EQ, ErrorType.CLOCK_RIGHT.getValue()); //检查数据及时率 Float timelyPercentResult = result.getSnapTimely().getTimelyPercent(); check(YwThreadConstants.Car_TimelyPercent, timelyPercentResult, result.getExternalIndexCode(), thresholdMap, workOrder, CompareType.LESS_THAN_EQ, ErrorType.DATA_TIMELY_ERROR.getValue()); //检查不唯一数据量 Integer nouniqueCountResult = result.getSnapUnique().getNouniqueCount(); check(YwThreadConstants.Car_NouniqueCount, nouniqueCountResult, result.getExternalIndexCode(), thresholdMap, workOrder, CompareType.MORE_THAN_EQ, ErrorType.NOT_UNIQUE_DATA_VOLUME.getValue()); //检查白天未识别量 Integer dayNoNumberCountResult = result.getSnapPlate().getDayNoNumberCount(); check(YwThreadConstants.Car_DayNoNumberCount, dayNoNumberCountResult, result.getExternalIndexCode(), thresholdMap, workOrder, CompareType.MORE_THAN_EQ, ErrorType.UNRECOGNIZED_DAY_VOLUME.getValue()); //车辆主要属性不完整率 Integer noIntegrityCountResult = result.getIntegrity().getMainNoIntegrityCount(); check(YwThreadConstants.Car_NoIntegrityCount, noIntegrityCountResult, result.getExternalIndexCode(), thresholdMap, workOrder, CompareType.MORE_THAN_EQ, ErrorType.CAR_SIX.getValue()); // 点位在线率 if (2 == result.getSnapResult()) { workOrder.setSerialNumber(result.getExternalIndexCode()); workOrder.setStatus(WorkOrderStatusEnum.DISTRIBUTED); if (CollectionUtils.isEmpty(workOrder.getErrorTypeList())) { workOrder.setErrorTypeList(new ArrayList<>()); workOrder.getErrorTypeList().add(ErrorType.DEVICE_OFFLINE.getValue()); } else { workOrder.getErrorTypeList().add(ErrorType.DEVICE_OFFLINE.getValue()); } } if (WorkOrderStatusEnum.WAIT_DISTRIBUTE.equals(workOrder.getStatus())) { workOrderList.add(workOrder); } else if (WorkOrderStatusEnum.DISTRIBUTED.equals(workOrder.getStatus())) { distributeList.add(workOrder); } } /** 添加工单 */ workOrderService.innerAddWorkOrder(workOrderList); workOrderService.innerAddWorkOrder(distributeList); } /** * 把阈值条件查出来,转成map * * @param name * @return */ private Map getYwThresholdMap(String name) { return ywThresholdMapper.selectList( new QueryWrapper().eq("monitor_type", name) ).stream().collect(Collectors.toMap( YwThreshold::getKey, Function.identity() )); } /** * 检查阈值 * * @param key 某阈值标识 * @param value 接口获取到的值 * @param serialNumber 国标码 * @param thresholds 阈值条件map * @param compareType 比较方式:>= <= * @param errorType 故障类型 * @param */ private > void check(String key, T value, String serialNumber, Map thresholds, WorkOrder workOrder, CompareType compareType,String errorType) { Optional.ofNullable(value).ifPresentOrElse( v -> { YwThreshold ywThreshold = thresholds.get(key); //转换类型 T thresholdValue = parseThreshold(ywThreshold.getValueAuto(), value.getClass()); T thresholdAutoValue = parseThreshold(ywThreshold.getValue(), value.getClass()); //比较大小,加入到对应待处理集合 if (compareType.compare(v, thresholdAutoValue)) { //自动下发工单 workOrder.setSerialNumber(serialNumber); workOrder.setStatus(WorkOrderStatusEnum.WAIT_DISTRIBUTE); if (CollectionUtils.isEmpty(workOrder.getErrorTypeList())) { workOrder.setErrorTypeList(new ArrayList<>()); workOrder.getErrorTypeList().add(errorType); } else { workOrder.getErrorTypeList().add(errorType); } } else if (compareType.compare(v, thresholdValue)) { //进入工单代下发 workOrder.setSerialNumber(serialNumber); workOrder.setStatus(WorkOrderStatusEnum.DISTRIBUTED); if (CollectionUtils.isEmpty(workOrder.getErrorTypeList())) { workOrder.setErrorTypeList(new ArrayList<>()); workOrder.getErrorTypeList().add(errorType); } else { workOrder.getErrorTypeList().add(errorType); } } }, () -> log.error("{} 为空: {}", thresholds.get(key).getName(), serialNumber) ); } private > T parseThreshold(String thresholdStr, Class type) { if (Integer.class.equals(type)) { return (T) Integer.valueOf(thresholdStr); } else if (Float.class.equals(type)) { return (T) Float.valueOf(thresholdStr); } else if (Double.class.equals(type)) { return (T) Double.valueOf(thresholdStr); } else if (Long.class.equals(type)) { return (T) Long.valueOf(thresholdStr); } else { throw new IllegalArgumentException("不支持转换类型" + type); } } }