温度上下限告警处理
parent
780a4456e5
commit
c2d651d38d
|
|
@ -4,8 +4,15 @@ import com.agri.common.utils.wechat.WxUtil;
|
|||
import com.agri.framework.config.MqttConfig;
|
||||
import com.agri.framework.manager.MqttAutoOffManager;
|
||||
import com.agri.framework.manager.MqttSubscriptionManager;
|
||||
import com.agri.system.domain.SysAgriInfo;
|
||||
import com.agri.system.domain.SysMessage;
|
||||
import com.agri.system.domain.SysUserAgri;
|
||||
import com.agri.system.service.AgriService;
|
||||
import com.agri.system.service.ISysAgriInfoService;
|
||||
import com.agri.system.util.UrlEncodeUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
|
@ -15,6 +22,7 @@ import org.springframework.data.redis.core.StringRedisTemplate;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
|
@ -58,11 +66,15 @@ public class DeviceStatusHandler {
|
|||
@Autowired
|
||||
private DeviceAckHandler deviceAckHandler;
|
||||
|
||||
|
||||
@Autowired
|
||||
private ISysAgriInfoService agriInfoService;
|
||||
// 新增:最新状态缓存TTL(设备每10秒上报一次,缓存一小段时间即可)
|
||||
@Value("${spring.mqtt.latest-ttl-seconds:120}")
|
||||
private int latestTtlSeconds;
|
||||
|
||||
@Autowired
|
||||
private AgriService agriService;
|
||||
|
||||
private static final String AUTO_MODE = "auto_mode";
|
||||
private static final String AUTO_OFF = "autooff";
|
||||
/**
|
||||
|
|
@ -134,10 +146,60 @@ public class DeviceStatusHandler {
|
|||
|
||||
// 转发消息
|
||||
forwardPayload(deviceId, payload,payloadObj,action, sendObj, isAck);
|
||||
|
||||
// 获取第二个动态段,如"up"或"ack"
|
||||
if ("ack".equals(action)) {
|
||||
deviceAckHandler.isStartAutoOffTask(payloadObj,deviceId,payload);
|
||||
return;
|
||||
}
|
||||
// payload全部为数字
|
||||
if ("up".equals(action) && isAllKeysDigit(payloadObj)) {
|
||||
SysAgriInfo agriInfo = agriInfoService.lambdaQuery()
|
||||
.eq(SysAgriInfo::getImei, deviceId)
|
||||
.one();
|
||||
if (agriInfo == null) {
|
||||
return;
|
||||
}
|
||||
// 温度上下限
|
||||
BigDecimal tempUp = agriInfo.getTempUp();
|
||||
BigDecimal tempLow = agriInfo.getTempLow();
|
||||
// 湿度上下限
|
||||
BigDecimal humiUp = agriInfo.getHumiUp();
|
||||
BigDecimal humiLow = agriInfo.getHumiLow();
|
||||
List<SysAgriInfo> msgList = new ArrayList<>();
|
||||
// 仅当up且所有key为数字时,才更新最新状态缓存
|
||||
for (String key : payloadObj.keySet()) {
|
||||
BigDecimal value = payloadObj.getBigDecimal(key);
|
||||
// 温度
|
||||
if (key.startsWith("20")) {
|
||||
// 温度大于温度上限
|
||||
if (value.compareTo(tempUp) > 0 ) {
|
||||
agriInfo.setTitle("温度异常");
|
||||
agriInfo.setMsg("温度"+key.substring(2)+ "异常!高于上限"+tempUp+"℃!");
|
||||
}
|
||||
// 温度小于温度下限
|
||||
if (value.compareTo(tempLow) < 0) {
|
||||
agriInfo.setTitle("温度异常");
|
||||
agriInfo.setMsg("温度"+key.substring(2)+ "异常!低于下限"+tempLow+"℃!");
|
||||
}
|
||||
msgList.add(agriInfo);
|
||||
}
|
||||
// 湿度
|
||||
if (key.startsWith("10")) {
|
||||
// 湿度大于湿度上限
|
||||
if (value.compareTo(humiUp) > 0 ) {
|
||||
agriInfo.setTitle("湿度异常");
|
||||
agriInfo.setMsg("湿度"+key.substring(2)+ "异常!高于上限"+humiUp+"RH%!");
|
||||
}
|
||||
// 湿度小于湿度下限
|
||||
if (value.compareTo(humiLow) < 0) {
|
||||
agriInfo.setTitle("湿度异常");
|
||||
agriInfo.setMsg("湿度"+key.substring(2)+ "异常!低于下限"+humiLow+"RH%!");
|
||||
}
|
||||
msgList.add(agriInfo);
|
||||
}
|
||||
}
|
||||
|
||||
agriService.saveMessage(msgList);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -236,4 +298,10 @@ public class DeviceStatusHandler {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isAllKeysDigit(JSONObject obj) {
|
||||
return obj != null && !obj.isEmpty()
|
||||
&& obj.keySet().stream().allMatch(k -> k.matches("\\d+"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import com.agri.system.service.ISysUserService;
|
|||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -73,7 +74,7 @@ public class FrontendControlHandler {
|
|||
|
||||
@Autowired
|
||||
private ISysUserService sysUserService;
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
@Value("${spring.mqtt.dtu-ctl-lock-ttl}")
|
||||
private int dtuCtlLockTTL;
|
||||
private static final Map<String, Function<SysAgriLimit, Integer>> LIMIT_MAP = new HashMap<>();
|
||||
|
|
@ -256,4 +257,15 @@ public class FrontendControlHandler {
|
|||
// 普通用户权限:校验Redis中是否绑定该设备
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
public void sendAlarmMessage(String msg, String imei, String timeStr) throws Exception {
|
||||
|
||||
Map<String, Object> alarmMsg = new HashMap<>();
|
||||
alarmMsg.put("online", msg);
|
||||
alarmMsg.put("time", timeStr);
|
||||
alarmMsg.put("imei", imei);
|
||||
String alarmMessage = objectMapper.writeValueAsString(alarmMsg);
|
||||
mqttMessageSender.publish("frontend/" + imei + "/alarm", alarmMessage);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.agri.framework.manager;
|
||||
|
||||
import com.agri.framework.config.MqttConfig;
|
||||
import com.agri.framework.interceptor.FrontendControlHandler;
|
||||
import com.agri.system.domain.SysAgriInfo;
|
||||
import com.agri.system.service.AgriService;
|
||||
import com.agri.system.service.ISysAgriInfoService;
|
||||
|
|
@ -44,6 +45,8 @@ public class AgriStatusManager {
|
|||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Resource
|
||||
private FrontendControlHandler frontendControlHandler;
|
||||
@Autowired
|
||||
private AgriService agriService;
|
||||
|
||||
|
|
@ -131,7 +134,7 @@ public class AgriStatusManager {
|
|||
}
|
||||
// 无论设备是否在线 只要离线就推送设备状态
|
||||
if (!imeiMap.get("imeiOnline")) {
|
||||
agriService.sendAlarmMessage("设备离线", imei, dateNow);
|
||||
frontendControlHandler.sendAlarmMessage("设备离线", imei, dateNow);
|
||||
}
|
||||
successCount++;
|
||||
} catch (Exception e) {
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ public class AgriStatusTask {
|
|||
// 4. 保存离线设备
|
||||
List<SysAgriInfo> offlineDevices = findOfflineDevices(agriInfos, statusMap);
|
||||
// 5. 保存消息中心
|
||||
agriService.saveMessage(offlineDevices,"怀疑设备离线");
|
||||
agriService.saveMessage(offlineDevices);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("设备在线状态推送任务异常", e);
|
||||
|
|
@ -110,6 +110,8 @@ public class AgriStatusTask {
|
|||
List<SysAgriInfo> offlineDevices = new ArrayList<>();
|
||||
for (SysAgriInfo agriInfo : agriInfos) {
|
||||
if (!statusMap.containsKey(agriInfo.getImei())) {
|
||||
agriInfo.setTitle("设备离线告警");
|
||||
agriInfo.setMsg("怀疑设备离线!请及时检查");
|
||||
offlineDevices.add(agriInfo);
|
||||
log.info("设备{} 不存在设备状态", agriInfo.getImei());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.agri.quartz.task;
|
||||
|
||||
import com.agri.framework.interceptor.FrontendControlHandler;
|
||||
import com.agri.system.service.AgriService;
|
||||
import com.agri.system.domain.SysAgriInfo;
|
||||
import com.agri.system.service.ISysAgriInfoService;
|
||||
|
|
@ -40,6 +41,9 @@ public class AgriTempTask {
|
|||
@Autowired
|
||||
private AgriService agriService;
|
||||
|
||||
@Resource
|
||||
private FrontendControlHandler frontendControlHandler;
|
||||
|
||||
public void checkTempStatus() {
|
||||
if (!acquireLock()) {
|
||||
return;
|
||||
|
|
@ -54,7 +58,7 @@ public class AgriTempTask {
|
|||
Map<String, Object> latestDataMap = queryLatestDtuData(imeiList);
|
||||
List<SysAgriInfo> offlineDevices = findOfflineDevices(agriInfos, latestDataMap);
|
||||
pushOfflineAlarm(offlineDevices);
|
||||
agriService.saveMessage(offlineDevices,"怀疑温度离线");
|
||||
agriService.saveMessage(offlineDevices);
|
||||
} catch (Exception e) {
|
||||
log.error("设备在线状态推送任务异常", e);
|
||||
} finally {
|
||||
|
|
@ -104,6 +108,8 @@ public class AgriTempTask {
|
|||
List<SysAgriInfo> offlineList = new ArrayList<>();
|
||||
for (SysAgriInfo agriInfo : agriInfos) {
|
||||
if (!latestDataMap.containsKey(agriInfo.getImei())) {
|
||||
agriInfo.setTitle("温度离线");
|
||||
agriInfo.setMsg("怀疑温度离线!请检查");
|
||||
offlineList.add(agriInfo);
|
||||
log.info("设备{} 不存在温湿度数据", agriInfo.getImei());
|
||||
}
|
||||
|
|
@ -119,7 +125,7 @@ public class AgriTempTask {
|
|||
String timeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
for (SysAgriInfo agriInfo : offlineList) {
|
||||
try {
|
||||
agriService.sendAlarmMessage("温度离线",agriInfo.getImei(), timeStr);
|
||||
frontendControlHandler.sendAlarmMessage("温度离线",agriInfo.getImei(), timeStr);
|
||||
} catch (Exception e) {
|
||||
log.error("发送设备离线告警失败, imei={}", agriInfo.getImei(), e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,4 +112,10 @@ public class SysAgriInfo extends BaseEntity
|
|||
/** 湿度下限(%RH) */
|
||||
@Excel(name = "湿度下限(%RH)")
|
||||
private BigDecimal humiLow;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String title;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String msg;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,4 +90,7 @@ public class SysUserAgri extends BaseEntity
|
|||
public SysUserAgri(List<Long> idList) {
|
||||
this.idList = idList;
|
||||
}
|
||||
|
||||
public SysUserAgri() {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,7 @@ import java.util.Map;
|
|||
|
||||
public interface AgriService {
|
||||
|
||||
void sendAlarmMessage(String msg, String imei, String timeStr) throws Exception;
|
||||
|
||||
void saveMessage(List<SysAgriInfo> offlineList,String msg);
|
||||
void saveMessage(List<SysAgriInfo> offlineList);
|
||||
|
||||
List<String> queryAllGreenhouseImei(List<SysAgriInfo> agriInfos);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.agri.system.service.impl;
|
||||
|
||||
import com.agri.framework.config.MqttConfig;
|
||||
import com.agri.system.service.AgriService;
|
||||
import com.agri.system.domain.SysAgriInfo;
|
||||
import com.agri.system.domain.SysMessage;
|
||||
|
|
@ -19,8 +18,6 @@ import java.util.stream.Collectors;
|
|||
@Service
|
||||
public class AgriServiceImpl implements AgriService {
|
||||
|
||||
@Resource
|
||||
private MqttConfig.MqttMessageSender mqttMessageSender;
|
||||
|
||||
@Resource
|
||||
private ISysUserAgriService userAgriService;
|
||||
|
|
@ -28,24 +25,9 @@ public class AgriServiceImpl implements AgriService {
|
|||
@Resource
|
||||
private ISysMessageService messageService;
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
// 发送离线告警消息
|
||||
@Override
|
||||
public void sendAlarmMessage(String msg, String imei, String timeStr) throws Exception {
|
||||
|
||||
Map<String, Object> alarmMsg = new HashMap<>();
|
||||
alarmMsg.put("online", msg);
|
||||
alarmMsg.put("time", timeStr);
|
||||
alarmMsg.put("imei", imei);
|
||||
String alarmMessage = objectMapper.writeValueAsString(alarmMsg);
|
||||
mqttMessageSender.publish("frontend/" + imei + "/alarm", alarmMessage);
|
||||
|
||||
}
|
||||
|
||||
// 保存离线设备消息
|
||||
@Override
|
||||
public void saveMessage(List<SysAgriInfo> offlineList,String msg) {
|
||||
public void saveMessage(List<SysAgriInfo> offlineList) {
|
||||
// 离线是否为空
|
||||
if (CollectionUtils.isEmpty(offlineList)) {
|
||||
return;
|
||||
|
|
@ -59,10 +41,10 @@ public class AgriServiceImpl implements AgriService {
|
|||
List<SysMessage> msgList = new ArrayList<>();
|
||||
for (SysAgriInfo agriInfo : offlineList) {
|
||||
SysMessage message = new SysMessage();
|
||||
message.setTitle(msg);
|
||||
message.setTitle(agriInfo.getTitle());
|
||||
message.setMsgType("status");
|
||||
message.setReadStatus(0L);
|
||||
message.setContent("大棚【" + agriInfo.getAgriName() + "】" + msg + "!请检查设备状态。");
|
||||
message.setContent("大棚【" + agriInfo.getAgriName() + "】" + agriInfo.getMsg());
|
||||
message.setImgUrl("");
|
||||
message.setLinkUrl(UrlEncodeUtil.buildControlPageUrl(agriInfo, "/pages/home/control/index?agriInfo="));
|
||||
for (SysUserAgri userAgri : agriUser){
|
||||
|
|
|
|||
Loading…
Reference in New Issue