Files
MiddlePlatform/maibu-netty-server/src/main/java/com/maibu/service/DeviceThreadService.java

164 lines
6.7 KiB
Java
Raw Normal View History

2026-04-17 17:12:41 +08:00
package com.maibu.service;
2026-04-17 10:42:16 +08:00
import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson2.JSON;
2026-04-17 17:12:41 +08:00
import com.maibu.common.CommandConstant;
import com.maibu.common.NettyCacheKey;
import com.maibu.core.redis.RedisCache;
import com.maibu.domain.DeviceRunningStatusHistory;
import com.maibu.domain.DeviceStatusRecordDTO;
import com.maibu.dto.DeviceErrorPushDTO;
import com.maibu.dto.DeviceErrorPushDetail;
import com.maibu.dto.NettyDevice;
import com.maibu.entity.ErrorIdentificationStandard;
import com.maibu.enums.CompareEnum;
import com.maibu.enums.RespondCode;
import com.maibu.manager.DeviceSessionManager;
import com.maibu.mapper.ErrorIdentificationStandardMapper;
import com.maibu.memory.GlobalMemory;
import com.maibu.utils.CommandUtils;
import com.maibu.utils.CompareUtils;
2026-04-17 10:42:16 +08:00
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
2026-04-21 09:20:55 +08:00
import org.springframework.util.CollectionUtils;
2026-04-17 10:42:16 +08:00
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
public class DeviceThreadService {
@Autowired
private ResourceLoader resourceLoader;
@Autowired
private GlobalMemory globalMemory;
@Autowired
private RedisCache redisCache;
@Autowired
private DeviceSessionManager sessionManager;
@Autowired
private ErrorIdentificationStandardMapper standardMapper;
public void deviceErrorMonitor() throws InterruptedException, IOException {
initStandard();
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleWithFixedDelay(() -> {
try {
String key = NettyCacheKey.deviceRunningStatusKey;
Collection<String> keys = redisCache.getListKeyByPrefix(key);
if (!CollectionUtils.isEmpty(keys)) {
keys.forEach(k -> {
DeviceStatusRecordDTO recordDTO = redisCache.getCacheObject(k);
if (recordDTO != null && !CollectionUtils.isEmpty(recordDTO.getHistories())) {
recordDTO.getHistories().sort(Comparator.comparing(DeviceRunningStatusHistory::getCreateTime).reversed());
DeviceRunningStatusHistory history = recordDTO.getHistories().get(0);
List<DeviceErrorPushDetail> compared = compareErrorStandard(history, globalMemory.standard);
String[] parts = k.split(":");
String deviceId = parts[1];
DeviceErrorPushDTO pushDTO = new DeviceErrorPushDTO();
pushDTO.setDeviceId(deviceId);
pushDTO.setTime(System.currentTimeMillis());
pushDTO.setDetails(compared);
pushDTO.setEvent(RespondCode.device_error_push);
//todo push 推送到前端
pushErrorMessage(deviceId, JSON.toJSONString(pushDTO));
}
});
}
} catch (Exception e) {
log.error("执行监测错误线程错误:{}", e.getMessage());
}
}, 0, 2, TimeUnit.MINUTES);
}
public void initStandard() throws IOException {
if (globalMemory.standard == null) {
List<ErrorIdentificationStandard> standards = standardMapper.selectList();
if (CollectionUtils.isEmpty(standards)) {
// 读取resource目录下的device-config.json文件
Resource resource = resourceLoader.getResource("classpath:errorStandard.json");
// 使用fastjson2转换为DeviceConfig对象
String jsonContent = IoUtil.readUtf8(resource.getInputStream());
globalMemory.standard = JSON.parseArray(jsonContent, ErrorIdentificationStandard.class);
} else {
globalMemory.standard = standards;
}
}
}
public void pushErrorMessage(String deviceId, String dto) {
NettyDevice device = sessionManager.getDevice(deviceId);
if (device != null) {
ByteBuf buf = Unpooled.buffer();
CommandUtils.buildCommand(buf, dto, CommandConstant.interaction);
if (device.getChannel() != null && device.getChannel().isActive()) {
device.getChannel().writeAndFlush(buf);
}
}
}
public List<DeviceErrorPushDetail> compareErrorStandard(DeviceRunningStatusHistory history, List<ErrorIdentificationStandard> standards) {
if (history == null || CollectionUtils.isEmpty(standards)) return null;
List<DeviceErrorPushDetail> list = new ArrayList<>();
standards.forEach(standard -> {
String fieldName = standard.getField();
String compareValues = standard.getCompareValues();
CompareEnum compareType = standard.getCompareType();
String targetValue = knownClassFieldFinding(fieldName, history);
if (!StringUtils.isEmpty(compareValues) && !StringUtils.isEmpty(targetValue)) {
boolean result = CompareUtils.compare(compareType, compareValues, targetValue);
if (!result) {
DeviceErrorPushDetail detail = new DeviceErrorPushDetail();
detail.setErrorName(standard.getErrorName());
detail.setDescription(standard.getErrorDescription());
detail.setValue(targetValue);
detail.setRange(compareValues);
list.add(detail);
}
}
});
return list;
}
private static String knownClassFieldFinding(String fieldName, DeviceRunningStatusHistory history) {
try {
// 1. 获取类的Class对象
Class<?> historyClass = DeviceRunningStatusHistory.class;
Field field = historyClass.getDeclaredField(fieldName);
field.setAccessible(true);
Object value = field.get(history);
return (String) value;
} catch (NoSuchFieldException | IllegalAccessException e) {
System.out.println("获取字段失败: " + e.getMessage());
log.error("获取属性值失败:{}", e.getMessage());
}
return null;
}
}