package service import ( "time" "laic-backend/cache" "laic-backend/common" "laic-backend/logger" ) func heartbeatTimeout() uint { if common.AppConf != nil && common.AppConf.Heartbeat.TimeoutSeconds > 0 { return uint(common.AppConf.Heartbeat.TimeoutSeconds) } return 30 } func refreshDeviceHeartbeat(key string) { if err := common.SetValueWithExpired(key, "1", heartbeatTimeout()); err != nil { logger.WARN("刷新设备心跳失败:", err) } } func expireDeviceHeartbeats() { dockMembers, err := common.SetMembers(cache.OnlineDockSetKey) if err != nil { logger.WARN("扫描机巢在线状态失败:", err) } else { for _, dockID := range dockMembers { removed, e := common.SetRemoveIfKeyMissing(cache.OnlineDockSetKey, cache.DockHeartbeatKeyOf(dockID), dockID) if e != nil { logger.WARN("检查机巢心跳失败:", e) continue } if removed { markDockOffline(dockID) } } } droneMembers, err := common.SetMembers(cache.OnlineDroneSetKey) if err != nil { logger.WARN("扫描无人机在线状态失败:", err) return } for _, droneSN := range droneMembers { removed, e := common.SetRemoveIfKeyMissing(cache.OnlineDroneSetKey, cache.DroneHeartbeatKeyOf(droneSN), droneSN) if e != nil { logger.WARN("检查无人机心跳失败:", e) continue } if removed { markDroneOffline(droneSN) } } } func markDockOffline(dockID string) { broadcast("dock.status", map[string]any{"dockId": dockID, "online": false}) } func markDroneOffline(droneSN string) { broadcast("drone.status", map[string]any{"droneSn": droneSN, "online": false}) } func heartbeatScanInterval() time.Duration { if common.AppConf != nil && common.AppConf.Heartbeat.ScanSeconds > 0 { return time.Duration(common.AppConf.Heartbeat.ScanSeconds) * time.Second } return 5 * time.Second }