package com.iailab.module.job.task;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONArray;
|
import com.iailab.framework.common.util.object.ConvertUtils;
|
import com.iailab.common.utils.DateUtils;
|
import com.iailab.module.device.commons.HealthIndexTypeEnum;
|
import com.iailab.module.device.commons.HealthLevelEnum;
|
import com.iailab.module.device.entity.DeviceStatCountEntity;
|
import com.iailab.module.device.entity.DeviceStatNewnessEntity;
|
import com.iailab.module.device.dto.*;
|
import com.iailab.module.device.service.*;
|
import com.iailab.module.model.handler.ModelHandler;
|
import com.iailab.module.model.sample.constructor.SampleDataConstructor;
|
import com.iailab.module.model.sample.constructor.SampleInfoConstructor;
|
import com.iailab.module.model.sample.dto.ColumnItem;
|
import com.iailab.module.model.sample.entity.DataEntity;
|
import com.xxl.job.core.handler.annotation.XxlJob;
|
import org.apache.commons.lang3.StringUtils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import javax.annotation.Resource;
|
import org.springframework.stereotype.Component;
|
import org.springframework.util.CollectionUtils;
|
|
import java.math.BigDecimal;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
/**
|
* 设备健康评价
|
* 10 0 0/1 * * ?
|
*
|
* @author PanZhibao
|
* @Description
|
* @createTime 2024年06月29日
|
*/
|
@Component("deviceHealthTask")
|
public class DeviceHealthTask implements ITask {
|
private Logger logger = LoggerFactory.getLogger(getClass());
|
|
|
private BigDecimal DEFAULT_HEALTH_SCORE = new BigDecimal(100);
|
|
private String DEFAULT_REPORT_CONTENT = "设备运行正常";
|
|
private int DEFAULT_DATA_LENGTH = 60;
|
|
@Resource
|
private DeviceHealthEvaluateService deviceHealthEvaluateService;
|
|
@Resource
|
private DeviceEvaluateIndexService deviceEvaluateIndexService;
|
|
@Resource
|
private SampleInfoConstructor sampleInfoConstructor;
|
|
@Resource
|
private SampleDataConstructor sampleDataConstructor;
|
|
@Resource
|
private ModelHandler modelHandler;
|
|
@Resource
|
private DeviceHealthReportService deviceHealthReportService;
|
|
@Resource
|
private DeviceStatCountService deviceStatCountService;
|
|
@Resource
|
private DeviceInfoService deviceInfoService;
|
|
@Resource
|
private DeviceFaultService deviceFaultService;
|
|
@Resource
|
private DeviceStatNewnessService deviceStatNewnessService;
|
|
private final int GRANULARITY = 60;
|
|
private Map<Integer, String> HEALTH_FAULT_TYPE = new HashMap<>();
|
private Map<String, String> ALARM_INDEX_TYPE = new HashMap<>();
|
|
private String[] indexArr = new String[]{HealthIndexTypeEnum.elec.getCode(), HealthIndexTypeEnum.temperature.getCode(),
|
HealthIndexTypeEnum.flutter.getCode(), HealthIndexTypeEnum.runTime.getCode()};
|
|
|
|
DeviceHealthTask() {
|
HEALTH_FAULT_TYPE.put(1, "波动正常,趋势正常");
|
HEALTH_FAULT_TYPE.put(2, "波动正常,趋势异常");
|
HEALTH_FAULT_TYPE.put(3, "波动异常,趋势正常");
|
HEALTH_FAULT_TYPE.put(4, "波动异常,趋势异常");
|
|
ALARM_INDEX_TYPE.put("temperature", "温度");
|
ALARM_INDEX_TYPE.put("flutter", "震动");
|
ALARM_INDEX_TYPE.put("elec", "电流");
|
}
|
|
@Override
|
@XxlJob("deviceHealthTask")
|
public void run(String params) {
|
Calendar calendar = Calendar.getInstance();
|
calendar.set(Calendar.MILLISECOND, 0);
|
calendar.set(Calendar.SECOND, 0);
|
try {
|
List<DeviceStatNewnessEntity> newnessList = new ArrayList<>();
|
Map<String, Object> queryParams = new HashMap<>();
|
queryParams.put("isEnable", 1);
|
List<DeviceHealthEvaluateDTO> evaList = deviceHealthEvaluateService.list(queryParams);
|
if (CollectionUtils.isEmpty(evaList)) {
|
return;
|
}
|
// 开始健康评价
|
evaList.forEach(item -> {
|
this.runModel(item, calendar.getTime(), newnessList);
|
});
|
|
// 统计数量
|
deviceStatCount(calendar);
|
|
// 更新设备新度系数
|
deviceStatNewnessService.statNewness(newnessList, calendar.getTime());
|
|
} catch (Exception ex) {
|
logger.error("DeviceHealthTask运行异常");
|
ex.printStackTrace();
|
}
|
logger.info("DeviceHealthTask运行完成");
|
}
|
|
public void runModel(DeviceHealthEvaluateDTO dto, Date runTime, List<DeviceStatNewnessEntity> newnessList) {
|
try {
|
List<DeviceEvaluateIndexDTO> indexList = deviceEvaluateIndexService.listByEvaluateId(dto.getId());
|
if (CollectionUtils.isEmpty(indexList)) {
|
DeviceHealthEvaluateDTO updateDto = new DeviceHealthEvaluateDTO();
|
updateDto.setId(dto.getId());
|
updateDto.setReportContent(DEFAULT_REPORT_CONTENT);
|
updateDto.setReportDate(runTime);
|
updateDto.setReportId("");
|
updateDto.setAbnormalCount(0);
|
updateDto.setHealthScore(DEFAULT_HEALTH_SCORE);
|
updateDto.setHealthLevel(HealthLevelEnum.Level1.getCode());
|
deviceHealthEvaluateService.updateReport(updateDto);
|
return;
|
}
|
Map<String, DeviceEvaluateIndexDTO> indexMap = new HashMap<>();
|
indexList.forEach(item -> {
|
indexMap.put(item.getIndexType(), item);
|
});
|
|
DEFAULT_DATA_LENGTH = indexList.get(0).getDataLength();
|
|
ColumnItem columnItem = new ColumnItem();
|
columnItem.setEndTime(runTime);
|
columnItem.setStartTime(sampleInfoConstructor.calculateTime(runTime, true, DEFAULT_DATA_LENGTH - 1, GRANULARITY));
|
List<double[][]> sampleDataList = new ArrayList<>();
|
Map<String, List<DataEntity>> dataMap = new LinkedHashMap<>();
|
|
double[][] matrix1 = new double[DEFAULT_DATA_LENGTH][indexArr.length];
|
double[][] matrix2 = new double[1][3];
|
for (int i = 0; i < indexArr.length; i++) {
|
if (indexMap.get(indexArr[i]) == null) {
|
for (int k = 0; k < DEFAULT_DATA_LENGTH; k++) {
|
matrix1[k][i] = -2;
|
}
|
continue;
|
}
|
DeviceEvaluateIndexDTO indDTO = indexMap.get(indexArr[i]);
|
columnItem.setParamId(indDTO.getParamId());
|
columnItem.setParamType(indDTO.getParamType());
|
List<DataEntity> dataEntityList = sampleDataConstructor.getColumnData(columnItem);
|
logger.info("BEF:ParamType=" + indDTO.getParamType() + ";ParamId=" + indDTO.getParamId() + ";size=" + dataEntityList.size());
|
//补全数据
|
dataEntityList = sampleDataConstructor.completionData(matrix1.length, dataEntityList, columnItem.startTime, columnItem.endTime, GRANULARITY);
|
logger.info("AFT:ParamType=" + indDTO.getParamType() + ";ParamId=" + indDTO.getParamId() + ";size=" + dataEntityList.size());
|
if (CollectionUtils.isEmpty(dataEntityList)) {
|
continue;
|
}
|
for (int k = 0; k < DEFAULT_DATA_LENGTH; k++) {
|
matrix1[k][i] = dataEntityList.get(k).getDataValue();
|
}
|
dataMap.put(indexArr[i], dataEntityList);
|
|
if (i < 3) {
|
matrix2[0][i] = indDTO.getNominalValue().doubleValue();
|
}
|
}
|
sampleDataList.add(matrix1);
|
sampleDataList.add(matrix2);
|
|
// 调用模型
|
logger.info("调用模型,DevNo=" + dto.getDevNo());
|
Map<String, Object> modelCommonResult = modelHandler.run(dto.getModelCode(), sampleDataList);
|
|
// 生成评价报告
|
this.saveReport(dto, runTime, modelCommonResult, dataMap, indexMap);
|
|
// 更新新度系数
|
if (modelCommonResult.get("run_time_adjust") != null) {
|
DeviceStatNewnessEntity deviceStatNewness = new DeviceStatNewnessEntity();
|
deviceStatNewness.setDevNo(dto.getDevNo());
|
deviceStatNewness.setDevName(dto.getDevName());
|
deviceStatNewness.setRunTime(new BigDecimal(modelCommonResult.get("run_time_normal").toString()).intValue());
|
deviceStatNewness.setLossTime(new BigDecimal(modelCommonResult.get("run_time_adjust").toString()).intValue());
|
deviceStatNewness.setLossRate(new BigDecimal(deviceStatNewness.getLossTime()).divide(new BigDecimal(deviceStatNewness.getRunTime()),2,BigDecimal.ROUND_HALF_UP));
|
newnessList.add(deviceStatNewness);
|
}
|
} catch (Exception ex) {
|
ex.printStackTrace();
|
logger.error("设备健康评价计算异常,devNo=" + dto.getDevNo());
|
}
|
}
|
|
public void saveReport(DeviceHealthEvaluateDTO evaluateDTO, Date runTime, Map<String, Object> modelCommonResult,
|
Map<String, List<DataEntity>> dataMap, Map<String, DeviceEvaluateIndexDTO> indexMap) {
|
|
DeviceInfoDTO deviceInfo = deviceInfoService.getByDevNo(evaluateDTO.getDevNo());
|
|
DeviceHealthReportDTO reportDTO = new DeviceHealthReportDTO();
|
reportDTO.setId(UUID.randomUUID().toString());
|
reportDTO.setReportNo("H" + DateUtils.format(runTime, "yyyyMMddHHmmss") + getRand(evaluateDTO.getDevNo()));
|
reportDTO.setReportName(evaluateDTO.getDevName() + "健康评价报告");
|
reportDTO.setReportDate(runTime);
|
String deviceHealthLevel = modelCommonResult.get("isqualified").toString();
|
reportDTO.setHealthLevel(deviceHealthLevel);
|
reportDTO.setAbnormalCount(getAbnormalCount(JSONArray.toJSONString(modelCommonResult.get("part_grade"))));
|
reportDTO.setContent(modelCommonResult.get("health_evaluate").toString());
|
reportDTO.setHealthScore(new BigDecimal(modelCommonResult.get("health_score").toString()));
|
reportDTO.setDataLength(DEFAULT_DATA_LENGTH);
|
reportDTO.setRunTime(new BigDecimal(modelCommonResult.get("run_time_adjust").toString()).intValue());
|
reportDTO.setDevNo(evaluateDTO.getDevNo());
|
reportDTO.setDevName(evaluateDTO.getDevName());
|
if (deviceInfo != null) {
|
reportDTO.setClassNo(deviceInfo.getClassNo());
|
reportDTO.setClassName(deviceInfo.getClassName());
|
reportDTO.setWorkshop(deviceInfo.getWorkshop());
|
reportDTO.setModel(deviceInfo.getModel());
|
}
|
List<Integer> partGrade = getIntValueArr(modelCommonResult.get("part_grade"));
|
List<BigDecimal> maxArr = getValueArr(modelCommonResult.get("max_arr"));
|
List<BigDecimal> minArr = getValueArr(modelCommonResult.get("min_arr"));
|
List<BigDecimal> meanArr = getValueArr(modelCommonResult.get("mean_arr"));
|
List<DeviceHealthReportDataDTO> detList = new ArrayList<>();
|
List<DeviceHealthAlarmDetailDTO> deviceHealthAlarmDetailDTOList = new ArrayList<>();
|
List<String> alarmIndexTypes = new ArrayList<>();
|
List<String> alarmSolutions = new ArrayList<>();
|
// 故障id
|
String alarmId = UUID.randomUUID().toString();
|
for (int i = 0; i < indexArr.length; i++) {
|
List<DataEntity> dataList = dataMap.get(indexArr[i]);
|
if (CollectionUtils.isEmpty(dataList)) {
|
continue;
|
}
|
List<Object[]> dataCont = dataList.stream().map(t -> {
|
return new Object[]{DateUtils.format(t.getTimeStamp(), DateUtils.DATE_TIME_PATTERN_MIN), new BigDecimal(t.getDataValue()).setScale(4, BigDecimal.ROUND_HALF_UP)};
|
}).collect(Collectors.toList());
|
DeviceHealthReportDataDTO det = new DeviceHealthReportDataDTO();
|
det.setSort(i);
|
det.setDataName(indexMap.get(indexArr[i]).getParamName());
|
det.setDataValue(JSONArray.toJSONString(dataCont));
|
if (!HealthIndexTypeEnum.runTime.getCode().equals(indexArr[i])) {
|
det.setDataMax(maxArr.get(i));
|
det.setDataMin(minArr.get(i));
|
det.setDataAvg(meanArr.get(i));
|
det.setGradeCode(partGrade.get(i).toString());
|
det.setGradeName(HEALTH_FAULT_TYPE.get(partGrade.get(i)));
|
|
DeviceFaultDTO querySoluDto = new DeviceFaultDTO();
|
querySoluDto.setClassNo(deviceInfo.getClassNo());
|
querySoluDto.setIndexType(indexArr[i]);
|
querySoluDto.setFaultType(det.getGradeCode());
|
DeviceFaultDTO faultDTO = deviceFaultService.getSolution(querySoluDto);
|
if (faultDTO != null) {
|
det.setSolution(faultDTO.getSolution());
|
det.setFaultCode(faultDTO.getFaultCode());
|
}
|
|
// 设备健康故障详情记录
|
if (HealthLevelEnum.Level3.getCode().equals(deviceHealthLevel) && faultDTO != null){
|
DeviceHealthAlarmDetailDTO deviceHealthAlarmDetail = new DeviceHealthAlarmDetailDTO();
|
deviceHealthAlarmDetail.setId(UUID.randomUUID().toString());
|
deviceHealthAlarmDetail.setAlarmId(alarmId);
|
deviceHealthAlarmDetail.setFaultCode(faultDTO.getFaultCode());
|
deviceHealthAlarmDetail.setFaultName(HEALTH_FAULT_TYPE.get(partGrade.get(i)));
|
deviceHealthAlarmDetail.setSolution(faultDTO.getSolution());
|
|
alarmIndexTypes.add(ALARM_INDEX_TYPE.get(faultDTO.getIndexType()));
|
alarmSolutions.add(faultDTO.getSolution());
|
deviceHealthAlarmDetailDTOList.add(deviceHealthAlarmDetail);
|
}
|
} else {
|
StringBuilder rsb = new StringBuilder();
|
rsb.append("运行时长:");
|
rsb.append(modelCommonResult.get("run_time_normal").toString());
|
det.setRemark(rsb.toString());
|
}
|
detList.add(det);
|
}
|
|
// 设备健康故障记录
|
if (deviceHealthAlarmDetailDTOList.size() > 0) {
|
DeviceHealthAlarmDTO deviceHealthAlarm = new DeviceHealthAlarmDTO();
|
deviceHealthAlarm.setId(alarmId);
|
deviceHealthAlarm.setReportId(reportDTO.getId());
|
deviceHealthAlarm.setDevNo(evaluateDTO.getDevNo());
|
deviceHealthAlarm.setDevName(evaluateDTO.getDevName());
|
deviceHealthAlarm.setFaultTime(runTime);
|
deviceHealthAlarm.setIsPushed(0);
|
deviceHealthAlarm.setPushType(evaluateDTO.getIsPushed() == 0 ? 2 : 1);
|
deviceHealthAlarm.setCreateDate(new Date());
|
deviceHealthAlarm.setAlarmIndexTypes(String.join(",", alarmIndexTypes));
|
deviceHealthAlarm.setAlarmSolutions(String.join("\n", alarmSolutions));
|
|
reportDTO.setDeviceHealthAlarm(deviceHealthAlarm);
|
reportDTO.setDeviceHealthAlarmDetails(deviceHealthAlarmDetailDTOList);
|
}
|
reportDTO.setDetList(detList);
|
|
deviceHealthReportService.save(reportDTO);
|
|
DeviceHealthEvaluateDTO updateDto = new DeviceHealthEvaluateDTO();
|
updateDto.setId(evaluateDTO.getId());
|
updateDto.setReportContent(reportDTO.getContent());
|
updateDto.setReportDate(runTime);
|
updateDto.setReportId(reportDTO.getId());
|
updateDto.setAbnormalCount(reportDTO.getAbnormalCount());
|
updateDto.setHealthScore(reportDTO.getHealthScore());
|
updateDto.setHealthLevel(reportDTO.getHealthLevel());
|
deviceHealthEvaluateService.updateReport(updateDto);
|
}
|
public void deviceStatCount(Calendar calendar) {
|
DeviceStatCountDTO deviceStatCountDTO = deviceStatCountService.getDeviceStatCount();
|
DeviceStatCountEntity deviceStatCount = ConvertUtils.sourceToTarget(deviceStatCountDTO, DeviceStatCountEntity.class);
|
deviceStatCount.setId(UUID.randomUUID().toString());
|
deviceStatCount.setDate(calendar.getTime());
|
deviceStatCount.setCreateDate(new Date());
|
deviceStatCountService.insert(deviceStatCount);
|
}
|
|
private String getRand(String devNo) {
|
String t = Long.toString(System.currentTimeMillis());
|
return devNo.substring(0, 1) + t.substring(t.length() - 4);
|
}
|
|
private int getAbnormalCount(String partGrade) {
|
int result = 0;
|
if (StringUtils.isBlank(partGrade)) {
|
return result;
|
}
|
List<Integer> pgList = JSONArray.parseArray(partGrade, Integer.class);
|
if (CollectionUtils.isEmpty(pgList)) {
|
return result;
|
}
|
for (int i = 0; i < pgList.size(); i++) {
|
if (pgList.get(i) != 1) {
|
result = result + 1;
|
}
|
}
|
return result;
|
}
|
|
private List<BigDecimal> getValueArr(Object value) {
|
List<BigDecimal> result = new ArrayList<>();
|
if (value == null) {
|
return result;
|
}
|
result = JSONArray.parseArray(JSON.toJSONString(value), BigDecimal.class);
|
return result;
|
|
}
|
|
private List<Integer> getIntValueArr(Object value) {
|
List<Integer> result = new ArrayList<>();
|
if (value == null) {
|
return result;
|
}
|
result = JSONArray.parseArray(JSON.toJSONString(value), Integer.class);
|
return result;
|
|
}
|
}
|