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<String, List<StatusBo>> 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<List<String>> supplier) {
|
if (Objects.isNull(userId)) {
|
return false;
|
}
|
String unionKey = refreshStatusEnum.name() + userId;
|
// 获取缓存中的设备状态
|
List<StatusBo> cachedStatus = STATUS_CACHE.get(unionKey);
|
|
// 检查是否需要刷新缓存
|
if (shouldRefreshCache(cachedStatus, intervalTime)) {
|
cachedStatus = refreshStatusCache(userId, supplier, refreshStatusEnum);
|
}
|
|
// 无设备状态数据时直接返回false
|
if (CollectionUtils.isEmpty(cachedStatus)) {
|
return false;
|
}
|
|
// 获取当前设备状态
|
List<String> sns = Streams.toList(cachedStatus, StatusBo::getKey);
|
List<StatusBo> currentStatus = getStatuses(sns, refreshStatusEnum);
|
// 比较状态并更新缓存
|
boolean statusChanged = !compareStatus(cachedStatus, currentStatus);
|
STATUS_CACHE.put(unionKey, currentStatus);
|
return statusChanged;
|
}
|
|
/**
|
* 判断是否需要刷新缓存
|
*/
|
private static boolean shouldRefreshCache(List<StatusBo> 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<StatusBo> refreshStatusCache(Long userId, Supplier<List<String>> supplier
|
, RefreshStatusEnum refreshStatusEnum) {
|
// sns 要看 refreshStatusEnum 是设备的还是任务的,如果是设备的就是设备的sn 如果是任务就是当前用户的arecode 例如 36
|
List<String> sns = supplier.get();
|
if (CollectionUtils.isEmpty(sns)) {
|
return Collections.emptyList();
|
}
|
|
List<StatusBo> newStatus = getStatuses(sns, refreshStatusEnum);
|
STATUS_CACHE.put(refreshStatusEnum.name() + userId, newStatus);
|
return newStatus;
|
}
|
|
/**
|
* 比较两个设备状态列表是否一致
|
*/
|
private static boolean compareStatus(List<StatusBo> before, List<StatusBo> current) {
|
if (before == current) return true;
|
if (before == null || current == null) return false;
|
if (before.size() != current.size()) return false;
|
|
// 创建设备SN到状态码的映射
|
Map<String, String> 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<StatusBo> getStatuses(List<String> 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();
|
}
|
|
}
|