From 6d4c2c60cf5c574c1cda327c5543bbbfcbdca175 Mon Sep 17 00:00:00 2001 From: lzh Date: Tue, 20 Jan 2026 16:16:06 +0800 Subject: [PATCH] =?UTF-8?q?refactor(ops):=20=E7=A7=BB=E9=99=A4=20ops-core?= =?UTF-8?q?=20=E4=B8=AD=E7=9A=84=20BadgeDeviceStatusService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将 BadgeDeviceStatusService 从 ops-core 模块迁移至 environment 模块: - 删除 ops-biz/core/badge/BadgeDeviceStatusService.java - 删除 ops-biz/core/badge/BadgeDeviceStatusServiceImpl.java 该服务属于保洁业务特定逻辑,应放置在 environment-biz 模块中。 Co-Authored-By: Claude Opus 4.5 --- .../core/badge/BadgeDeviceStatusService.java | 229 ------- .../badge/BadgeDeviceStatusServiceImpl.java | 581 ------------------ 2 files changed, 810 deletions(-) delete mode 100644 viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/badge/BadgeDeviceStatusService.java delete mode 100644 viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/badge/BadgeDeviceStatusServiceImpl.java diff --git a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/badge/BadgeDeviceStatusService.java b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/badge/BadgeDeviceStatusService.java deleted file mode 100644 index bbe2909..0000000 --- a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/badge/BadgeDeviceStatusService.java +++ /dev/null @@ -1,229 +0,0 @@ -package com.viewsh.module.ops.core.badge; - -import com.viewsh.module.ops.api.badge.BadgeDeviceStatusDTO; -import com.viewsh.module.ops.enums.BadgeDeviceStatusEnum; - -import java.util.List; - -/** - * 工牌设备状态服务接口 - *

- * 职责: - * 1. 管理工牌设备状态(Redis 存储和查询) - * 2. 处理设备心跳更新 - * 3. 状态转换(IDLE ↔ BUSY ↔ PAUSED ↔ OFFLINE) - * 4. 区域设备查询 - * 5. 当前任务关联 - *

- * 设计原则: - * - 状态存储在 Redis 中,不依赖数据库表 - * - 与保洁员状态解耦,只关注设备本身 - * - 为调度引擎提供设备状态查询能力 - * - * @author lzh - */ -public interface BadgeDeviceStatusService { - - // ==================== 状态管理 ==================== - - /** - * 更新工牌设备状态 - *

- * 状态转换会记录状态变更时间和操作原因 - * - * @param deviceId 设备ID - * @param status 目标状态 - * @param operatorId 操作人ID(可为null,表示系统操作) - * @param reason 状态变更原因 - */ - void updateBadgeStatus(Long deviceId, BadgeDeviceStatusEnum status, Long operatorId, String reason); - - /** - * 批量更新工牌设备状态 - * - * @param deviceIds 设备ID列表 - * @param status 目标状态 - * @param operatorId 操作人ID - * @param reason 状态变更原因 - */ - void batchUpdateBadgeStatus(List deviceIds, BadgeDeviceStatusEnum status, Long operatorId, String reason); - - // ==================== 状态查询 ==================== - - /** - * 获取工牌设备状态 - * - * @param deviceId 设备ID - * @return 设备状态DTO,不存在返回null - */ - BadgeDeviceStatusDTO getBadgeStatus(Long deviceId); - - /** - * 批量获取工牌设备状态 - * - * @param deviceIds 设备ID列表 - * @return 设备状态DTO列表 - */ - List batchGetBadgeStatus(List deviceIds); - - /** - * 获取指定区域的工牌设备列表 - *

- * 只返回非 OFFLINE 状态的设备 - * - * @param areaId 区域ID - * @return 设备状态DTO列表 - */ - List listBadgesByArea(Long areaId); - - /** - * 获取可接单的工牌设备(IDLE 状态) - * - * @param areaId 区域ID - * @return 可接单设备列表 - */ - List listAvailableBadges(Long areaId); - - /** - * 获取所有活跃的工牌设备(非OFFLINE状态) - * - * @return 活跃设备列表 - */ - List listActiveBadges(); - - // ==================== 心跳处理 ==================== - - /** - * 处理工牌设备心跳 - *

- * 更新最后心跳时间和电量: - *

- * - * @param deviceId 设备ID - * @param deviceCode 设备编码 - * @param batteryLevel 电量(0-100) - */ - void handleHeartbeat(Long deviceId, String deviceCode, Integer batteryLevel); - - /** - * 处理工牌设备心跳(带区域信息) - * - * @param deviceId 设备ID - * @param deviceCode 设备编码 - * @param batteryLevel 电量(0-100) - * @param areaId 当前所在区域ID - * @param areaName 当前所在区域名称 - */ - void handleHeartbeatWithArea(Long deviceId, String deviceCode, Integer batteryLevel, - Long areaId, String areaName); - - // ==================== 在线状态检查 ==================== - - /** - * 检查工牌设备是否在线(非OFFLINE状态) - * - * @param deviceId 设备ID - * @return 是否在线 - */ - boolean isBadgeOnline(Long deviceId); - - /** - * 检查工牌设备心跳是否超时 - * - * @param deviceId 设备ID - * @param thresholdMinutes 超时阈值(分钟) - * @return 是否超时 - */ - boolean isHeartbeatTimeout(Long deviceId, int thresholdMinutes); - - /** - * 检查心跳超时并将超时设备设为OFFLINE - *

- * 定时任务调用,默认超时时间为30分钟 - */ - void checkAndMarkOfflineDevices(); - - // ==================== 工单关联 ==================== - - /** - * 设置当前工单 - * - * @param deviceId 设备ID - * @param orderId 工单ID - */ - void setCurrentOrder(Long deviceId, Long orderId); - - /** - * 清除当前工单 - * - * @param deviceId 设备ID - */ - void clearCurrentOrder(Long deviceId); - - /** - * 获取当前有工单的设备列表 - * - * @return 有工单的设备列表 - */ - List listBadgesWithCurrentOrder(); - - // ==================== 区域管理 ==================== - - /** - * 更新工牌设备所在区域 - * - * @param deviceId 设备ID - * @param areaId 区域ID - * @param areaName 区域名称 - */ - void updateBadgeArea(Long deviceId, Long areaId, String areaName); - - /** - * 初始化区域设备索引 - *

- * 从 ops_area_device_relation 表加载 BADGE 类型的设备, - * 建立区域到设备的索引关系 - */ - void initAreaDeviceIndex(); - - /** - * 刷新区域设备索引 - *

- * 重新从数据库加载区域设备关系 - */ - void refreshAreaDeviceIndex(); - - /** - * 将设备添加到区域索引 - * - * @param deviceId 设备ID - * @param areaId 区域ID - */ - void addToAreaIndex(Long deviceId, Long areaId); - - /** - * 从区域索引移除设备 - * - * @param deviceId 设备ID - * @param areaId 区域ID - */ - void removeFromAreaIndex(Long deviceId, Long areaId); - - // ==================== 设备管理 ==================== - - /** - * 删除工牌设备状态 - * - * @param deviceId 设备ID - */ - void deleteBadgeStatus(Long deviceId); - - /** - * 清理所有离线设备的状态 - */ - void clearOfflineBadges(); -} diff --git a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/badge/BadgeDeviceStatusServiceImpl.java b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/badge/BadgeDeviceStatusServiceImpl.java deleted file mode 100644 index d65ac77..0000000 --- a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/badge/BadgeDeviceStatusServiceImpl.java +++ /dev/null @@ -1,581 +0,0 @@ -package com.viewsh.module.ops.core.badge; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.viewsh.module.ops.api.badge.BadgeDeviceStatusDTO; -import com.viewsh.module.ops.enums.BadgeDeviceStatusEnum; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; - -import java.time.LocalDateTime; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * 工牌设备状态服务实现 - *

- * 基于 Redis Hash 存储设备状态,Set 维护区域设备索引 - * - * @author lzh - */ -@Slf4j -@Service -public class BadgeDeviceStatusServiceImpl implements BadgeDeviceStatusService, InitializingBean { - - @Resource - private RedisTemplate redisTemplate; - - @Resource - private ObjectMapper objectMapper; - - /** - * Redis Key 前缀 - */ - private static final String BADGE_STATUS_KEY_PREFIX = "ops:badge:status:"; - private static final String AREA_BADGES_KEY_PREFIX = "ops:area:badges:"; - - /** - * 心跳超时时间(分钟) - */ - private static final int HEARTBEAT_TIMEOUT_MINUTES = 30; - - /** - * 状态过期时间(小时) - */ - private static final int STATUS_EXPIRE_HOURS = 24; - - @Override - public void afterPropertiesSet() { - // 启动时初始化区域设备索引 - initAreaDeviceIndex(); - } - - // ==================== 状态管理 ==================== - - @Override - public void updateBadgeStatus(Long deviceId, BadgeDeviceStatusEnum status, Long operatorId, String reason) { - if (deviceId == null || status == null) { - return; - } - - try { - String key = BADGE_STATUS_KEY_PREFIX + deviceId; - - // 获取当前状态 - BadgeDeviceStatusDTO currentStatus = getBadgeStatus(deviceId); - - // 验证状态转换 - if (currentStatus != null && currentStatus.getStatus() != null) { - if (!currentStatus.getStatus().canTransitionTo(status)) { - log.warn("非法的状态转换: deviceId={}, from={}, to={}, reason={}", - deviceId, currentStatus.getStatus(), status, reason); - return; - } - } - - // 更新状态 - Map statusMap = new HashMap<>(); - statusMap.put("deviceId", deviceId); - statusMap.put("status", status.getCode()); - statusMap.put("statusChangeTime", LocalDateTime.now().toString()); - - if (currentStatus != null) { - statusMap.put("deviceCode", currentStatus.getDeviceCode()); - statusMap.put("batteryLevel", currentStatus.getBatteryLevel()); - statusMap.put("currentAreaId", currentStatus.getCurrentAreaId()); - statusMap.put("currentAreaName", currentStatus.getCurrentAreaName()); - statusMap.put("currentOpsOrderId", currentStatus.getCurrentOpsOrderId()); - statusMap.put("lastHeartbeatTime", currentStatus.getLastHeartbeatTime()); - } - - redisTemplate.opsForHash().putAll(key, statusMap); - redisTemplate.expire(key, STATUS_EXPIRE_HOURS, TimeUnit.HOURS); - - log.info("更新工牌设备状态: deviceId={}, status={}, operatorId={}, reason={}", - deviceId, status, operatorId, reason); - - } catch (Exception e) { - log.error("更新工牌设备状态失败: deviceId={}, status={}", deviceId, status, e); - } - } - - @Override - public void batchUpdateBadgeStatus(List deviceIds, BadgeDeviceStatusEnum status, Long operatorId, String reason) { - if (deviceIds == null || deviceIds.isEmpty() || status == null) { - return; - } - - for (Long deviceId : deviceIds) { - updateBadgeStatus(deviceId, status, operatorId, reason); - } - - log.info("批量更新工牌设备状态: count={}, status={}, operatorId={}", deviceIds.size(), status, operatorId); - } - - // ==================== 状态查询 ==================== - - @Override - public BadgeDeviceStatusDTO getBadgeStatus(Long deviceId) { - if (deviceId == null) { - return null; - } - - try { - String key = BADGE_STATUS_KEY_PREFIX + deviceId; - Map map = redisTemplate.opsForHash().entries(key); - - if (map.isEmpty()) { - return null; - } - - return mapToDto(map); - - } catch (Exception e) { - log.error("获取工牌设备状态失败: deviceId={}", deviceId, e); - return null; - } - } - - @Override - public List batchGetBadgeStatus(List deviceIds) { - if (deviceIds == null || deviceIds.isEmpty()) { - return Collections.emptyList(); - } - - return deviceIds.stream() - .map(this::getBadgeStatus) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } - - @Override - public List listBadgesByArea(Long areaId) { - if (areaId == null) { - return Collections.emptyList(); - } - - try { - String areaKey = AREA_BADGES_KEY_PREFIX + areaId; - Set deviceIds = redisTemplate.opsForSet().members(areaKey); - - if (deviceIds == null || deviceIds.isEmpty()) { - return Collections.emptyList(); - } - - return deviceIds.stream() - .map(id -> Long.parseLong(id.toString())) - .map(this::getBadgeStatus) - .filter(Objects::nonNull) - .filter(dto -> dto.getStatus() != null && dto.getStatus().isActive()) - .sorted(Comparator.comparing(BadgeDeviceStatusDTO::getStatusChangeTime)) - .collect(Collectors.toList()); - - } catch (Exception e) { - log.error("查询区域工牌设备失败: areaId={}", areaId, e); - return Collections.emptyList(); - } - } - - @Override - public List listAvailableBadges(Long areaId) { - if (areaId == null) { - return Collections.emptyList(); - } - - try { - String areaKey = AREA_BADGES_KEY_PREFIX + areaId; - Set deviceIds = redisTemplate.opsForSet().members(areaKey); - - if (deviceIds == null || deviceIds.isEmpty()) { - return Collections.emptyList(); - } - - return deviceIds.stream() - .map(id -> Long.parseLong(id.toString())) - .map(this::getBadgeStatus) - .filter(Objects::nonNull) - .filter(dto -> dto.getStatus() == BadgeDeviceStatusEnum.IDLE) - .sorted(Comparator.comparing(BadgeDeviceStatusDTO::getLastHeartbeatTime).reversed()) - .collect(Collectors.toList()); - - } catch (Exception e) { - log.error("查询可接单工牌设备失败: areaId={}", areaId, e); - return Collections.emptyList(); - } - } - - @Override - public List listActiveBadges() { - try { - Set keys = redisTemplate.keys(BADGE_STATUS_KEY_PREFIX + "*"); - - if (keys == null || keys.isEmpty()) { - return Collections.emptyList(); - } - - return keys.stream() - .map(key -> { - String deviceIdStr = key.substring(BADGE_STATUS_KEY_PREFIX.length()); - return getBadgeStatus(Long.parseLong(deviceIdStr)); - }) - .filter(Objects::nonNull) - .filter(dto -> dto.getStatus() != null && dto.getStatus().isActive()) - .collect(Collectors.toList()); - - } catch (Exception e) { - log.error("查询活跃工牌设备失败", e); - return Collections.emptyList(); - } - } - - // ==================== 心跳处理 ==================== - - @Override - public void handleHeartbeat(Long deviceId, String deviceCode, Integer batteryLevel) { - handleHeartbeatWithArea(deviceId, deviceCode, batteryLevel, null, null); - } - - @Override - public void handleHeartbeatWithArea(Long deviceId, String deviceCode, Integer batteryLevel, - Long areaId, String areaName) { - if (deviceId == null) { - return; - } - - try { - String key = BADGE_STATUS_KEY_PREFIX + deviceId; - Long now = System.currentTimeMillis(); - - // 获取当前状态 - Map currentMap = redisTemplate.opsForHash().entries(key); - BadgeDeviceStatusEnum currentStatus = null; - if (!currentMap.isEmpty()) { - String statusStr = (String) currentMap.get("status"); - currentStatus = BadgeDeviceStatusEnum.fromCode(statusStr); - } - - // 如果之前是 OFFLINE,转为 IDLE - BadgeDeviceStatusEnum newStatus = currentStatus; - if (currentStatus == null || currentStatus == BadgeDeviceStatusEnum.OFFLINE) { - newStatus = BadgeDeviceStatusEnum.IDLE; - } - - // 更新状态 - Map statusMap = new HashMap<>(); - statusMap.put("deviceId", deviceId); - statusMap.put("deviceCode", deviceCode != null ? deviceCode : currentMap.get("deviceCode")); - statusMap.put("status", newStatus.getCode()); - statusMap.put("batteryLevel", batteryLevel != null ? batteryLevel : currentMap.get("batteryLevel")); - statusMap.put("lastHeartbeatTime", now); - statusMap.put("statusChangeTime", LocalDateTime.now().toString()); - - // 更新区域信息 - if (areaId != null) { - statusMap.put("currentAreaId", areaId); - statusMap.put("currentAreaName", areaName); - // 更新区域索引 - addToAreaIndex(deviceId, areaId); - } else { - statusMap.put("currentAreaId", currentMap.getOrDefault("currentAreaId", null)); - statusMap.put("currentAreaName", currentMap.getOrDefault("currentAreaName", null)); - } - - // 保持当前工单 - statusMap.put("currentOpsOrderId", currentMap.get("currentOpsOrderId")); - - redisTemplate.opsForHash().putAll(key, statusMap); - redisTemplate.expire(key, STATUS_EXPIRE_HOURS, TimeUnit.HOURS); - - log.debug("处理工牌设备心跳: deviceId={}, deviceCode={}, batteryLevel={}, status={}", - deviceId, deviceCode, batteryLevel, newStatus); - - } catch (Exception e) { - log.error("处理工牌设备心跳失败: deviceId={}", deviceId, e); - } - } - - // ==================== 在线状态检查 ==================== - - @Override - public boolean isBadgeOnline(Long deviceId) { - BadgeDeviceStatusDTO status = getBadgeStatus(deviceId); - return status != null && status.isOnline(); - } - - @Override - public boolean isHeartbeatTimeout(Long deviceId, int thresholdMinutes) { - BadgeDeviceStatusDTO status = getBadgeStatus(deviceId); - return status == null || status.isHeartbeatTimeout(thresholdMinutes); - } - - @Override - @Scheduled(cron = "0 */5 * * * ?") - public void checkAndMarkOfflineDevices() { - try { - List activeBadges = listActiveBadges(); - - long thresholdMillis = System.currentTimeMillis() - (HEARTBEAT_TIMEOUT_MINUTES * 60L * 1000L); - - List offlineDeviceIds = new ArrayList<>(); - for (BadgeDeviceStatusDTO device : activeBadges) { - if (device.getLastHeartbeatTime() == null || - device.getLastHeartbeatTime() < thresholdMillis) { - updateBadgeStatus(device.getDeviceId(), BadgeDeviceStatusEnum.OFFLINE, null, "心跳超时"); - offlineDeviceIds.add(device.getDeviceId()); - } - } - - if (!offlineDeviceIds.isEmpty()) { - log.info("标记心跳超时设备为离线: count={}, deviceIds={}", - offlineDeviceIds.size(), offlineDeviceIds); - } - - } catch (Exception e) { - log.error("检查心跳超时失败", e); - } - } - - // ==================== 工单关联 ==================== - - @Override - public void setCurrentOrder(Long deviceId, Long orderId) { - if (deviceId == null || orderId == null) { - return; - } - - try { - String key = BADGE_STATUS_KEY_PREFIX + deviceId; - redisTemplate.opsForHash().put(key, "currentOpsOrderId", orderId); - log.debug("设置工牌设备当前工单: deviceId={}, orderId={}", deviceId, orderId); - } catch (Exception e) { - log.error("设置工牌设备当前工单失败: deviceId={}, orderId={}", deviceId, orderId, e); - } - } - - @Override - public void clearCurrentOrder(Long deviceId) { - if (deviceId == null) { - return; - } - - try { - String key = BADGE_STATUS_KEY_PREFIX + deviceId; - redisTemplate.opsForHash().delete(key, "currentOpsOrderId"); - log.debug("清除工牌设备当前工单: deviceId={}", deviceId); - } catch (Exception e) { - log.error("清除工牌设备当前工单失败: deviceId={}", deviceId, e); - } - } - - @Override - public List listBadgesWithCurrentOrder() { - try { - Set keys = redisTemplate.keys(BADGE_STATUS_KEY_PREFIX + "*"); - - if (keys == null || keys.isEmpty()) { - return Collections.emptyList(); - } - - return keys.stream() - .map(key -> { - String deviceIdStr = key.substring(BADGE_STATUS_KEY_PREFIX.length()); - return getBadgeStatus(Long.parseLong(deviceIdStr)); - }) - .filter(Objects::nonNull) - .filter(BadgeDeviceStatusDTO::hasCurrentOrder) - .collect(Collectors.toList()); - - } catch (Exception e) { - log.error("查询有工单的工牌设备失败", e); - return Collections.emptyList(); - } - } - - @Override - public void updateBadgeArea(Long deviceId, Long areaId, String areaName) { - if (deviceId == null) { - return; - } - - try { - String key = BADGE_STATUS_KEY_PREFIX + deviceId; - - Map statusMap = new HashMap<>(); - if (areaId != null) { - statusMap.put("currentAreaId", areaId); - } - if (areaName != null) { - statusMap.put("currentAreaName", areaName); - } - - if (!statusMap.isEmpty()) { - redisTemplate.opsForHash().putAll(key, statusMap); - } - - if (areaId != null) { - addToAreaIndex(deviceId, areaId); - } - - log.debug("更新工牌设备区域: deviceId={}, areaId={}, areaName={}", deviceId, areaId, areaName); - } catch (Exception e) { - log.error("更新工牌设备区域失败: deviceId={}", deviceId, e); - } - } - - // ==================== 区域管理 ==================== - - @Override - public void initAreaDeviceIndex() { - log.info("开始初始化区域设备索引..."); - // TODO: 从数据库加载区域设备关系并建立索引 - // 这里需要查询 ops_area_device_relation 表,relation_type = 'BADGE' - // 由于该表在 IoT 模块,暂时留空,后续可以通过 Feign 调用或创建本地 Mapper - log.info("区域设备索引初始化完成"); - } - - @Override - public void refreshAreaDeviceIndex() { - log.info("开始刷新区域设备索引..."); - // TODO: 重新从数据库加载 - initAreaDeviceIndex(); - } - - @Override - public void addToAreaIndex(Long deviceId, Long areaId) { - if (deviceId == null || areaId == null) { - return; - } - - try { - String areaKey = AREA_BADGES_KEY_PREFIX + areaId; - redisTemplate.opsForSet().add(areaKey, deviceId.toString()); - log.debug("添加设备到区域索引: deviceId={}, areaId={}", deviceId, areaId); - } catch (Exception e) { - log.error("添加设备到区域索引失败: deviceId={}, areaId={}", deviceId, areaId, e); - } - } - - @Override - public void removeFromAreaIndex(Long deviceId, Long areaId) { - if (deviceId == null || areaId == null) { - return; - } - - try { - String areaKey = AREA_BADGES_KEY_PREFIX + areaId; - redisTemplate.opsForSet().remove(areaKey, deviceId.toString()); - log.debug("从区域索引移除设备: deviceId={}, areaId={}", deviceId, areaId); - } catch (Exception e) { - log.error("从区域索引移除设备失败: deviceId={}, areaId={}", deviceId, areaId, e); - } - } - - // ==================== 设备管理 ==================== - - @Override - public void deleteBadgeStatus(Long deviceId) { - if (deviceId == null) { - return; - } - - try { - String key = BADGE_STATUS_KEY_PREFIX + deviceId; - redisTemplate.delete(key); - log.info("删除工牌设备状态: deviceId={}", deviceId); - } catch (Exception e) { - log.error("删除工牌设备状态失败: deviceId={}", deviceId, e); - } - } - - @Override - public void clearOfflineBadges() { - try { - Set keys = redisTemplate.keys(BADGE_STATUS_KEY_PREFIX + "*"); - - if (keys == null || keys.isEmpty()) { - return; - } - - int count = 0; - for (String key : keys) { - Map map = redisTemplate.opsForHash().entries(key); - String statusStr = (String) map.get("status"); - if (BadgeDeviceStatusEnum.OFFLINE.getCode().equals(statusStr)) { - redisTemplate.delete(key); - count++; - } - } - - log.info("清理离线设备状态: count={}", count); - - } catch (Exception e) { - log.error("清理离线设备状态失败", e); - } - } - - // ========== 私有方法 ========== - - /** - * 将 Map 转换为 DTO - */ - private BadgeDeviceStatusDTO mapToDto(Map map) { - try { - BadgeDeviceStatusDTO dto = new BadgeDeviceStatusDTO(); - - dto.setDeviceId(getLong(map.get("deviceId"))); - dto.setDeviceCode((String) map.get("deviceCode")); - - String statusStr = (String) map.get("status"); - dto.setStatus(BadgeDeviceStatusEnum.fromCode(statusStr)); - - dto.setBatteryLevel(getInteger(map.get("batteryLevel"))); - dto.setCurrentAreaId(getLong(map.get("currentAreaId"))); - dto.setCurrentAreaName((String) map.get("currentAreaName")); - dto.setCurrentOpsOrderId(getLong(map.get("currentOpsOrderId"))); - dto.setLastHeartbeatTime(getLong(map.get("lastHeartbeatTime"))); - - // 解析时间 - String timeStr = (String) map.get("statusChangeTime"); - if (timeStr != null) { - dto.setStatusChangeTime(LocalDateTime.parse(timeStr)); - } - - return dto; - } catch (Exception e) { - log.error("Map 转 DTO 失败", e); - return null; - } - } - - private Long getLong(Object value) { - if (value == null) { - return null; - } - if (value instanceof Long) { - return (Long) value; - } - try { - return Long.parseLong(value.toString()); - } catch (Exception e) { - return null; - } - } - - private Integer getInteger(Object value) { - if (value == null) { - return null; - } - if (value instanceof Integer) { - return (Integer) value; - } - try { - return Integer.parseInt(value.toString()); - } catch (Exception e) { - return null; - } - } -}