提交 | 用户 | 时间
|
a6de49
|
1 |
package com.iailab.module.job.task; |
H |
2 |
|
|
3 |
import com.alibaba.fastjson.JSON; |
|
4 |
import com.alibaba.fastjson.JSONArray; |
|
5 |
import com.iailab.framework.common.util.object.ConvertUtils; |
|
6 |
import com.iailab.common.utils.DateUtils; |
|
7 |
import com.iailab.module.device.commons.HealthIndexTypeEnum; |
|
8 |
import com.iailab.module.device.commons.HealthLevelEnum; |
|
9 |
import com.iailab.module.device.entity.DeviceStatCountEntity; |
|
10 |
import com.iailab.module.device.entity.DeviceStatNewnessEntity; |
|
11 |
import com.iailab.module.device.dto.*; |
|
12 |
import com.iailab.module.device.service.*; |
|
13 |
import com.iailab.module.model.handler.ModelHandler; |
|
14 |
import com.iailab.module.model.sample.constructor.SampleDataConstructor; |
|
15 |
import com.iailab.module.model.sample.constructor.SampleInfoConstructor; |
|
16 |
import com.iailab.module.model.sample.dto.ColumnItem; |
|
17 |
import com.iailab.module.model.sample.entity.DataEntity; |
325d2f
|
18 |
import com.xxl.job.core.handler.annotation.XxlJob; |
a6de49
|
19 |
import org.apache.commons.lang3.StringUtils; |
H |
20 |
import org.slf4j.Logger; |
|
21 |
import org.slf4j.LoggerFactory; |
|
22 |
import javax.annotation.Resource; |
|
23 |
import org.springframework.stereotype.Component; |
|
24 |
import org.springframework.util.CollectionUtils; |
|
25 |
|
|
26 |
import java.math.BigDecimal; |
|
27 |
import java.util.*; |
|
28 |
import java.util.stream.Collectors; |
|
29 |
|
|
30 |
/** |
|
31 |
* 设备健康评价 |
|
32 |
* 10 0 0/1 * * ? |
|
33 |
* |
|
34 |
* @author PanZhibao |
|
35 |
* @Description |
|
36 |
* @createTime 2024年06月29日 |
|
37 |
*/ |
|
38 |
@Component("deviceHealthTask") |
|
39 |
public class DeviceHealthTask implements ITask { |
|
40 |
private Logger logger = LoggerFactory.getLogger(getClass()); |
|
41 |
|
|
42 |
|
|
43 |
private BigDecimal DEFAULT_HEALTH_SCORE = new BigDecimal(100); |
|
44 |
|
|
45 |
private String DEFAULT_REPORT_CONTENT = "设备运行正常"; |
|
46 |
|
|
47 |
private int DEFAULT_DATA_LENGTH = 60; |
|
48 |
|
|
49 |
@Resource |
|
50 |
private DeviceHealthEvaluateService deviceHealthEvaluateService; |
|
51 |
|
|
52 |
@Resource |
|
53 |
private DeviceEvaluateIndexService deviceEvaluateIndexService; |
|
54 |
|
|
55 |
@Resource |
|
56 |
private SampleInfoConstructor sampleInfoConstructor; |
|
57 |
|
|
58 |
@Resource |
|
59 |
private SampleDataConstructor sampleDataConstructor; |
|
60 |
|
|
61 |
@Resource |
|
62 |
private ModelHandler modelHandler; |
|
63 |
|
|
64 |
@Resource |
|
65 |
private DeviceHealthReportService deviceHealthReportService; |
|
66 |
|
|
67 |
@Resource |
|
68 |
private DeviceStatCountService deviceStatCountService; |
|
69 |
|
|
70 |
@Resource |
|
71 |
private DeviceInfoService deviceInfoService; |
|
72 |
|
|
73 |
@Resource |
|
74 |
private DeviceFaultService deviceFaultService; |
|
75 |
|
|
76 |
@Resource |
|
77 |
private DeviceStatNewnessService deviceStatNewnessService; |
|
78 |
|
|
79 |
private final int GRANULARITY = 60; |
|
80 |
|
|
81 |
private Map<Integer, String> HEALTH_FAULT_TYPE = new HashMap<>(); |
|
82 |
private Map<String, String> ALARM_INDEX_TYPE = new HashMap<>(); |
|
83 |
|
|
84 |
private String[] indexArr = new String[]{HealthIndexTypeEnum.elec.getCode(), HealthIndexTypeEnum.temperature.getCode(), |
|
85 |
HealthIndexTypeEnum.flutter.getCode(), HealthIndexTypeEnum.runTime.getCode()}; |
|
86 |
|
|
87 |
|
|
88 |
|
|
89 |
DeviceHealthTask() { |
|
90 |
HEALTH_FAULT_TYPE.put(1, "波动正常,趋势正常"); |
|
91 |
HEALTH_FAULT_TYPE.put(2, "波动正常,趋势异常"); |
|
92 |
HEALTH_FAULT_TYPE.put(3, "波动异常,趋势正常"); |
|
93 |
HEALTH_FAULT_TYPE.put(4, "波动异常,趋势异常"); |
|
94 |
|
|
95 |
ALARM_INDEX_TYPE.put("temperature", "温度"); |
|
96 |
ALARM_INDEX_TYPE.put("flutter", "震动"); |
|
97 |
ALARM_INDEX_TYPE.put("elec", "电流"); |
|
98 |
} |
|
99 |
|
|
100 |
@Override |
325d2f
|
101 |
@XxlJob("deviceHealthTask") |
a6de49
|
102 |
public void run(String params) { |
H |
103 |
Calendar calendar = Calendar.getInstance(); |
|
104 |
calendar.set(Calendar.MILLISECOND, 0); |
|
105 |
calendar.set(Calendar.SECOND, 0); |
|
106 |
try { |
|
107 |
List<DeviceStatNewnessEntity> newnessList = new ArrayList<>(); |
|
108 |
Map<String, Object> queryParams = new HashMap<>(); |
|
109 |
queryParams.put("isEnable", 1); |
|
110 |
List<DeviceHealthEvaluateDTO> evaList = deviceHealthEvaluateService.list(queryParams); |
|
111 |
if (CollectionUtils.isEmpty(evaList)) { |
|
112 |
return; |
|
113 |
} |
|
114 |
// 开始健康评价 |
|
115 |
evaList.forEach(item -> { |
|
116 |
this.runModel(item, calendar.getTime(), newnessList); |
|
117 |
}); |
|
118 |
|
|
119 |
// 统计数量 |
|
120 |
deviceStatCount(calendar); |
|
121 |
|
|
122 |
// 更新设备新度系数 |
|
123 |
deviceStatNewnessService.statNewness(newnessList, calendar.getTime()); |
|
124 |
|
|
125 |
} catch (Exception ex) { |
|
126 |
logger.error("DeviceHealthTask运行异常"); |
|
127 |
ex.printStackTrace(); |
|
128 |
} |
|
129 |
logger.info("DeviceHealthTask运行完成"); |
|
130 |
} |
|
131 |
|
|
132 |
public void runModel(DeviceHealthEvaluateDTO dto, Date runTime, List<DeviceStatNewnessEntity> newnessList) { |
|
133 |
try { |
|
134 |
List<DeviceEvaluateIndexDTO> indexList = deviceEvaluateIndexService.listByEvaluateId(dto.getId()); |
|
135 |
if (CollectionUtils.isEmpty(indexList)) { |
|
136 |
DeviceHealthEvaluateDTO updateDto = new DeviceHealthEvaluateDTO(); |
|
137 |
updateDto.setId(dto.getId()); |
|
138 |
updateDto.setReportContent(DEFAULT_REPORT_CONTENT); |
|
139 |
updateDto.setReportDate(runTime); |
|
140 |
updateDto.setReportId(""); |
|
141 |
updateDto.setAbnormalCount(0); |
|
142 |
updateDto.setHealthScore(DEFAULT_HEALTH_SCORE); |
|
143 |
updateDto.setHealthLevel(HealthLevelEnum.Level1.getCode()); |
|
144 |
deviceHealthEvaluateService.updateReport(updateDto); |
|
145 |
return; |
|
146 |
} |
|
147 |
Map<String, DeviceEvaluateIndexDTO> indexMap = new HashMap<>(); |
|
148 |
indexList.forEach(item -> { |
|
149 |
indexMap.put(item.getIndexType(), item); |
|
150 |
}); |
|
151 |
|
|
152 |
DEFAULT_DATA_LENGTH = indexList.get(0).getDataLength(); |
|
153 |
|
|
154 |
ColumnItem columnItem = new ColumnItem(); |
|
155 |
columnItem.setEndTime(runTime); |
|
156 |
columnItem.setStartTime(sampleInfoConstructor.calculateTime(runTime, true, DEFAULT_DATA_LENGTH - 1, GRANULARITY)); |
|
157 |
List<double[][]> sampleDataList = new ArrayList<>(); |
|
158 |
Map<String, List<DataEntity>> dataMap = new LinkedHashMap<>(); |
|
159 |
|
|
160 |
double[][] matrix1 = new double[DEFAULT_DATA_LENGTH][indexArr.length]; |
|
161 |
double[][] matrix2 = new double[1][3]; |
|
162 |
for (int i = 0; i < indexArr.length; i++) { |
|
163 |
if (indexMap.get(indexArr[i]) == null) { |
|
164 |
for (int k = 0; k < DEFAULT_DATA_LENGTH; k++) { |
|
165 |
matrix1[k][i] = -2; |
|
166 |
} |
|
167 |
continue; |
|
168 |
} |
|
169 |
DeviceEvaluateIndexDTO indDTO = indexMap.get(indexArr[i]); |
|
170 |
columnItem.setParamId(indDTO.getParamId()); |
|
171 |
columnItem.setParamType(indDTO.getParamType()); |
|
172 |
List<DataEntity> dataEntityList = sampleDataConstructor.getColumnData(columnItem); |
|
173 |
logger.info("BEF:ParamType=" + indDTO.getParamType() + ";ParamId=" + indDTO.getParamId() + ";size=" + dataEntityList.size()); |
|
174 |
//补全数据 |
|
175 |
dataEntityList = sampleDataConstructor.completionData(matrix1.length, dataEntityList, columnItem.startTime, columnItem.endTime, GRANULARITY); |
|
176 |
logger.info("AFT:ParamType=" + indDTO.getParamType() + ";ParamId=" + indDTO.getParamId() + ";size=" + dataEntityList.size()); |
|
177 |
if (CollectionUtils.isEmpty(dataEntityList)) { |
|
178 |
continue; |
|
179 |
} |
|
180 |
for (int k = 0; k < DEFAULT_DATA_LENGTH; k++) { |
|
181 |
matrix1[k][i] = dataEntityList.get(k).getDataValue(); |
|
182 |
} |
|
183 |
dataMap.put(indexArr[i], dataEntityList); |
|
184 |
|
|
185 |
if (i < 3) { |
|
186 |
matrix2[0][i] = indDTO.getNominalValue().doubleValue(); |
|
187 |
} |
|
188 |
} |
|
189 |
sampleDataList.add(matrix1); |
|
190 |
sampleDataList.add(matrix2); |
|
191 |
|
|
192 |
// 调用模型 |
|
193 |
logger.info("调用模型,DevNo=" + dto.getDevNo()); |
|
194 |
Map<String, Object> modelCommonResult = modelHandler.run(dto.getModelCode(), sampleDataList); |
|
195 |
|
|
196 |
// 生成评价报告 |
|
197 |
this.saveReport(dto, runTime, modelCommonResult, dataMap, indexMap); |
|
198 |
|
|
199 |
// 更新新度系数 |
|
200 |
if (modelCommonResult.get("run_time_adjust") != null) { |
|
201 |
DeviceStatNewnessEntity deviceStatNewness = new DeviceStatNewnessEntity(); |
|
202 |
deviceStatNewness.setDevNo(dto.getDevNo()); |
|
203 |
deviceStatNewness.setDevName(dto.getDevName()); |
|
204 |
deviceStatNewness.setRunTime(new BigDecimal(modelCommonResult.get("run_time_normal").toString()).intValue()); |
|
205 |
deviceStatNewness.setLossTime(new BigDecimal(modelCommonResult.get("run_time_adjust").toString()).intValue()); |
|
206 |
deviceStatNewness.setLossRate(new BigDecimal(deviceStatNewness.getLossTime()).divide(new BigDecimal(deviceStatNewness.getRunTime()),2,BigDecimal.ROUND_HALF_UP)); |
|
207 |
newnessList.add(deviceStatNewness); |
|
208 |
} |
|
209 |
} catch (Exception ex) { |
|
210 |
ex.printStackTrace(); |
|
211 |
logger.error("设备健康评价计算异常,devNo=" + dto.getDevNo()); |
|
212 |
} |
|
213 |
} |
|
214 |
|
|
215 |
public void saveReport(DeviceHealthEvaluateDTO evaluateDTO, Date runTime, Map<String, Object> modelCommonResult, |
|
216 |
Map<String, List<DataEntity>> dataMap, Map<String, DeviceEvaluateIndexDTO> indexMap) { |
|
217 |
|
|
218 |
DeviceInfoDTO deviceInfo = deviceInfoService.getByDevNo(evaluateDTO.getDevNo()); |
|
219 |
|
|
220 |
DeviceHealthReportDTO reportDTO = new DeviceHealthReportDTO(); |
|
221 |
reportDTO.setId(UUID.randomUUID().toString()); |
|
222 |
reportDTO.setReportNo("H" + DateUtils.format(runTime, "yyyyMMddHHmmss") + getRand(evaluateDTO.getDevNo())); |
|
223 |
reportDTO.setReportName(evaluateDTO.getDevName() + "健康评价报告"); |
|
224 |
reportDTO.setReportDate(runTime); |
|
225 |
String deviceHealthLevel = modelCommonResult.get("isqualified").toString(); |
|
226 |
reportDTO.setHealthLevel(deviceHealthLevel); |
|
227 |
reportDTO.setAbnormalCount(getAbnormalCount(JSONArray.toJSONString(modelCommonResult.get("part_grade")))); |
|
228 |
reportDTO.setContent(modelCommonResult.get("health_evaluate").toString()); |
|
229 |
reportDTO.setHealthScore(new BigDecimal(modelCommonResult.get("health_score").toString())); |
|
230 |
reportDTO.setDataLength(DEFAULT_DATA_LENGTH); |
|
231 |
reportDTO.setRunTime(new BigDecimal(modelCommonResult.get("run_time_adjust").toString()).intValue()); |
|
232 |
reportDTO.setDevNo(evaluateDTO.getDevNo()); |
|
233 |
reportDTO.setDevName(evaluateDTO.getDevName()); |
|
234 |
if (deviceInfo != null) { |
|
235 |
reportDTO.setClassNo(deviceInfo.getClassNo()); |
|
236 |
reportDTO.setClassName(deviceInfo.getClassName()); |
|
237 |
reportDTO.setWorkshop(deviceInfo.getWorkshop()); |
|
238 |
reportDTO.setModel(deviceInfo.getModel()); |
|
239 |
} |
|
240 |
List<Integer> partGrade = getIntValueArr(modelCommonResult.get("part_grade")); |
|
241 |
List<BigDecimal> maxArr = getValueArr(modelCommonResult.get("max_arr")); |
|
242 |
List<BigDecimal> minArr = getValueArr(modelCommonResult.get("min_arr")); |
|
243 |
List<BigDecimal> meanArr = getValueArr(modelCommonResult.get("mean_arr")); |
|
244 |
List<DeviceHealthReportDataDTO> detList = new ArrayList<>(); |
|
245 |
List<DeviceHealthAlarmDetailDTO> deviceHealthAlarmDetailDTOList = new ArrayList<>(); |
|
246 |
List<String> alarmIndexTypes = new ArrayList<>(); |
|
247 |
List<String> alarmSolutions = new ArrayList<>(); |
|
248 |
// 故障id |
|
249 |
String alarmId = UUID.randomUUID().toString(); |
|
250 |
for (int i = 0; i < indexArr.length; i++) { |
|
251 |
List<DataEntity> dataList = dataMap.get(indexArr[i]); |
|
252 |
if (CollectionUtils.isEmpty(dataList)) { |
|
253 |
continue; |
|
254 |
} |
|
255 |
List<Object[]> dataCont = dataList.stream().map(t -> { |
|
256 |
return new Object[]{DateUtils.format(t.getTimeStamp(), DateUtils.DATE_TIME_PATTERN_MIN), new BigDecimal(t.getDataValue()).setScale(4, BigDecimal.ROUND_HALF_UP)}; |
|
257 |
}).collect(Collectors.toList()); |
|
258 |
DeviceHealthReportDataDTO det = new DeviceHealthReportDataDTO(); |
|
259 |
det.setSort(i); |
|
260 |
det.setDataName(indexMap.get(indexArr[i]).getParamName()); |
|
261 |
det.setDataValue(JSONArray.toJSONString(dataCont)); |
|
262 |
if (!HealthIndexTypeEnum.runTime.getCode().equals(indexArr[i])) { |
|
263 |
det.setDataMax(maxArr.get(i)); |
|
264 |
det.setDataMin(minArr.get(i)); |
|
265 |
det.setDataAvg(meanArr.get(i)); |
|
266 |
det.setGradeCode(partGrade.get(i).toString()); |
|
267 |
det.setGradeName(HEALTH_FAULT_TYPE.get(partGrade.get(i))); |
|
268 |
|
|
269 |
DeviceFaultDTO querySoluDto = new DeviceFaultDTO(); |
|
270 |
querySoluDto.setClassNo(deviceInfo.getClassNo()); |
|
271 |
querySoluDto.setIndexType(indexArr[i]); |
|
272 |
querySoluDto.setFaultType(det.getGradeCode()); |
|
273 |
DeviceFaultDTO faultDTO = deviceFaultService.getSolution(querySoluDto); |
|
274 |
if (faultDTO != null) { |
|
275 |
det.setSolution(faultDTO.getSolution()); |
|
276 |
det.setFaultCode(faultDTO.getFaultCode()); |
|
277 |
} |
|
278 |
|
|
279 |
// 设备健康故障详情记录 |
|
280 |
if (HealthLevelEnum.Level3.getCode().equals(deviceHealthLevel) && faultDTO != null){ |
|
281 |
DeviceHealthAlarmDetailDTO deviceHealthAlarmDetail = new DeviceHealthAlarmDetailDTO(); |
|
282 |
deviceHealthAlarmDetail.setId(UUID.randomUUID().toString()); |
|
283 |
deviceHealthAlarmDetail.setAlarmId(alarmId); |
|
284 |
deviceHealthAlarmDetail.setFaultCode(faultDTO.getFaultCode()); |
|
285 |
deviceHealthAlarmDetail.setFaultName(HEALTH_FAULT_TYPE.get(partGrade.get(i))); |
|
286 |
deviceHealthAlarmDetail.setSolution(faultDTO.getSolution()); |
|
287 |
|
|
288 |
alarmIndexTypes.add(ALARM_INDEX_TYPE.get(faultDTO.getIndexType())); |
|
289 |
alarmSolutions.add(faultDTO.getSolution()); |
|
290 |
deviceHealthAlarmDetailDTOList.add(deviceHealthAlarmDetail); |
|
291 |
} |
|
292 |
} else { |
|
293 |
StringBuilder rsb = new StringBuilder(); |
|
294 |
rsb.append("运行时长:"); |
|
295 |
rsb.append(modelCommonResult.get("run_time_normal").toString()); |
|
296 |
det.setRemark(rsb.toString()); |
|
297 |
} |
|
298 |
detList.add(det); |
|
299 |
} |
|
300 |
|
|
301 |
// 设备健康故障记录 |
|
302 |
if (deviceHealthAlarmDetailDTOList.size() > 0) { |
|
303 |
DeviceHealthAlarmDTO deviceHealthAlarm = new DeviceHealthAlarmDTO(); |
|
304 |
deviceHealthAlarm.setId(alarmId); |
|
305 |
deviceHealthAlarm.setReportId(reportDTO.getId()); |
|
306 |
deviceHealthAlarm.setDevNo(evaluateDTO.getDevNo()); |
|
307 |
deviceHealthAlarm.setDevName(evaluateDTO.getDevName()); |
|
308 |
deviceHealthAlarm.setFaultTime(runTime); |
|
309 |
deviceHealthAlarm.setIsPushed(0); |
|
310 |
deviceHealthAlarm.setPushType(evaluateDTO.getIsPushed() == 0 ? 2 : 1); |
|
311 |
deviceHealthAlarm.setCreateDate(new Date()); |
|
312 |
deviceHealthAlarm.setAlarmIndexTypes(String.join(",", alarmIndexTypes)); |
|
313 |
deviceHealthAlarm.setAlarmSolutions(String.join("\n", alarmSolutions)); |
|
314 |
|
|
315 |
reportDTO.setDeviceHealthAlarm(deviceHealthAlarm); |
|
316 |
reportDTO.setDeviceHealthAlarmDetails(deviceHealthAlarmDetailDTOList); |
|
317 |
} |
|
318 |
reportDTO.setDetList(detList); |
|
319 |
|
|
320 |
deviceHealthReportService.save(reportDTO); |
|
321 |
|
|
322 |
DeviceHealthEvaluateDTO updateDto = new DeviceHealthEvaluateDTO(); |
|
323 |
updateDto.setId(evaluateDTO.getId()); |
|
324 |
updateDto.setReportContent(reportDTO.getContent()); |
|
325 |
updateDto.setReportDate(runTime); |
|
326 |
updateDto.setReportId(reportDTO.getId()); |
|
327 |
updateDto.setAbnormalCount(reportDTO.getAbnormalCount()); |
|
328 |
updateDto.setHealthScore(reportDTO.getHealthScore()); |
|
329 |
updateDto.setHealthLevel(reportDTO.getHealthLevel()); |
|
330 |
deviceHealthEvaluateService.updateReport(updateDto); |
|
331 |
} |
|
332 |
public void deviceStatCount(Calendar calendar) { |
|
333 |
DeviceStatCountDTO deviceStatCountDTO = deviceStatCountService.getDeviceStatCount(); |
|
334 |
DeviceStatCountEntity deviceStatCount = ConvertUtils.sourceToTarget(deviceStatCountDTO, DeviceStatCountEntity.class); |
|
335 |
deviceStatCount.setId(UUID.randomUUID().toString()); |
|
336 |
deviceStatCount.setDate(calendar.getTime()); |
|
337 |
deviceStatCount.setCreateDate(new Date()); |
|
338 |
deviceStatCountService.insert(deviceStatCount); |
|
339 |
} |
|
340 |
|
|
341 |
private String getRand(String devNo) { |
|
342 |
String t = Long.toString(System.currentTimeMillis()); |
|
343 |
return devNo.substring(0, 1) + t.substring(t.length() - 4); |
|
344 |
} |
|
345 |
|
|
346 |
private int getAbnormalCount(String partGrade) { |
|
347 |
int result = 0; |
|
348 |
if (StringUtils.isBlank(partGrade)) { |
|
349 |
return result; |
|
350 |
} |
|
351 |
List<Integer> pgList = JSONArray.parseArray(partGrade, Integer.class); |
|
352 |
if (CollectionUtils.isEmpty(pgList)) { |
|
353 |
return result; |
|
354 |
} |
|
355 |
for (int i = 0; i < pgList.size(); i++) { |
|
356 |
if (pgList.get(i) != 1) { |
|
357 |
result = result + 1; |
|
358 |
} |
|
359 |
} |
|
360 |
return result; |
|
361 |
} |
|
362 |
|
|
363 |
private List<BigDecimal> getValueArr(Object value) { |
|
364 |
List<BigDecimal> result = new ArrayList<>(); |
|
365 |
if (value == null) { |
|
366 |
return result; |
|
367 |
} |
|
368 |
result = JSONArray.parseArray(JSON.toJSONString(value), BigDecimal.class); |
|
369 |
return result; |
|
370 |
|
|
371 |
} |
|
372 |
|
|
373 |
private List<Integer> getIntValueArr(Object value) { |
|
374 |
List<Integer> result = new ArrayList<>(); |
|
375 |
if (value == null) { |
|
376 |
return result; |
|
377 |
} |
|
378 |
result = JSONArray.parseArray(JSON.toJSONString(value), Integer.class); |
|
379 |
return result; |
|
380 |
|
|
381 |
} |
|
382 |
} |