From c35551698c25af43b1d590da741e116241c6d775 Mon Sep 17 00:00:00 2001 From: lld <15027638633@163.com> Date: Tue, 31 Mar 2026 16:50:29 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=89=80=E6=9C=89=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E6=9C=80=E6=96=B0=E7=9A=84=E6=B8=A9=E6=B9=BF=E5=BA=A6?= =?UTF-8?q?=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/agri/quartz/task/AgriStatusTask.java | 9 +- .../com/agri/quartz/task/AgriTempTask.java | 106 ++++++++++++++++++ .../mapper/system/SysDtuDataMapper.xml | 2 +- 3 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 agri-quartz/src/main/java/com/agri/quartz/task/AgriTempTask.java 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 5367ea9..c66a561 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 @@ -39,7 +39,7 @@ public class AgriStatusTask { @Resource private StringRedisTemplate stringRedisTemplate; - @Value("${spring.mqtt.dtu-ctl-lock-ttl:15}") + @Value("${spring.mqtt.dtu-ctl-lock-ttl:60}") private int lockTtl; @Autowired @@ -70,12 +70,7 @@ public class AgriStatusTask { } long startTime = System.currentTimeMillis(); try { - // 2. 安全遍历所有 sub: 开头的 key,提取设备 IMEI -// List allDeviceImeiList = scanAllSubDeviceImei(); -// if (allDeviceImeiList.isEmpty()) { -// log.info("没有找到任何设备订阅记录,结束任务"); -// return; -// } + // 查询大棚列表所有在线设备 List imeiList = agriInfoService.queryImeiByUserId(null); if (imeiList.isEmpty()) { 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 new file mode 100644 index 0000000..65d2dcd --- /dev/null +++ b/agri-quartz/src/main/java/com/agri/quartz/task/AgriTempTask.java @@ -0,0 +1,106 @@ +package com.agri.quartz.task; + +import com.agri.framework.config.MqttConfig; +import com.agri.system.service.ISysAgriInfoService; +import com.agri.system.service.ISysDtuDataService; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.collections4.CollectionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * // 1、查询大棚所有imei + * // 2、查询所有设备最新的温湿度数据 + * // 3、判断谁不存在 + * // 4、发送不存在的告警 + */ +@Component +public class AgriTempTask { + + private static final Logger log = LoggerFactory.getLogger(AgriTempTask.class); + + @Autowired + private ISysDtuDataService dtuDataService; + + @Autowired + private ISysAgriInfoService agriInfoService; + + private static final String LOCK_KEY = "lock:check:temp:push"; + @Resource + private StringRedisTemplate stringRedisTemplate; + + @Value("${spring.mqtt.dtu-ctl-lock-ttl:60}") + private int lockTtl; + + @Resource + private MqttConfig.MqttMessageSender mqttMessageSender; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + public void checkTempStatus() { + + Boolean lockSuccess = stringRedisTemplate.opsForValue() + .setIfAbsent(LOCK_KEY, "agriTempTask", lockTtl, TimeUnit.SECONDS); + // 补充:处理Redis连接异常的情况 + if (lockSuccess == null) { + log.error("获取分布式锁失败:Redis连接异常"); + return; + } + if (!lockSuccess) { + log.debug("其他节点正在执行,跳过本次推送"); + return; + } + try { + + // 查询大棚所有imei + List imeiList = agriInfoService.queryImeiByUserId(null); + if (imeiList.isEmpty()) { + log.info("大棚表无数据,结束推送"); + return; + } + // 查询所有设备最新的温湿度数据 + List> dtuDataList = dtuDataService.getLastDtuDataByImeiList(imeiList); + if (CollectionUtils.isEmpty(dtuDataList)) return; + // 判断谁不存在 + ArrayList offlineTempList = new ArrayList<>(); + for (String imei : imeiList) { + if (dtuDataList.stream().noneMatch(item -> item.get("imei").equals(imei))) { + offlineTempList.add(imei); + log.info("设备{} 不存在温湿度数据", imei); + } + } + // 不存在的告警 + for (String imei : offlineTempList) { + // todo 设备离线推送 发消息提醒 + Map alarmMsg = new HashMap<>(); + alarmMsg.put("online", "温度离线"); + alarmMsg.put("time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + alarmMsg.put("imei", imei); + String alarmMessage = objectMapper.writeValueAsString(alarmMsg); + mqttMessageSender.publish("frontend/" + imei + "/alarm", alarmMessage); + } + } catch (Exception e) { + log.error("设备在线状态推送任务异常", e); + // 可选:异常告警(如企业微信/钉钉) + // WxUtil.pushText("【设备在线状态推送异常】\n" + e.getMessage()); + } finally { + // 释放锁(可选,也可依赖TTL自动过期) + stringRedisTemplate.delete(LOCK_KEY); + } + + + } +} diff --git a/agri-system/src/main/resources/mapper/system/SysDtuDataMapper.xml b/agri-system/src/main/resources/mapper/system/SysDtuDataMapper.xml index db9c72b..29d6dc7 100644 --- a/agri-system/src/main/resources/mapper/system/SysDtuDataMapper.xml +++ b/agri-system/src/main/resources/mapper/system/SysDtuDataMapper.xml @@ -148,7 +148,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{imei} - AND time >= DATE_SUB(NOW(), INTERVAL 1 MINUTE) + AND time >= DATE_SUB(NOW(), INTERVAL 90 SECOND) GROUP BY imei )