diff --git a/agri-framework/src/main/java/com/agri/framework/interceptor/DeviceStatusHandler.java b/agri-framework/src/main/java/com/agri/framework/interceptor/DeviceStatusHandler.java index 24febda..cd068c0 100644 --- a/agri-framework/src/main/java/com/agri/framework/interceptor/DeviceStatusHandler.java +++ b/agri-framework/src/main/java/com/agri/framework/interceptor/DeviceStatusHandler.java @@ -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 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+")); + } + } diff --git a/agri-framework/src/main/java/com/agri/framework/interceptor/FrontendControlHandler.java b/agri-framework/src/main/java/com/agri/framework/interceptor/FrontendControlHandler.java index f07d487..04d1973 100644 --- a/agri-framework/src/main/java/com/agri/framework/interceptor/FrontendControlHandler.java +++ b/agri-framework/src/main/java/com/agri/framework/interceptor/FrontendControlHandler.java @@ -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> 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 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); + + } } \ No newline at end of file diff --git a/agri-framework/src/main/java/com/agri/framework/manager/AgriStatusManager.java b/agri-framework/src/main/java/com/agri/framework/manager/AgriStatusManager.java index b2237e8..f9c3463 100644 --- a/agri-framework/src/main/java/com/agri/framework/manager/AgriStatusManager.java +++ b/agri-framework/src/main/java/com/agri/framework/manager/AgriStatusManager.java @@ -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) { diff --git a/agri-quartz/src/main/java/com/agri/quartz/task/AgriStatusTask.java b/agri-quartz/src/main/java/com/agri/quartz/task/AgriStatusTask.java index f892b77..de17bef 100644 --- a/agri-quartz/src/main/java/com/agri/quartz/task/AgriStatusTask.java +++ b/agri-quartz/src/main/java/com/agri/quartz/task/AgriStatusTask.java @@ -89,7 +89,7 @@ public class AgriStatusTask { // 4. 保存离线设备 List 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 offlineDevices = new ArrayList<>(); for (SysAgriInfo agriInfo : agriInfos) { if (!statusMap.containsKey(agriInfo.getImei())) { + agriInfo.setTitle("设备离线告警"); + agriInfo.setMsg("怀疑设备离线!请及时检查"); offlineDevices.add(agriInfo); log.info("设备{} 不存在设备状态", agriInfo.getImei()); } diff --git a/agri-quartz/src/main/java/com/agri/quartz/task/AgriTempTask.java b/agri-quartz/src/main/java/com/agri/quartz/task/AgriTempTask.java index fdde433..6a205a6 100644 --- a/agri-quartz/src/main/java/com/agri/quartz/task/AgriTempTask.java +++ b/agri-quartz/src/main/java/com/agri/quartz/task/AgriTempTask.java @@ -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 latestDataMap = queryLatestDtuData(imeiList); List 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 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); } diff --git a/agri-system/src/main/java/com/agri/system/domain/SysAgriInfo.java b/agri-system/src/main/java/com/agri/system/domain/SysAgriInfo.java index 6cb2def..13a008d 100644 --- a/agri-system/src/main/java/com/agri/system/domain/SysAgriInfo.java +++ b/agri-system/src/main/java/com/agri/system/domain/SysAgriInfo.java @@ -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; } diff --git a/agri-system/src/main/java/com/agri/system/domain/SysUserAgri.java b/agri-system/src/main/java/com/agri/system/domain/SysUserAgri.java index c16f865..4551d5f 100644 --- a/agri-system/src/main/java/com/agri/system/domain/SysUserAgri.java +++ b/agri-system/src/main/java/com/agri/system/domain/SysUserAgri.java @@ -90,4 +90,7 @@ public class SysUserAgri extends BaseEntity public SysUserAgri(List idList) { this.idList = idList; } + + public SysUserAgri() { + } } diff --git a/agri-system/src/main/java/com/agri/system/service/AgriService.java b/agri-system/src/main/java/com/agri/system/service/AgriService.java index 115b2fe..d460202 100644 --- a/agri-system/src/main/java/com/agri/system/service/AgriService.java +++ b/agri-system/src/main/java/com/agri/system/service/AgriService.java @@ -7,9 +7,7 @@ import java.util.Map; public interface AgriService { - void sendAlarmMessage(String msg, String imei, String timeStr) throws Exception; - - void saveMessage(List offlineList,String msg); + void saveMessage(List offlineList); List queryAllGreenhouseImei(List agriInfos); diff --git a/agri-system/src/main/java/com/agri/system/service/impl/AgriServiceImpl.java b/agri-system/src/main/java/com/agri/system/service/impl/AgriServiceImpl.java index 701f7cb..a6ee18c 100644 --- a/agri-system/src/main/java/com/agri/system/service/impl/AgriServiceImpl.java +++ b/agri-system/src/main/java/com/agri/system/service/impl/AgriServiceImpl.java @@ -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 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 offlineList,String msg) { + public void saveMessage(List offlineList) { // 离线是否为空 if (CollectionUtils.isEmpty(offlineList)) { return; @@ -59,10 +41,10 @@ public class AgriServiceImpl implements AgriService { List 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){