package org.sxkj.common.cache; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.sxkj.common.enums.RefreshStatusEnum; import org.sxkj.common.func.Streams; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; /** * 比较前后状态是否一致 */ public class StatusCacheUtils { /** * 上一次获取的设备状态值缓存 * Key: 用户ID, Value: 设备状态列表 */ private static final ConcurrentHashMap> STATUS_CACHE = new ConcurrentHashMap<>(); /** * 检查间隔时间内设备状态是否变更 * * @param userId 用户ID * @param intervalTime 间隔时间(秒) * @param supplier 设备SN列表提供函数 * @return true-状态已变更需要处理, false-状态未变更 */ public static boolean intervalTimeStatusChange(Long userId, RefreshStatusEnum refreshStatusEnum, int intervalTime, Supplier> supplier) { if (Objects.isNull(userId)) { return false; } String unionKey = refreshStatusEnum.name() + userId; // 获取缓存中的设备状态 List cachedStatus = STATUS_CACHE.get(unionKey); // 检查是否需要刷新缓存 if (shouldRefreshCache(cachedStatus, intervalTime)) { cachedStatus = refreshStatusCache(userId, supplier, refreshStatusEnum); } // 无设备状态数据时直接返回false if (CollectionUtils.isEmpty(cachedStatus)) { return false; } // 获取当前设备状态 List sns = Streams.toList(cachedStatus, StatusBo::getKey); List currentStatus = getStatuses(sns, refreshStatusEnum); // 比较状态并更新缓存 boolean statusChanged = !compareStatus(cachedStatus, currentStatus); STATUS_CACHE.put(unionKey, currentStatus); return statusChanged; } /** * 判断是否需要刷新缓存 */ private static boolean shouldRefreshCache(List cachedStatus, int intervalTime) { if (CollectionUtils.isEmpty(cachedStatus)) { return true; } // 计算时间差(绝对值) long timeDiff = Math.abs(System.currentTimeMillis() - cachedStatus.get(0).getTime()); return timeDiff >= intervalTime * 2 * 1000L; } /** * 刷新设备状态缓存 * * @param userId * @param supplier * @param refreshStatusEnum * @return */ private static List refreshStatusCache(Long userId, Supplier> supplier , RefreshStatusEnum refreshStatusEnum) { // sns 要看 refreshStatusEnum 是设备的还是任务的,如果是设备的就是设备的sn 如果是任务就是当前用户的arecode 例如 36 List sns = supplier.get(); if (CollectionUtils.isEmpty(sns)) { return Collections.emptyList(); } List newStatus = getStatuses(sns, refreshStatusEnum); STATUS_CACHE.put(refreshStatusEnum.name() + userId, newStatus); return newStatus; } /** * 比较两个设备状态列表是否一致 */ private static boolean compareStatus(List before, List current) { if (before == current) return true; if (before == null || current == null) return false; if (before.size() != current.size()) return false; // 创建设备SN到状态码的映射 Map statusMap = Streams.toMap(before, StatusBo::getKey, StatusBo::getValue); // 比较每个设备的状态 return current.stream().allMatch(curr -> { String prevCode = statusMap.get(curr.getKey()); return Objects.equals(prevCode, curr.getValue()); }); } /** * 获取设备状态列表 */ private static List getStatuses(List sns, RefreshStatusEnum refreshStatusEnum) { long currentTime = System.currentTimeMillis(); return Streams.toList(sns, sn -> { StatusBo status = new StatusBo(); status.setKey(sn); String modelCode = CurrentCacheUtils.getValue(refreshStatusEnum + sn); status.setValue(StringUtils.isEmpty(modelCode) ? "-1" : modelCode); status.setTime(currentTime); return status; }); } /** * 清空状态缓存 */ public static void clearStatusCache() { STATUS_CACHE.clear(); } }