|
|
@@ -1,36 +1,79 @@
|
|
|
package com.zksy.manhole.utils;
|
|
|
|
|
|
-import com.zksy.manhole.service.BaseDevicesManholeService;
|
|
|
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.http.HttpEntity;
|
|
|
+import org.springframework.http.HttpHeaders;
|
|
|
+import org.springframework.http.MediaType;
|
|
|
import org.springframework.scheduling.annotation.Scheduled;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.web.client.RestTemplate;
|
|
|
|
|
|
import java.util.Date;
|
|
|
-import java.util.HashMap;
|
|
|
import java.util.Map;
|
|
|
+import java.util.Set;
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
|
+/**
|
|
|
+ * 设备离线检测定时任务
|
|
|
+ * 通过 REST API 更新设备在线状态
|
|
|
+ */
|
|
|
@Component
|
|
|
public class DeviceOfflineCheckTask {
|
|
|
private static final Logger logger = LoggerFactory.getLogger(DeviceOfflineCheckTask.class);
|
|
|
|
|
|
- // 用于存储设备编号及其最后一次接收数据的时间
|
|
|
- public static Map<String, Date> deviceLastReceiveTimeMap = new HashMap<>();
|
|
|
+ /** 设备最后接收数据时间 */
|
|
|
+ public static ConcurrentHashMap<String, Date> deviceLastReceiveTimeMap = new ConcurrentHashMap<>();
|
|
|
+
|
|
|
+ /** 已知离线设备集合,用于避免重复API调用 */
|
|
|
+ private final Set<String> offlineDeviceSet = ConcurrentHashMap.newKeySet();
|
|
|
+
|
|
|
@Autowired
|
|
|
- private BaseDevicesManholeService baseDevicesService;
|
|
|
+ private RestTemplate restTemplate;
|
|
|
+
|
|
|
+ /** 离线判定超时,单位:分钟,默认30分钟 */
|
|
|
+ @Value("${device.offline.timeout-minutes:30}")
|
|
|
+ private int offlineTimeoutMinutes;
|
|
|
|
|
|
- // 定时检查设备是否离线
|
|
|
- @Scheduled(fixedRate = 24 * 60 * 60 * 1000) // 每24小时执行一次
|
|
|
+ /** 检查间隔,单位:毫秒,默认5分钟 */
|
|
|
+ @Scheduled(fixedRateString = "${device.offline.check-interval-ms:300000}")
|
|
|
public void checkDeviceOffline() {
|
|
|
Date now = new Date();
|
|
|
+ long timeoutMs = (long) offlineTimeoutMinutes * 60 * 1000;
|
|
|
for (Map.Entry<String, Date> entry : deviceLastReceiveTimeMap.entrySet()) {
|
|
|
long diff = now.getTime() - entry.getValue().getTime();
|
|
|
- // 如果设备在 23 小时内没有接收数据,则认为设备离线
|
|
|
- if (diff > 23 * 60 * 60 * 1000) {
|
|
|
- baseDevicesService.getByDeviceNumberStatus(entry.getKey(), 1, 0);
|
|
|
- logger.info("设备 {} 已离线", entry.getKey());
|
|
|
+ if (diff > timeoutMs) {
|
|
|
+ // 只在设备不在离线集合中时才调用API
|
|
|
+ if (offlineDeviceSet.add(entry.getKey())) {
|
|
|
+ updateDeviceOnlineStatus(entry.getKey(), 0);
|
|
|
+ logger.info("设备 {} 已离线(超过{}分钟未收到数据)", entry.getKey(), offlineTimeoutMinutes);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 标记设备在线(收到数据时调用)
|
|
|
+ * 只在设备当前处于离线状态时才调用API
|
|
|
+ */
|
|
|
+ public void markDeviceOnline(String deviceCode) {
|
|
|
+ if (offlineDeviceSet.remove(deviceCode)) {
|
|
|
+ updateDeviceOnlineStatus(deviceCode, 1);
|
|
|
+ logger.info("设备 {} 恢复在线", deviceCode);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateDeviceOnlineStatus(String deviceCode, int onlineStatus) {
|
|
|
+ try {
|
|
|
+ Map<String, Object> params = Map.of("deviceCode", deviceCode, "onlineStatus", onlineStatus);
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.setContentType(MediaType.APPLICATION_JSON);
|
|
|
+ HttpEntity<Map<String, Object>> request = new HttpEntity<>(params, headers);
|
|
|
+ restTemplate.postForObject("http://zk-api-service/equipmentStatus/updateOnlineStatus", request, Map.class);
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("更新设备在线状态失败: deviceCode={}, onlineStatus={}", deviceCode, onlineStatus, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|