定时清理,自动化修改、自动化误差上下温度改为0.5

master
lld 2026-03-24 19:22:47 +08:00
parent 1d6d86b9d2
commit ecb83531e8
5 changed files with 28 additions and 42 deletions

View File

@ -9,7 +9,7 @@ import java.math.BigDecimal;
*/ */
public class TempJudgeUtil { public class TempJudgeUtil {
// 条件参考温度允许的上下误差(抽成常量,后续可配置化) // 条件参考温度允许的上下误差(抽成常量,后续可配置化)
public static final BigDecimal TEMP_ERROR_RANGE = java.math.BigDecimal.ONE; public static final BigDecimal TEMP_ERROR_RANGE = BigDecimal.valueOf(0.5);
/** /**
* *

View File

@ -82,7 +82,6 @@ public class AgriStatusTask {
log.info("大棚表无数据,结束推送"); log.info("大棚表无数据,结束推送");
return; return;
} }
log.info("从大棚表获取到合法IMEI总数{}", imeiList.size());
// 3. 批量查询设备在线状态Redis Pipeline一次网络往返 // 3. 批量查询设备在线状态Redis Pipeline一次网络往返
agriStatusManager.asyncBatchPushMqtt(agriStatusManager.batchCheckDeviceOnline(imeiList)); agriStatusManager.asyncBatchPushMqtt(agriStatusManager.batchCheckDeviceOnline(imeiList));
@ -93,7 +92,6 @@ public class AgriStatusTask {
} finally { } finally {
// 释放锁可选也可依赖TTL自动过期 // 释放锁可选也可依赖TTL自动过期
stringRedisTemplate.delete(LOCK_KEY); stringRedisTemplate.delete(LOCK_KEY);
log.info("设备在线状态推送任务完成,耗时:{}ms", System.currentTimeMillis() - startTime);
} }
} }
@ -148,9 +146,6 @@ public class AgriStatusTask {
} }
} }
log.info("Lua查询完成合法IMEI数={},在线数={}",
allGreenhouseImeiList.size(),
onlineStatusMap.values().stream().filter(Boolean::booleanValue).count());
return onlineStatusMap; return onlineStatusMap;
} catch (Exception e) { } catch (Exception e) {
log.error("Lua脚本执行失败", e); log.error("Lua脚本执行失败", e);

View File

@ -1,71 +1,50 @@
package com.agri.quartz.task; package com.agri.quartz.task;
import com.agri.common.utils.spring.SpringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions; import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/**
* JDK 8 Redis
* 1. RedisTemplate 2. Cursor<byte[]> 3.
* Redis sub:
*/
@Component("agriTask") @Component("agriTask")
public class AgriTask { public class AgriTask {
// 核心修复:指定注入的 Bean 名称为 "redisTemplate"(匹配自定义配置的 Bean
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static final Logger log = LoggerFactory.getLogger(AgriTask.class); private static final Logger log = LoggerFactory.getLogger(AgriTask.class);
/**
* sub: Redis
*/
public void clearInvalidCache() { public void clearInvalidCache() {
log.info("===== 开始执行Redis sub: 键清理任务 ====="); log.info("=============【定时任务】开始执行Redis sub: 键清理任务=============");
int deletedCount = 0; int deletedCount = 0;
// 兜底获取 RedisTemplate指定 Bean 名称,解决多实例冲突) try {
// 重点*****
RedisTemplate<String, Object> redisTemplate = SpringUtils.getBean("redisTemplate");
if (redisTemplate == null) { if (redisTemplate == null) {
log.error("RedisTemplate 初始化失败,清理任务终止"); log.error("RedisTemplate 获取失败,清理任务终止");
return; return;
} }
try {
// 配置 SCAN 参数:匹配 sub:*分批遍历每次1000条
ScanOptions scanOptions = ScanOptions.scanOptions() ScanOptions scanOptions = ScanOptions.scanOptions()
.match("sub:*") .match("sub:*")
.count(1000) .count(1000)
.build(); .build();
// 接收 Cursor<byte[]> 类型JDK 8 下原生返回类型)
Cursor<byte[]> cursor = redisTemplate.executeWithStickyConnection(connection -> Cursor<byte[]> cursor = redisTemplate.executeWithStickyConnection(connection ->
connection.scan(scanOptions) connection.scan(scanOptions)
); );
// 批量删除缓冲区(存储 String 类型键)
List<String> batchKeys = new ArrayList<>(1000); List<String> batchKeys = new ArrayList<>(1000);
// 遍历字节数组类型的键,转换为 String
while (cursor != null && cursor.hasNext()) { while (cursor != null && cursor.hasNext()) {
byte[] keyBytes = cursor.next(); byte[] keyBytes = cursor.next();
// 转换 byte[] -> StringUTF-8 编码,避免乱码)
String key = new String(keyBytes, StandardCharsets.UTF_8); String key = new String(keyBytes, StandardCharsets.UTF_8);
batchKeys.add(key); batchKeys.add(key);
// 每攒1000个键批量删除
if (batchKeys.size() >= 1000) { if (batchKeys.size() >= 1000) {
deletedCount += batchKeys.size(); deletedCount += batchKeys.size();
redisTemplate.delete(batchKeys); redisTemplate.delete(batchKeys);
@ -74,14 +53,12 @@ public class AgriTask {
} }
} }
// 删除剩余的键
if (!batchKeys.isEmpty()) { if (!batchKeys.isEmpty()) {
deletedCount += batchKeys.size(); deletedCount += batchKeys.size();
redisTemplate.delete(batchKeys); redisTemplate.delete(batchKeys);
log.info("批量删除剩余 {} 个sub: 键", batchKeys.size()); log.info("批量删除剩余 {} 个sub: 键", batchKeys.size());
} }
// 关闭游标(避免资源泄漏)
if (cursor != null) { if (cursor != null) {
try { try {
cursor.close(); cursor.close();
@ -90,11 +67,10 @@ public class AgriTask {
} }
} }
log.info("===== Redis sub: 键清理完成,总计删除 {} 个键 =====", deletedCount); log.info("=============【定时任务】Redis sub: 键清理完成,总计删除 {} 个键=============", deletedCount);
} catch (Exception e) { } catch (Exception e) {
log.error("Redis sub: 键清理失败", e); log.error("=============【定时任务】Redis sub: 键清理失败=============", e);
} }
} }
} }

View File

@ -370,7 +370,7 @@ public class RollerAutoTask {
// ========== 4. 计算运行时间并调度自动关 ========== // ========== 4. 计算运行时间并调度自动关 ==========
int runTime = RollerTimeCalculator.calculateRunTime(len); int runTime = RollerTimeCalculator.calculateRunTime(len);
if (runTime > 0) { if (runTime > 0) {
String autoOffKey = roller + (isOpen ? "k" : "g"); String autoOffKey = roller + (isOpen ? "k1" : "g1");
autoOffManager.scheduleAutoOff(imei, autoOffKey, runTime); autoOffManager.scheduleAutoOff(imei, autoOffKey, runTime);
log.debug("【自动关调度】设备{}卷膜「{}:{}」调度{}秒后自动关闭", imei, roller,(isOpen?"开":"关"), runTime); log.debug("【自动关调度】设备{}卷膜「{}:{}」调度{}秒后自动关闭", imei, roller,(isOpen?"开":"关"), runTime);
} }

View File

@ -142,4 +142,19 @@ public class SysAgriInfoController extends BaseController
.update(); .update();
return success(); return success();
} }
/**
*
*/
@PreAuthorize("@ss.hasPermi('assets:agri:edit')")
@Log(title = "大棚管理", businessType = BusinessType.UPDATE)
@PutMapping("/renameAgriName")
public AjaxResult renameAgriName(@RequestParam("imei") String imei, @RequestParam("newAgriName") String newAgriName)
{
boolean update = sysAgriInfoService.lambdaUpdate()
.eq(SysAgriInfo::getImei, imei)
.set(SysAgriInfo::getAgriName, newAgriName)
.update();
return update? success():error();
}
} }