소스 검색

device redis缓存 改写

chejianzheng 3 달 전
부모
커밋
265586a3b0
18개의 변경된 파일1847개의 추가작업 그리고 2045개의 파일을 삭제
  1. 8 2
      device-service-application/src/main/java/com/hfln/device/application/service/impl/DeviceEventServiceImpl.java
  2. 5 0
      device-service-common/pom.xml
  3. 2 2
      device-service-common/src/main/java/com/hfln/device/common/constant/redis/RedisCacheConstant.java
  4. 4 4
      device-service-domain/pom.xml
  5. 0 118
      device-service-domain/src/main/java/com/hfln/device/domain/customer/util/MsgClient.java
  6. 1597 1597
      device-service-domain/src/main/java/com/hfln/device/domain/entity/DeviceCache.java
  7. 0 15
      device-service-domain/src/main/java/com/hfln/device/domain/gateway/sms/SmsGateway.java
  8. 8 0
      device-service-domain/src/main/java/com/hfln/device/domain/service/DeviceManagerService.java
  9. 1 1
      device-service-domain/src/main/java/com/hfln/device/domain/service/impl/DeviceManagerServiceImpl.java
  10. 138 32
      device-service-domain/src/main/java/com/hfln/device/domain/service/impl/DeviceRedisManagerServiceImpl.java
  11. 44 0
      device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/config/FastJson2JsonRedisSerializer.java
  12. 32 0
      device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/config/RedisConfig.java
  13. 0 204
      device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/gateway/impl/UserGatewayImpl.java
  14. 0 65
      device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/gateway/impl/sms/SmsGatewayImpl.java
  15. 2 2
      device-service-server/src/main/java/com/hfln/device/server/DeviceApplication.java
  16. 0 2
      device-service-server/src/main/resources/bootstrap-local.yml
  17. 1 1
      device-service-server/src/main/resources/bootstrap.yml
  18. 5 0
      pom.xml

+ 8 - 2
device-service-application/src/main/java/com/hfln/device/application/service/impl/DeviceEventServiceImpl.java

@@ -20,6 +20,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Collections;
@@ -44,7 +45,7 @@ public class DeviceEventServiceImpl implements DeviceEventService {
     @Autowired
     private MqttGateway mqttGateway;
 
-    @Autowired
+    @Resource(name = "deviceRedisManagerService")
     private DeviceManagerService deviceManagerService;
 
     @Autowired
@@ -248,7 +249,12 @@ public class DeviceEventServiceImpl implements DeviceEventService {
                     device.setKeepaliveTime(System.currentTimeMillis());
                     
                     // 更新设备缓存
-                    deviceManagerService.updateDeviceInCache(device);
+//                    deviceManagerService.updateDeviceInCache(device);
+
+                    Map<String, Object> updateDeviceMap = new HashMap<>();
+                    updateDeviceMap.put("online", 1);
+                    updateDeviceMap.put("keepAliveTime", System.currentTimeMillis());
+                    deviceManagerService.updateDeviceMapInCache(device.getDevId(), updateDeviceMap);
                     
                     log.info("设备重新上线: deviceId={}", deviceId);
                     

+ 5 - 0
device-service-common/pom.xml

@@ -57,6 +57,11 @@
             <artifactId>junit-jupiter-engine</artifactId>
             <scope>test</scope>
         </dependency>
+
+        <dependency>
+            <groupId>cn.hfln.framework</groupId>
+            <artifactId>redis-spring-boot-starter</artifactId>
+        </dependency>
     </dependencies>
 
 

+ 2 - 2
device-service-common/src/main/java/com/hfln/device/common/constant/redis/RedisCacheConstant.java

@@ -9,8 +9,8 @@ public interface RedisCacheConstant {
     /**
      * redis缓存设备 key
      */
-    String KEY_DEVICE = "hfln:device:";
-    String KEY_DEVICE_ID = "hfln:devid:";
+    String KEY_DEVICE_pre = "hfln:device:";
+    String KEY_DEVICE_ID = "hfln:device:id";
     String KEY_DEVICE_DEBUG_PARAM_PRE = "hfln:device:debugParam-";
 
 

+ 4 - 4
device-service-domain/pom.xml

@@ -17,10 +17,10 @@
             <groupId>com.hfln.device</groupId>
             <artifactId>device-service-client-starter</artifactId>
         </dependency>
-        <dependency>
-            <groupId>cn.hfln.framework</groupId>
-            <artifactId>hfln-framework-common</artifactId>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>cn.hfln.framework</groupId>-->
+<!--            <artifactId>hfln-framework-common</artifactId>-->
+<!--        </dependency>-->
 
         <dependency>
             <groupId>com.alibaba.fastjson2</groupId>

+ 0 - 118
device-service-domain/src/main/java/com/hfln/device/domain/customer/util/MsgClient.java

@@ -1,118 +0,0 @@
-package com.hfln.device.domain.customer.util;
-
-import cn.hfln.framework.extension.BizException;
-import com.tencentcloudapi.common.AbstractModel;
-import com.tencentcloudapi.common.Credential;
-import com.tencentcloudapi.common.profile.ClientProfile;
-import com.tencentcloudapi.sms.v20210111.SmsClient;
-import com.tencentcloudapi.sms.v20210111.models.*;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-import org.springframework.web.client.RestTemplate;
-
-import javax.validation.constraints.NotBlank;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-
-@Slf4j
-@Component
-public class MsgClient {
-
-	@Autowired
-	private RestTemplate restTemplate;
-
-	@NotBlank
-	@Value("${lnxx.sms.tencent.secretId}")
-	private String secretId;
-
-	@NotBlank
-	@Value("${lnxx.sms.tencent.secretKey}")
-	private String secretKey;
-
-	@NotBlank
-	@Value("${lnxx.sms.tencent.loginId}")
-	private String loginId;
-
-	@NotBlank
-	@Value("${lnxx.sms.tencent.registerId}")
-	private String registerId;
-
-	@NotBlank
-	@Value("${lnxx.sms.tencent.notifyId}")
-	private String notifyId;
-
-	@NotBlank
-	@Value("${lnxx.sms.tencent.sdkAppId}")
-	private String sdkAppId;
-
-	@NotBlank
-	@Value("${lnxx.sms.tencent.region}")
-	private String region;
-
-	public String sendMsg(String mobile, String content, String signName) {
-		if (isValidMobile(mobile)) {
-			return "手机号格式不正确";
-		}
-		if (StringUtils.isEmpty(signName)) {
-			signName = "安徽柒零玖";
-		}
-		try {
-			String encodedContent = URLEncoder.encode(content + "【" + signName + "】", "GB2312");
-			String url = String.format(
-					"https://mb345.com/ws/BatchSend2.aspx?CorpID=HFLKJ0006642&Pwd=zh9527@&Mobile=%s&Content=%s&Cell=&SendTime=",
-					mobile, encodedContent);
-
-			log.info("发送短信内容: {}", content);
-			return restTemplate.getForObject(url, String.class);
-
-		} catch (UnsupportedEncodingException e) {
-			log.error("短信内容编码失败", e);
-		} catch (Exception e) {
-			log.error("调用短信接口异常", e);
-		}
-		return "发送失败";
-	}
-
-	public String sendLoginMsg(String mobile, String captcha) {
-		return sendTencentMsg(mobile, loginId, new String[]{captcha, "5"});
-	}
-
-	public String sendRegisterMsg(String mobile, String captcha) {
-		return sendTencentMsg(mobile, registerId, new String[]{captcha});
-	}
-
-	public String sendNotifyMsg(String mobile, String devName) {
-		String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
-		String[] timeParts = nowTime.split("[- :]");
-		return sendTencentMsg(mobile, notifyId, new String[]{devName, timeParts[0], timeParts[1], timeParts[2], timeParts[3], timeParts[4], timeParts[5]});
-	}
-
-	private String sendTencentMsg(String mobile, String templateId, String[] templateParams) {
-		if (isValidMobile(mobile)) {
-			throw new BizException("手机号码格式有误");
-		}
-		try {
-			SmsClient client = new SmsClient(new Credential(secretId, secretKey), region, new ClientProfile());
-			SendSmsRequest req = new SendSmsRequest();
-			req.setPhoneNumberSet(new String[]{mobile});
-			req.setSignName("雷能守护小程序");
-			req.setTemplateId(templateId);
-			req.setTemplateParamSet(templateParams);
-			req.setSmsSdkAppId(sdkAppId);
-			SendSmsResponse resp = client.SendSms(req);
-			return AbstractModel.toJsonString(resp);
-		} catch (Exception e) {
-			log.error("发送腾讯云短信失败", e);
-		}
-		return null;
-	}
-
-	private boolean isValidMobile(String mobile) {
-		return mobile == null || !mobile.matches("^1[3-9]\\d{9}$");
-	}
-}

+ 1597 - 1597
device-service-domain/src/main/java/com/hfln/device/domain/entity/DeviceCache.java

@@ -1,1611 +1,1611 @@
-package com.hfln.device.domain.entity;
-
-import com.hfln.device.domain.vo.BehaviorPattern;
-import lombok.*;
-import org.springframework.util.CollectionUtils;
-
-import java.util.*;
-
-/**
- * 设备实体类 - 聚合根(Aggregate Root)
- *
- * 作为聚合根,Device 封装了设备相关的业务属性、行为和不变性,
- * 其生命周期内可包含多个子实体(如 Region)和值对象(如 InstallParam、TrackingRegion、NetworkInfo)。
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class DeviceCache {
-
-    /**
-     * 设备ID
-     */
-    private String devId;                // 设备ID
-    private String devType;              // 设备类型
-    private String software;             // 软件版本
-    private String hardware;             // 硬件版本
-    private String bluVer;               // 蓝牙版本
-
-//    private NetworkInfo network;         // 网络信息
-    private String ssid;             // WIFI SSID
-    private String password;         // WIFI 密码
-    private String ip;               // IP地址
-//    private InstallParam installParam;   // 安装参数
-private String mountPlain;       // 安装面
-    private Integer isCeiling;       // 是否天花板安装
-    private Float height;            // 安装高度
-//    private TrackingRegion trackingRegion; // 跟踪区域
-    private Integer startX;          // 起始X
-    private Integer startY;          // 起始Y
-    private Integer startZ;          // 起始Z
-    private Integer stopX;           // 终止X
-    private Integer stopY;           // 终止Y
-    private Integer stopZ;           // 终止Z
-
-    private List<Float> targets;         // 实时目标位置
-    //    private List<Integer> realtimePose;  // 实时姿态
-    //
-//    private Long enterTs;                // 进入时间戳
-//    private Long leaveTs;                // 离开时间戳
-//    private Long stayTime;               // 停留时间
-
-//    private Long retentionTime;          // 滞留时间
-//    private Long retentionKeepTime;      // 滞留保持时间
-//    private Long retentionAlarmTime;     // 滞留告警时间
-private Integer online;              // 在线状态:0-离线,1-在线
-
-    private Long keepaliveTime;          // 最后一次心跳时间
-    private Long expireTime;             // 超时时间(毫秒),默认90秒
-        private Boolean alarmAck;            // 告警确认
-        private Long lastAlarmAckTime;       // 最后告警确认时间
-    //
-    private Long lastReportFallTime;     // 最后上报跌倒时间
-//
-//    private String lastAlarmType;        // 最后一次告警类型
-//    private Long lastAlarmTime;          // 最后一次告警时间
-
-    // 跌倒状态记录 (对应Python版本的device.falling_)
-    private Integer falling_;            // 当前跌倒状态:0-无跌倒,1-检测到跌倒,2-跌倒确认,3-跌倒呼救
-
-    // 告警间隔相关属性 (参考Python版本)
-    private Long alarmInterval;          // 告警间隔时间(毫秒),默认30秒
-    private Long alarmAckInterval;       // 告警确认间隔时间(毫秒),默认5分钟
-
-    // 调试参数 (参考Python版本的g_dev_dbg_map)
-    private Map<String, Object> debugParams = new HashMap<>();
-
-//    // 姿态分析相关属性
-//    private PoseAnalysisResult lastPoseResult;  // 最近一次姿态分析结果
-//    private Long lastPoseChangeTime;            // 最近一次姿态变化时间
-//    private Map<Integer, Long> poseDurations;   // 各姿态持续时间(姿态ID -> 持续时间毫秒)
-//    private Map<Integer, Float> poseDistribution; // 姿态分布(姿态ID -> 占比百分比)
-
-//    // 行为分析相关属性
-//    private Long lastActivityDetectTime;        // 最近一次活动检测时间
-//    private Long lastRestTime;                  // 最近一次休息时间
-//    private Long lastFallTime;                  // 最近一次跌倒时间
-//    private Integer currentActivityLevel;       // 当前活动级别
-//    private Map<String, Long> areaRetentionTimes; // 各区域滞留时间(区域名称 -> 开始滞留时间毫秒)
-
-//    // 历史行为模式记录
-//    private final List<BehaviorPattern> behaviorHistory = new ArrayList<>();
-//
-//    // 告警历史记录
-//    private final List<Alarm> alarmHistory = new ArrayList<>();
-//
-//    // 设备最近的活动记录
-//    private final Map<String, Long> lastActivityTime = new HashMap<>();
-
-    // 每个事件类型的最后跌倒时间 (对应Python版本的last_fall_time_)
-    private final Map<String, Long> lastFallTimeByEvent = new HashMap<>();
-
-//    // 告警计划管理
-//    private Map<String, AlarmPlan> alarmPlanMap = new HashMap<>();
-//
-//    // 区域管理
-//    private List<Region> regions = new ArrayList<>();
-
-    // 完整的设备参数信息 (对应Python版本的param_)
-    private Map<String, Object> param = new HashMap<>();
-
-//    // 点云数据队列 (对应Python版本的put_cloud_points_que方法)
-//    private final Queue<List<List<Float>>> cloudPointsQueue = new LinkedList<>();
-//    private static final int MAX_CLOUD_POINTS_QUEUE_SIZE = 10; // 最大队列大小
-//
-//    private final ReentrantLock lock = new ReentrantLock();
-
-//    /**
-//     * 告警计划
-//     */
-//    private Map<String, Object> alarmSchedule;
-
-    /**
-     * 目标稳定器 - 对应Python版本的TargetStabilizer类
-     * 动态阈值调整的目标稳定算法
-     */
-//    private static class TargetStabilizer {
-//        private final java.util.Deque<List<Float>> targetList;
-//        private final float baseThreshold;
-//
-//        public TargetStabilizer(int queueLength, float baseThreshold) {
-//            this.targetList = new java.util.ArrayDeque<>(queueLength);
-//            this.baseThreshold = baseThreshold;
-//        }
+//package com.hfln.device.domain.entity;
+//
+//import com.hfln.device.domain.vo.BehaviorPattern;
+//import lombok.*;
+//import org.springframework.util.CollectionUtils;
+//
+//import java.util.*;
+//
+///**
+// * 设备实体类 - 聚合根(Aggregate Root)
+// *
+// * 作为聚合根,Device 封装了设备相关的业务属性、行为和不变性,
+// * 其生命周期内可包含多个子实体(如 Region)和值对象(如 InstallParam、TrackingRegion、NetworkInfo)。
+// */
+//@Getter
+//@Setter
+//@Builder
+//@NoArgsConstructor
+//@AllArgsConstructor
+//public class DeviceCache {
+//
+//    /**
+//     * 设备ID
+//     */
+//    private String devId;                // 设备ID
+//    private String devType;              // 设备类型
+//    private String software;             // 软件版本
+//    private String hardware;             // 硬件版本
+//    private String bluVer;               // 蓝牙版本
+//
+////    private NetworkInfo network;         // 网络信息
+//    private String ssid;             // WIFI SSID
+//    private String password;         // WIFI 密码
+//    private String ip;               // IP地址
+////    private InstallParam installParam;   // 安装参数
+//private String mountPlain;       // 安装面
+//    private Integer isCeiling;       // 是否天花板安装
+//    private Float height;            // 安装高度
+////    private TrackingRegion trackingRegion; // 跟踪区域
+//    private Integer startX;          // 起始X
+//    private Integer startY;          // 起始Y
+//    private Integer startZ;          // 起始Z
+//    private Integer stopX;           // 终止X
+//    private Integer stopY;           // 终止Y
+//    private Integer stopZ;           // 终止Z
+//
+//    private List<Float> targets;         // 实时目标位置
+//    //    private List<Integer> realtimePose;  // 实时姿态
+//    //
+////    private Long enterTs;                // 进入时间戳
+////    private Long leaveTs;                // 离开时间戳
+////    private Long stayTime;               // 停留时间
+//
+////    private Long retentionTime;          // 滞留时间
+////    private Long retentionKeepTime;      // 滞留保持时间
+////    private Long retentionAlarmTime;     // 滞留告警时间
+//private Integer online;              // 在线状态:0-离线,1-在线
+//
+//    private Long keepaliveTime;          // 最后一次心跳时间
+//    private Long expireTime;             // 超时时间(毫秒),默认90秒
+//        private Boolean alarmAck;            // 告警确认
+//        private Long lastAlarmAckTime;       // 最后告警确认时间
+//    //
+//    private Long lastReportFallTime;     // 最后上报跌倒时间
+////
+////    private String lastAlarmType;        // 最后一次告警类型
+////    private Long lastAlarmTime;          // 最后一次告警时间
+//
+//    // 跌倒状态记录 (对应Python版本的device.falling_)
+//    private Integer falling_;            // 当前跌倒状态:0-无跌倒,1-检测到跌倒,2-跌倒确认,3-跌倒呼救
+//
+//    // 告警间隔相关属性 (参考Python版本)
+//    private Long alarmInterval;          // 告警间隔时间(毫秒),默认30秒
+//    private Long alarmAckInterval;       // 告警确认间隔时间(毫秒),默认5分钟
+//
+//    // 调试参数 (参考Python版本的g_dev_dbg_map)
+//    private Map<String, Object> debugParams = new HashMap<>();
+//
+////    // 姿态分析相关属性
+////    private PoseAnalysisResult lastPoseResult;  // 最近一次姿态分析结果
+////    private Long lastPoseChangeTime;            // 最近一次姿态变化时间
+////    private Map<Integer, Long> poseDurations;   // 各姿态持续时间(姿态ID -> 持续时间毫秒)
+////    private Map<Integer, Float> poseDistribution; // 姿态分布(姿态ID -> 占比百分比)
+//
+////    // 行为分析相关属性
+////    private Long lastActivityDetectTime;        // 最近一次活动检测时间
+////    private Long lastRestTime;                  // 最近一次休息时间
+////    private Long lastFallTime;                  // 最近一次跌倒时间
+////    private Integer currentActivityLevel;       // 当前活动级别
+////    private Map<String, Long> areaRetentionTimes; // 各区域滞留时间(区域名称 -> 开始滞留时间毫秒)
+//
+////    // 历史行为模式记录
+////    private final List<BehaviorPattern> behaviorHistory = new ArrayList<>();
+////
+////    // 告警历史记录
+////    private final List<Alarm> alarmHistory = new ArrayList<>();
+////
+////    // 设备最近的活动记录
+////    private final Map<String, Long> lastActivityTime = new HashMap<>();
+//
+//    // 每个事件类型的最后跌倒时间 (对应Python版本的last_fall_time_)
+//    private final Map<String, Long> lastFallTimeByEvent = new HashMap<>();
+//
+////    // 告警计划管理
+////    private Map<String, AlarmPlan> alarmPlanMap = new HashMap<>();
+////
+////    // 区域管理
+////    private List<Region> regions = new ArrayList<>();
+//
+//    // 完整的设备参数信息 (对应Python版本的param_)
+//    private Map<String, Object> param = new HashMap<>();
+//
+////    // 点云数据队列 (对应Python版本的put_cloud_points_que方法)
+////    private final Queue<List<List<Float>>> cloudPointsQueue = new LinkedList<>();
+////    private static final int MAX_CLOUD_POINTS_QUEUE_SIZE = 10; // 最大队列大小
+////
+////    private final ReentrantLock lock = new ReentrantLock();
+//
+////    /**
+////     * 告警计划
+////     */
+////    private Map<String, Object> alarmSchedule;
+//
+//    /**
+//     * 目标稳定器 - 对应Python版本的TargetStabilizer类
+//     * 动态阈值调整的目标稳定算法
+//     */
+////    private static class TargetStabilizer {
+////        private final java.util.Deque<List<Float>> targetList;
+////        private final float baseThreshold;
+////
+////        public TargetStabilizer(int queueLength, float baseThreshold) {
+////            this.targetList = new java.util.ArrayDeque<>(queueLength);
+////            this.baseThreshold = baseThreshold;
+////        }
+////
+////        /**
+////         * 优化目标点 (对应Python版本的optimize_target方法)
+////         * @param newTarget 新接收到的目标点 [x, y, z, snr]
+////         * @return 优化后的目标点
+////         */
+////        public List<Float> optimizeTarget(List<Float> newTarget) {
+////            if (targetList.isEmpty()) {
+////                return new ArrayList<>(newTarget);
+////            }
+////
+////            // 计算队列中点的平均值 (对应Python版本的avg_x, avg_y, avg_z计算)
+////            float avgX = 0.0f, avgY = 0.0f, avgZ = 0.0f;
+////            for (List<Float> target : targetList) {
+////                avgX += target.get(0);
+////                avgY += target.get(1);
+////                avgZ += target.get(2);
+////            }
+////            avgX /= targetList.size();
+////            avgY /= targetList.size();
+////            avgZ /= targetList.size();
+////
+////            // 动态阈值调整 (对应Python版本的dynamic_threshold计算)
+////            float dx = newTarget.get(0) - avgX;
+////            float dy = newTarget.get(1) - avgY;
+////            float distanceToAvg = (float) Math.sqrt(dx * dx + dy * dy);
+////            float dynamicThreshold = baseThreshold + (distanceToAvg * 0.3f);
+////
+////            // 如果与均值的偏差超过动态阈值,则平滑处理 (对应Python版本的平滑逻辑)
+////            if (distanceToAvg > dynamicThreshold) {
+////                float smoothedX = (newTarget.get(0) + avgX) / 2.0f;
+////                float smoothedY = (newTarget.get(1) + avgY) / 2.0f;
+////                float smoothedZ = (newTarget.get(1) + avgZ) / 2.0f;  // 保持与Python版本完全一致,包括这个bug:使用newTarget.get(1)而不是get(2)
+////
+////                List<Float> optimizedTarget = new ArrayList<>();
+////                optimizedTarget.add(smoothedX);
+////                optimizedTarget.add(smoothedY);
+////                optimizedTarget.add(smoothedZ);
+////                return optimizedTarget;
+////            } else {
+////                return new ArrayList<>(newTarget);
+////            }
+////        }
+////
+////        /**
+////         * 更新目标列表 (对应Python版本的update_target_list方法)
+////         * @param newTarget 原始目标点 [x, y, z, snr]
+////         * @return 优化后的目标点
+////         */
+////        public List<Float> updateTargetList(List<Float> newTarget) {
+////            if (newTarget.size() < 3) {
+////                // 对应Python: LOGDBG(f"update_target_list error: invlid target:{new_target}")
+////                return new ArrayList<>(newTarget);
+////            }
+////
+////            List<Float> optimizedTarget = optimizeTarget(newTarget);
+////
+////            // 如果队列已满,移除最老的目标 (对应Python的deque maxlen行为)
+////            if (targetList.size() >= 10) {  // queueLength
+////                targetList.removeFirst();
+////            }
+////            targetList.addLast(optimizedTarget);
+////
+////            return optimizedTarget;
+////        }
+////    }
+////
+////    // 目标稳定器实例 (对应Python版本device中的stabilizer)
+////    private TargetStabilizer stabilizer = new TargetStabilizer(10, 1.0f);
+//
+//    /**
+//     * 构造函数,设置默认值
+//     * @param devId 设备ID
+//     */
+//    public DeviceCache(String devId) {
+//        this.devId = devId;
+//        this.online = 0;
+//        this.expireTime = 90000L; // 默认90秒
+//        this.alarmAck = false;
+//        this.alarmInterval = 30000L; // 默认30秒告警间隔
+//        this.alarmAckInterval = 300000L; // 默认5分钟告警确认间隔
+////        this.realtimePose = new ArrayList<>();
+////        this.poseDurations = new HashMap<>();
+////        this.poseDistribution = new HashMap<>();
+////        this.areaRetentionTimes = new HashMap<>();
+////        this.alarmPlanMap = new HashMap<>();
+////        this.regions = new ArrayList<>();
+//        this.debugParams = new HashMap<>();
+//
+////        // 初始化时间戳
+////        this.enterTs = -1L;
+////        this.leaveTs = -1L;
+////        this.stayTime = -1L;
+////
+////        // 初始化滞留相关参数 (参考Python版本)
+////        this.retentionTime = 60000L;     // 默认60秒
+////        this.retentionKeepTime = 30000L; // 默认30秒
+////        this.retentionAlarmTime = 180000L; // 默认180秒(3分钟)
+//
+//        // 初始化跌倒状态 (对应Python版本)
+//        this.falling_ = 0; // 默认无跌倒状态
+//    }
+//
+//    /**
+//     * 安装参数 - 值对象(Value Object)
+//     * 不可变对象,描述设备的安装参数。
+//     */
+//    @Getter
+//    @Setter
+//    @NoArgsConstructor
+//    @AllArgsConstructor
+//    @Builder
+//    public static class InstallParam {
+//        private String mountPlain;       // 安装面
+//        private Integer isCeiling;       // 是否天花板安装
+//        private Float height;            // 安装高度
+//        private TrackingRegion trackingRegion; // 跟踪区域
+//
+//        /**
+//         * TODO: 完善安装参数类,参考dev_mng.py中的InstallParam类
+//         * 1. 添加安装面属性 (参考dev_mng.py中的mount_plain和isCeiling属性)
+//         * 2. 完善跟踪区域属性 (参考dev_mng.py中的tracking_region属性)
+//         */
+//    }
+//
+//    /**
+//     * 跟踪区域 - 值对象(Value Object)
+//     * 不可变对象,描述设备的跟踪区域。
+//     */
+//    @Getter
+//    @Setter
+//    @NoArgsConstructor
+//    @AllArgsConstructor
+//    public static class TrackingRegion {
+//        private Integer startX;          // 起始X
+//        private Integer startY;          // 起始Y
+//        private Integer startZ;          // 起始Z
+//        private Integer stopX;           // 终止X
+//        private Integer stopY;           // 终止Y
+//        private Integer stopZ;           // 终止Z
 //
 //        /**
-//         * 优化目标点 (对应Python版本的optimize_target方法)
-//         * @param newTarget 新接收到的目标点 [x, y, z, snr]
-//         * @return 优化后的目标点
+//         * TODO: 完善跟踪区域类,参考dev_mng.py中的TrackingRegion类
+//         * 1. 添加线程安全访问机制 (参考dev_mng.py中的lock_机制)
+//         * 2. 完善区域属性 (参考dev_mng.py中的TrackingRegion类属性)
 //         */
-//        public List<Float> optimizeTarget(List<Float> newTarget) {
-//            if (targetList.isEmpty()) {
-//                return new ArrayList<>(newTarget);
+//    }
+//
+//    /**
+//     * 网络信息 - 值对象(Value Object)
+//     * 不可变对象,描述设备的网络配置。
+//     */
+//    @Getter
+//    @Setter
+//    @NoArgsConstructor
+//    @AllArgsConstructor
+//    @Builder
+//    public static class NetworkInfo {
+//        private String ssid;             // WIFI SSID
+//        private String password;         // WIFI 密码
+//        private String ip;               // IP地址
+//
+//        /**
+//         * TODO: 完善网络信息类,参考dev_mng.py中的Network类
+//         * 1. 添加线程安全访问机制 (参考dev_mng.py中的lock_机制)
+//         * 2. 增加更多网络属性 (参考dev_mng.py中的Network类属性)
+//         */
+//    }
+//
+//    /**
+//     * 告警实体
+//     */
+//    @Getter
+//    @Setter
+//    @NoArgsConstructor
+//    @AllArgsConstructor
+//    @Builder
+//    public static class Alarm {
+//        private Long id;                 // 告警ID
+//        private String type;             // 告警类型
+//        private String description;      // 告警描述
+//        private Integer severity;        // 严重程度
+//        private Long timestamp;          // 时间戳
+//        private Boolean acknowledged;    // 是否已确认
+//        private Long acknowledgedTime;   // 确认时间
+//        private Long userId;             // 确认用户ID
+//
+//        /**
+//         * 确认告警
+//         * @param userId 用户ID
+//         * @param timestamp 确认时间
+//         */
+//        public void acknowledge(Long userId, Long timestamp) {
+//            this.acknowledged = true;
+//            this.acknowledgedTime = timestamp;
+//            this.userId = userId;
+//        }
+//    }
+//
+//    /**
+//     * 更新设备保活时间
+//     * @param keepaliveTime 保活时间戳
+//     */
+//    public void updateKeepAliveTime(Long keepaliveTime) {
+//        try {
+//            lock.lock();
+//            this.keepaliveTime = keepaliveTime;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 更新设备在线状态
+//     * @param online 在线状态
+//     * @return 返回旧的在线状态
+//     */
+//    public Integer updateOnlineStatus(Integer online) {
+//        try {
+//            lock.lock();
+//            Integer oldStatus = this.online;
+//            this.online = online;
+//            return oldStatus;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 更新停留时间
+//     */
+//    public void updateStayTime() {
+//        try {
+//            lock.lock();
+//            if (enterTs != null && leaveTs != null) {
+//                stayTime = leaveTs - enterTs;
+//            }
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 重置进入时间
+//     */
+//    public void resetEnterTs() {
+//        try {
+//            lock.lock();
+//            this.enterTs = null;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 重置离开时间
+//     */
+//    public void resetLeaveTs() {
+//        try {
+//            lock.lock();
+//            this.leaveTs = null;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 重置停留时间
+//     */
+//    public void resetStayTime() {
+//        try {
+//            lock.lock();
+//            this.stayTime = 0L;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 检查设备是否超时
+//     * @param currentTime 当前时间
+//     * @return 是否超时
+//     */
+//    public boolean isExpired(long currentTime) {
+//        if (online != null && online == 1 && keepaliveTime != null && expireTime != null) {
+//            return (currentTime - keepaliveTime) > expireTime;
+//        }
+//        return false;
+//    }
+//
+//    /**
+//     * 设置告警确认状态
+//     * @param ack 确认状态
+//     * @param timestamp 确认时间
+//     */
+//    public void setAlarmAcknowledgement(boolean ack, long timestamp) {
+//        try {
+//            lock.lock();
+//            this.alarmAck = ack;
+//            this.lastAlarmAckTime = timestamp;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 设置最后上报跌倒时间 (对应Python版本的set_last_report_fall_time方法)
+//     * @param timestamp 时间戳
+//     */
+//    public void setLastReportFallTime(Long timestamp) {
+//        try {
+//            lock.lock();
+//            this.lastReportFallTime = timestamp;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取最后上报跌倒时间 (对应Python版本的last_report_fall_time方法)
+//     * @return 最后上报跌倒时间
+//     */
+//    public Long getLastReportFallTime() {
+//        try {
+//            lock.lock();
+//            return lastReportFallTime != null ? lastReportFallTime : 0L;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 添加告警记录
+//     * @param alarm 告警对象
+//     */
+//    public void addAlarm(Alarm alarm) {
+//        try {
+//            lock.lock();
+//            alarmHistory.add(alarm);
+//            lastAlarmType = alarm.getType();
+//            lastAlarmTime = alarm.getTimestamp();
+//
+//            // 更新最近活动时间
+//            updateLastActivityTime(alarm.getType(), alarm.getTimestamp());
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 添加行为模式
+//     * @param pattern 行为模式
+//     */
+//    public void addBehaviorPattern(BehaviorPattern pattern) {
+//        try {
+//            lock.lock();
+//            behaviorHistory.add(pattern);
+//
+//            // 如果是异常行为,更新相关状态
+//            if (pattern.getBehaviorType() != null &&
+//                    pattern.getBehaviorType() == 3) { // 3表示异常行为
+//
+//                // 更新最近活动时间
+//                updateLastActivityTime(pattern.getDescription(), pattern.getTimestamp());
+//            }
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 更新最近活动时间
+//     * @param activityType 活动类型
+//     * @param timestamp 时间戳
+//     */
+//    private void updateLastActivityTime(String activityType, Long timestamp) {
+//        if (activityType != null && timestamp != null) {
+//            lastActivityTime.put(activityType, timestamp);
+//        }
+//    }
+//
+//    /**
+//     * 确认告警
+//     * @param alarmId 告警ID
+//     * @param userId 用户ID
+//     * @param timestamp 确认时间
+//     * @return 是否成功确认
+//     */
+//    public boolean acknowledgeAlarm(Long alarmId, Long userId, Long timestamp) {
+//        try {
+//            lock.lock();
+//            for (Alarm alarm : alarmHistory) {
+//                if (alarm.getId() != null && alarm.getId().equals(alarmId)) {
+//                    alarm.acknowledge(userId, timestamp);
+//                    return true;
+//                }
+//            }
+//            return false;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取未确认的告警
+//     * @return 未确认的告警列表
+//     */
+//    public List<Alarm> getUnacknowledgedAlarms() {
+//        try {
+//            lock.lock();
+//            List<Alarm> unacknowledgedAlarms = new ArrayList<>();
+//            for (Alarm alarm : alarmHistory) {
+//                if (alarm.getAcknowledged() == null || !alarm.getAcknowledged()) {
+//                    unacknowledgedAlarms.add(alarm);
+//                }
+//            }
+//            return unacknowledgedAlarms;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 检查是否应该发送告警
+//     * @param alarmType 告警类型
+//     * @param timestamp 当前时间戳
+//     * @param intervalThreshold 告警间隔阈值(毫秒)
+//     * @return 是否应该发送告警
+//     */
+//    public boolean shouldSendAlarm(String alarmType, Long timestamp, Long intervalThreshold) {
+//        try {
+//            lock.lock();
+//
+//            // 如果没有最近活动记录,应该发送告警
+//            if (!lastActivityTime.containsKey(alarmType)) {
+//                return true;
+//            }
+//
+//            // 获取上次该类型告警的时间
+//            Long lastTime = lastActivityTime.get(alarmType);
+//            if (lastTime == null) {
+//                return true;
+//            }
+//
+//            // 检查告警间隔是否超过阈值
+//            return (timestamp - lastTime) > intervalThreshold;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 检查设备是否存在持续滞留
+//     * @param currentTime 当前时间
+//     * @param areaName 区域名称
+//     * @param retentionThreshold 滞留阈值(毫秒)
+//     * @return 是否滞留
+//     */
+//    public boolean checkRetention(Long currentTime, String areaName, Long retentionThreshold) {
+//        if (enterTs == null || currentTime == null) {
+//            return false;
+//        }
+//
+//        long stayDuration = currentTime - enterTs;
+//
+//        // 如果滞留时间超过阈值且未发送过滞留告警,则需要发送告警
+//        if (stayDuration > retentionThreshold) {
+//            // 如果没有发送过滞留告警或者距离上次告警时间已经超过阈值
+//            if (retentionAlarmTime == null || (currentTime - retentionAlarmTime) > retentionThreshold) {
+//                return true;
+//            }
+//        }
+//
+//        return false;
+//    }
+//
+//    /**
+//     * 更新设备姿态
+//     *
+//     * @param pose 姿态
+//     * @param timestamp 时间戳
+//     */
+//    public void updatePose(Integer pose, Long timestamp) {
+//        try {
+//            lock.lock();
+//
+//            // 检查姿态是否变化
+//            boolean poseChanged = false;
+//            if (realtimePose == null) {
+//                realtimePose = new ArrayList<>();
+//            }
+//
+//            if (realtimePose.isEmpty() || !pose.equals(realtimePose.get(0))) {
+//                poseChanged = true;
+//            }
+//
+//            // 添加新姿态到列表开头
+//            realtimePose.add(0, pose);
+//
+//            // 保持列表长度不超过10
+//            if (realtimePose.size() > 10) {
+//                realtimePose.remove(realtimePose.size() - 1);
+//            }
+//
+//            // 如果姿态发生变化,更新姿态变化时间
+//            if (poseChanged) {
+//                lastPoseChangeTime = timestamp;
+//
+//                // 更新姿态持续时间
+//                updatePoseDuration(pose, timestamp);
+//            }
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 更新姿态持续时间
+//     *
+//     * @param pose 姿态
+//     * @param timestamp 当前时间戳
+//     */
+//    private void updatePoseDuration(Integer pose, Long timestamp) {
+//        if (poseDurations == null) {
+//            poseDurations = new HashMap<>();
+//        }
+//
+//        // 初始化姿态持续时间
+//        if (!poseDurations.containsKey(pose)) {
+//            poseDurations.put(pose, 0L);
+//        }
+//    }
+//
+//    /**
+//     * 更新区域滞留时间
+//     *
+//     * @param areaName 区域名称
+//     * @param timestamp 时间戳
+//     */
+//    public void updateAreaRetentionTime(String areaName, Long timestamp) {
+//        try {
+//            lock.lock();
+//
+//            if (areaRetentionTimes == null) {
+//                areaRetentionTimes = new HashMap<>();
+//            }
+//
+//            // 记录区域滞留开始时间
+//            if (!areaRetentionTimes.containsKey(areaName)) {
+//                areaRetentionTimes.put(areaName, timestamp);
+//            }
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 重置区域滞留时间
+//     *
+//     * @param areaName 区域名称
+//     */
+//    public void resetAreaRetentionTime(String areaName) {
+//        try {
+//            lock.lock();
+//
+//            if (areaRetentionTimes != null && areaRetentionTimes.containsKey(areaName)) {
+//                areaRetentionTimes.remove(areaName);
+//            }
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取区域滞留时间
+//     *
+//     * @param areaName 区域名称
+//     * @param currentTime 当前时间
+//     * @return 滞留时间(毫秒)
+//     */
+//    public Long getAreaRetentionDuration(String areaName, Long currentTime) {
+//        try {
+//            lock.lock();
+//
+//            if (areaRetentionTimes == null || !areaRetentionTimes.containsKey(areaName)) {
+//                return 0L;
+//            }
+//
+//            Long startTime = areaRetentionTimes.get(areaName);
+//            if (startTime == null) {
+//                return 0L;
+//            }
+//
+//            return currentTime - startTime;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 添加告警计划
+//     *
+//     * @param alarmPlan 告警计划
+//     */
+//    public void addAlarmPlan(AlarmPlan alarmPlan) {
+//        try {
+//            lock.lock();
+//
+//            if (alarmPlan != null && alarmPlan.getName() != null) {
+//                alarmPlanMap.put(alarmPlan.getName(), alarmPlan);
+//            }
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 移除告警计划
+//     *
+//     * @param planName 计划名称
+//     * @return 被移除的告警计划
+//     */
+//    public AlarmPlan removeAlarmPlan(String planName) {
+//        try {
+//            lock.lock();
+//
+//            return alarmPlanMap.remove(planName);
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取告警计划
+//     *
+//     * @param planName 计划名称
+//     * @return 告警计划
+//     */
+//    public AlarmPlan getAlarmPlan(String planName) {
+//        try {
+//            lock.lock();
+//
+//            return alarmPlanMap.get(planName);
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取所有告警计划
+//     *
+//     * @return 告警计划列表
+//     */
+//    public List<AlarmPlan> getAllAlarmPlans() {
+//        try {
+//            lock.lock();
+//
+//            return new ArrayList<>(alarmPlanMap.values());
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 更新告警计划目标
+//     *
+//     * @param targets 目标点列表
+//     */
+//    public void updateAlarmTargets(List<List<Float>> targets) {
+//        if (targets == null || targets.isEmpty()) {
+//            return;
+//        }
+//
+//        try {
+//            lock.lock();
+//
+//            long currentTime = System.currentTimeMillis();
+//
+//            // 更新所有告警计划的目标
+//            if (CollectionUtils.isEmpty(alarmPlanMap)) {
+//                return;
+//            }
+//            for (AlarmPlan plan : alarmPlanMap.values()) {
+//                plan.updateTarget(targets, currentTime);
+//            }
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 检查所有告警计划
+//     *
+//     * @return 需要触发告警的计划列表
+//     */
+//    public List<AlarmPlan> checkAlarmPlans() {
+//        try {
+//            lock.lock();
+//
+//            List<AlarmPlan> alarmedPlans = new ArrayList<>();
+//            long currentTime = System.currentTimeMillis();
+//
+//            // 检查所有告警计划
+//            for (AlarmPlan plan : alarmPlanMap.values()) {
+//                if (plan.checkRetention(currentTime)) {
+//                    alarmedPlans.add(plan);
+//                }
+//            }
+//
+//            return alarmedPlans;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 添加区域
+//     *
+//     * @param region 区域
+//     */
+//    public void addRegion(Region region) {
+//        try {
+//            lock.lock();
+//
+//            if (region != null) {
+//                // 检查是否已存在相同ID的区域
+//                for (int i = 0; i < regions.size(); i++) {
+//                    if (regions.get(i).getId().equals(region.getId())) {
+//                        // 更新现有区域
+//                        regions.set(i, region);
+//                        return;
+//                    }
+//                }
+//
+//                // 添加新区域
+//                regions.add(region);
+//            }
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 移除区域
+//     *
+//     * @param regionId 区域ID
+//     * @return 是否成功移除
+//     */
+//    public boolean removeRegion(String regionId) {
+//        try {
+//            lock.lock();
+//
+//            for (int i = 0; i < regions.size(); i++) {
+//                if (regions.get(i).getId().equals(regionId)) {
+//                    regions.remove(i);
+//                    return true;
+//                }
+//            }
+//
+//            return false;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取区域
+//     *
+//     * @param regionId 区域ID
+//     * @return 区域
+//     */
+//    public Region getRegion(String regionId) {
+//        try {
+//            lock.lock();
+//
+//            for (Region region : regions) {
+//                if (region.getId().equals(regionId)) {
+//                    return region;
+//                }
+//            }
+//
+//            return null;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取所有区域
+//     *
+//     * @return 区域列表
+//     */
+//    public List<Region> getAllRegions() {
+//        try {
+//            lock.lock();
+//
+//            return new ArrayList<>(regions);
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 查找包含指定点的区域
+//     *
+//     * @param x 点的x坐标
+//     * @param y 点的y坐标
+//     * @return 包含该点的区域列表
+//     */
+//    public List<Region> findRegionsContainingPoint(float x, float y) {
+//        try {
+//            lock.lock();
+//
+//            List<Region> result = new ArrayList<>();
+//
+//            for (Region region : regions) {
+//                if (region.containsPoint(x, y)) {
+//                    result.add(region);
+//                }
 //            }
 //
-//            // 计算队列中点的平均值 (对应Python版本的avg_x, avg_y, avg_z计算)
-//            float avgX = 0.0f, avgY = 0.0f, avgZ = 0.0f;
-//            for (List<Float> target : targetList) {
-//                avgX += target.get(0);
-//                avgY += target.get(1);
-//                avgZ += target.get(2);
+//            return result;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 更新告警配置
+//     *
+//     * @param retentionTime 停留时间阈值(毫秒)
+//     * @param retentionKeepTime 停留保持时间(毫秒)
+//     * @param retentionAlarmTime 停留告警时间(毫秒)
+//     */
+//    public void updateAlarmConfig(long retentionTime, long retentionKeepTime, long retentionAlarmTime) {
+//        try {
+//            lock.lock();
+//            this.retentionTime = retentionTime;
+//            this.retentionKeepTime = retentionKeepTime;
+//            this.retentionAlarmTime = retentionAlarmTime;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 检查是否应该发送跌倒告警 (参考Python版本的deal_report_falling_event逻辑)
+//     * @param currentTime 当前时间
+//     * @return true如果应该发送告警
+//     */
+//    public boolean shouldSendFallAlarm(long currentTime) {
+//        try {
+//            lock.lock();
+//            // 检查告警确认状态
+//            if (Boolean.TRUE.equals(alarmAck)) {
+//                return false;
+//            }
+//
+//            // 检查告警间隔
+//            if (lastReportFallTime != null) {
+//                long timeSinceLastAlarm = currentTime - lastReportFallTime;
+//                if (timeSinceLastAlarm < alarmInterval) {
+//                    return false;
+//                }
 //            }
-//            avgX /= targetList.size();
-//            avgY /= targetList.size();
-//            avgZ /= targetList.size();
-//
-//            // 动态阈值调整 (对应Python版本的dynamic_threshold计算)
-//            float dx = newTarget.get(0) - avgX;
-//            float dy = newTarget.get(1) - avgY;
-//            float distanceToAvg = (float) Math.sqrt(dx * dx + dy * dy);
-//            float dynamicThreshold = baseThreshold + (distanceToAvg * 0.3f);
-//
-//            // 如果与均值的偏差超过动态阈值,则平滑处理 (对应Python版本的平滑逻辑)
-//            if (distanceToAvg > dynamicThreshold) {
-//                float smoothedX = (newTarget.get(0) + avgX) / 2.0f;
-//                float smoothedY = (newTarget.get(1) + avgY) / 2.0f;
-//                float smoothedZ = (newTarget.get(1) + avgZ) / 2.0f;  // 保持与Python版本完全一致,包括这个bug:使用newTarget.get(1)而不是get(2)
-//
-//                List<Float> optimizedTarget = new ArrayList<>();
-//                optimizedTarget.add(smoothedX);
-//                optimizedTarget.add(smoothedY);
-//                optimizedTarget.add(smoothedZ);
-//                return optimizedTarget;
+//
+//            return true;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 检查心跳是否被调试参数拒绝 (参考Python版本的deal_dev_keepalive逻辑)
+//     * @return true如果应该拒绝心跳
+//     */
+//    public boolean shouldRejectKeepAlive() {
+//        try {
+//            lock.lock();
+//            Object keepaliveDebug = debugParams.get("keepalive");
+//            return keepaliveDebug != null && Integer.valueOf(0).equals(keepaliveDebug);
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 设置设备参数信息
+//     * 对应Python版本的set_param(self, param)方法
+//     * @param param 完整的设备参数信息
+//     */
+//    public void setParam(Map<String, Object> param) {
+//        try {
+//            lock.lock();
+//            this.param = param;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取设备参数信息
+//     * 对应Python版本的param(self)方法
+//     * @return 完整的设备参数信息
+//     */
+//    public Map<String, Object> getParam() {
+//        try {
+//            lock.lock();
+//            return param;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 设置调试参数
+//     * @param key 参数键
+//     * @param value 参数值
+//     */
+//    public void setDebugParam(String key, Object value) {
+//        try {
+//            lock.lock();
+//            debugParams.put(key, value);
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取调试参数
+//     * @param key 参数键
+//     * @return 参数值
+//     */
+//    public Object getDebugParam(String key) {
+//        try {
+//            lock.lock();
+//            return debugParams.get(key);
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 检查停留时间并处理滞留告警 (参考Python版本的check_stay_time逻辑)
+//     * @param currentTime 当前时间
+//     * @return 如果检测到滞留事件返回滞留记录,否则返回null
+//     */
+//    public StayTimeRecord checkStayTime(long currentTime) {
+//        try {
+//            lock.lock();
+//
+//            if (enterTs == null || enterTs == -1 || leaveTs == null || leaveTs == -1) {
+//                return null;
+//            }
+//
+//            // 保留时间内,不认为停留事件结束
+//            long timeSinceLeave = currentTime - leaveTs;
+//            if (timeSinceLeave <= retentionKeepTime) {
+//                return null;
+//            }
+//
+//            // 时间少于最小时间尺,忽略本次事件,并重置计时
+//            long stayTimeMs = leaveTs - enterTs;
+//            if (stayTimeMs < retentionTime) {
+//                // 重置计时
+//                this.enterTs = -1L;
+//                this.leaveTs = -1L;
+//                this.stayTime = -1L;
+//                return null;
+//            }
+//
+//            // 创建停留时间记录
+//            StayTimeRecord record = new StayTimeRecord();
+//            record.setDevId(devId);
+//            record.setEnterTime(enterTs);
+//            record.setLeaveTime(leaveTs);
+//            record.setStayTime(stayTimeMs);
+//
+//            // 检查是否需要创建滞留告警 (超过3分钟视为异常滞留)
+//            long stayTimeSeconds = stayTimeMs / 1000;
+//            if (stayTimeSeconds >= (retentionAlarmTime / 1000)) {
+//                record.setNeedAlarm(true);
+//                record.setAlarmType("alarm_retention");
+//                record.setAlarmDescription("设备滞留时间过长");
+//            }
+//
+//            // 重置计时
+//            this.enterTs = -1L;
+//            this.leaveTs = -1L;
+//            this.stayTime = -1L;
+//
+//            return record;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 检查告警确认是否超时 (参考Python版本的check_dev_alarm_ack逻辑)
+//     * @param currentTime 当前时间
+//     * @return true如果告警确认超时需要清除
+//     */
+//    public boolean shouldClearAlarmAck(long currentTime) {
+//        try {
+//            lock.lock();
+//            if (Boolean.TRUE.equals(alarmAck) && lastAlarmAckTime != null) {
+//                long timeSinceAck = currentTime - lastAlarmAckTime;
+//                return timeSinceAck > alarmAckInterval;
+//            }
+//            return false;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 清除告警确认状态
+//     */
+//    public void clearAlarmAck() {
+//        try {
+//            lock.lock();
+//            this.alarmAck = false;
+//            this.lastAlarmAckTime = null;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//         /**
+//      * 更新实时位置(平滑算法) - 重写以对应Python版本的update_targets方法
+//      * @param newTargets 新的目标位置列表
+//      * @return 稳定的目标位置列表
+//      */
+//     public List<List<Float>> updateTargets(List<List<Float>> newTargets) {
+//        try {
+//            lock.lock();
+//
+//            // 对应Python版本的输入验证
+//            if (newTargets == null || newTargets.isEmpty() ||
+//                newTargets.get(0).size() < 3) {
+//                // 对应Python: LOGERR(f"update_targets error: invalid new_targets")
+//                return new ArrayList<>();
+//            }
+//
+//            // 对应Python: new_target = new_targets[0]
+//            List<Float> newTarget = newTargets.get(0);
+//
+//            // 对应Python: stable_target = self.stabilizer.update_target_list(new_target)
+//            List<Float> stableTarget = stabilizer.updateTargetList(newTarget);
+//
+//            // 更新targets字段
+//            this.targets = stableTarget;
+//
+//            // 对应Python: return [stable_target]
+//            List<List<Float>> result = new ArrayList<>();
+//            result.add(stableTarget);
+//            return result;
+//
+//        } catch (Exception e) {
+//            // 对应Python: except Exception as e: LOGERR(f"update_targets error: {e}")
+//            return new ArrayList<>();
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取实时姿态 (对应Python版本的realtime_pose方法)
+//     * @return 实时姿态列表
+//     */
+//    public List<Integer> getRealtimePose() {
+//        try {
+//            lock.lock();
+//            return realtimePose != null ? new ArrayList<>(realtimePose) : new ArrayList<>();
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 设置实时姿态 (对应Python版本的set_realtime_pose方法)
+//     * @param pose 姿态列表
+//     */
+//    public void setRealtimePose(List<Integer> pose) {
+//        try {
+//            lock.lock();
+//            this.realtimePose = pose != null ? new ArrayList<>(pose) : new ArrayList<>();
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取进入时间 (对应Python版本的enter_ts方法)
+//     * @return 进入时间戳,如果未设置返回-1
+//     */
+//    public Long getEnterTime() {
+//        try {
+//            lock.lock();
+//            return enterTs != null ? enterTs : -1L;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 设置进入时间 (对应Python版本的set_enter_ts方法)
+//     * @param timestamp 时间戳
+//     */
+//    public void setEnterTime(Long timestamp) {
+//        try {
+//            lock.lock();
+//            this.enterTs = timestamp;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取离开时间 (对应Python版本的leave_ts方法)
+//     * @return 离开时间戳,如果未设置返回-1
+//     */
+//    public Long getLeaveTime() {
+//        try {
+//            lock.lock();
+//            return leaveTs != null ? leaveTs : -1L;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 设置离开时间 (对应Python版本的set_leave_ts方法)
+//     * @param timestamp 时间戳
+//     */
+//    public void setLeaveTime(Long timestamp) {
+//        try {
+//            lock.lock();
+//            this.leaveTs = timestamp;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 检查告警间隔 (对应Python版本的告警间隔检查逻辑)
+//     * @param eventType 事件类型
+//     * @param currentTime 当前时间
+//     * @return 是否应该发送告警
+//     */
+//    public boolean shouldSendAlarmForEvent(String eventType, Long currentTime) {
+//        try {
+//            lock.lock();
+//            // 如果已经确认告警,则不发送
+//            if (Boolean.TRUE.equals(alarmAck)) {
+//                return false;
+//            }
+//
+//            // 检查告警间隔 (对应Python: now - device.last_fall_time(event) < device.alarm_interval())
+//            Long lastEventTime = lastFallTimeByEvent.get(eventType);
+//            if (lastEventTime != null && currentTime != null) {
+//                long timeSinceLastAlarm = currentTime - lastEventTime;
+//                return timeSinceLastAlarm >= (alarmInterval != null ? alarmInterval : 30000L); // 默认30秒间隔
+//            }
+//
+//            return true;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 设置最后跌倒时间 (对应Python版本的set_last_fall_time方法)
+//     * @param eventType 事件类型
+//     * @param timestamp 时间戳
+//     */
+//    public void setLastFallTime(String eventType, Long timestamp) {
+//        try {
+//            lock.lock();
+//            this.lastReportFallTime = timestamp;
+//            // 为每个事件类型单独记录时间 (对应Python版本的last_fall_time_[event] = time)
+//            lastFallTimeByEvent.put(eventType, timestamp);
+//            lastActivityTime.put("fall_" + eventType, timestamp);
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取指定事件类型的最后跌倒时间 (对应Python版本的last_fall_time(event))
+//     * @param eventType 事件类型
+//     * @return 最后跌倒时间,如果没有记录返回0
+//     */
+//    public Long getLastFallTime(String eventType) {
+//        try {
+//            lock.lock();
+//            return lastFallTimeByEvent.getOrDefault(eventType, 0L);
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取当前跌倒状态 (对应Python版本的device.falling_)
+//     * @return 跌倒状态:0-无跌倒,1-检测到跌倒,2-跌倒确认,3-跌倒呼救
+//     */
+//    public Integer getFalling() {
+//        try {
+//            lock.lock();
+//            return falling_ != null ? falling_ : 0;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 设置当前跌倒状态 (对应Python版本的device.falling_)
+//     * @param falling 跌倒状态:0-无跌倒,1-检测到跌倒,2-跌倒确认,3-跌倒呼救
+//     */
+//    public void setFalling(Integer falling) {
+//        try {
+//            lock.lock();
+//            this.falling_ = falling;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 检查LNA设备的告警间隔 (对应Python版本的LNA特殊逻辑)
+//     *
+//     * Python真实逻辑:
+//     * - device.falling_字段永远为0(从不更新)
+//     * - 当falling==0(无跌倒)时:falling_ == falling为true,检查报警间隔
+//     * - 当falling!=0(有跌倒)时:falling_ == falling为false,跳过报警间隔检查,立即发送
+//     * - 简化理解:只有无跌倒状态才检查报警间隔,任何跌倒状态都立即发送
+//     *
+//     * @param newFalling 新的跌倒状态
+//     * @param currentTime 当前时间
+//     * @return 是否应该发送告警
+//     */
+//    public boolean shouldSendAlarmForLNA(Integer newFalling, Long currentTime) {
+//        try {
+//            lock.lock();
+//            // 如果已经确认告警,则不发送
+//            if (Boolean.TRUE.equals(alarmAck)) {
+//                return false;
+//            }
+//
+//            // 对应Python逻辑:if device.falling_ == falling
+//            // 由于falling_永远为0,所以只有当newFalling==0时才检查报警间隔
+//            if (Objects.equals(falling_, newFalling)) {
+//                // 检查报警间隔(使用lastReportFallTime,对应Python: device.last_report_fall_time())
+//                if (lastReportFallTime != null && currentTime != null) {
+//                    long timeSinceLastAlarm = currentTime - lastReportFallTime;
+//                    return timeSinceLastAlarm >= (alarmInterval != null ? alarmInterval : 30000L);
+//                }
+//            }
+//
+//            // 当falling_不等于newFalling时(即newFalling!=0时),或者没有历史时间时,直接发送
+//            return true;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 根据设备类型处理跌倒事件 (参考Python版本的设备类型区分逻辑)
+//     * @param event 事件类型
+//     * @param pose 姿态
+//     * @param location 位置坐标
+//     * @return 处理结果
+//     */
+//    public FallEventResult processFallEvent(String event, int pose, List<Float> location) {
+//        try {
+//            lock.lock();
+//            FallEventResult result = new FallEventResult();
+//            result.setDevId(devId);
+//            result.setEvent(event);
+//
+//            if ("LNB".equals(devType)) {
+//                // LNB设备的处理逻辑 (参考Python版本)
+//                result.setPose("no_fall".equals(event) ? 4 : 0); // POSE_4 或 POSE_0
+//                // 转换位置坐标格式 (参考Python版本的targets格式)
+//                if (location != null && location.size() >= 3) {
+//                    float[] targetPoint = {location.get(0)/100f, location.get(1)/100f, location.get(2)/100f};
+//                    result.setLocation(targetPoint);
+//                }
+//                result.setShouldProcess(true);
+//            } else if ("LNA".equals(devType)) {
+//                // LNA设备的处理逻辑 (参考Python版本)
+//                if (realtimePose == null || realtimePose.isEmpty() || !Integer.valueOf(0).equals(realtimePose.get(0))) {
+//                    result.setShouldProcess(false);
+//                    return result;
+//                }
+//                result.setPose(realtimePose.get(0));
+//                // 转换位置坐标格式
+//                if (location != null && location.size() >= 3) {
+//                    float[] targetPoint = {location.get(0)/100f, location.get(1)/100f, location.get(2)/100f};
+//                    result.setLocation(targetPoint);
+//                }
+//                result.setShouldProcess(true);
 //            } else {
-//                return new ArrayList<>(newTarget);
+//                result.setShouldProcess(false);
 //            }
+//
+//            return result;
+//        } finally {
+//            lock.unlock();
 //        }
+//    }
 //
-//        /**
-//         * 更新目标列表 (对应Python版本的update_target_list方法)
-//         * @param newTarget 原始目标点 [x, y, z, snr]
-//         * @return 优化后的目标点
-//         */
-//        public List<Float> updateTargetList(List<Float> newTarget) {
-//            if (newTarget.size() < 3) {
-//                // 对应Python: LOGDBG(f"update_target_list error: invlid target:{new_target}")
-//                return new ArrayList<>(newTarget);
+//    /**
+//     * 放入点云数据到队列 (对应Python版本的put_cloud_points_que方法)
+//     * @param cloudPoints 点云数据
+//     */
+//    public void putCloudPointsQueue(List<List<Float>> cloudPoints) {
+//        try {
+//            lock.lock();
+//            if (cloudPoints != null && !cloudPoints.isEmpty()) {
+//                // 如果队列已满,移除最老的数据
+//                while (cloudPointsQueue.size() >= MAX_CLOUD_POINTS_QUEUE_SIZE) {
+//                    cloudPointsQueue.poll();
+//                }
+//                cloudPointsQueue.offer(new ArrayList<>(cloudPoints));
 //            }
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
 //
-//            List<Float> optimizedTarget = optimizeTarget(newTarget);
+//    /**
+//     * 获取点云数据队列 (用于调试和分析)
+//     * @return 点云数据队列的副本
+//     */
+//    public List<List<List<Float>>> getCloudPointsQueue() {
+//        try {
+//            lock.lock();
+//            return new ArrayList<>(cloudPointsQueue);
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 清空点云数据队列
+//     */
+//    public void clearCloudPointsQueue() {
+//        try {
+//            lock.lock();
+//            cloudPointsQueue.clear();
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
 //
-//            // 如果队列已满,移除最老的目标 (对应Python的deque maxlen行为)
-//            if (targetList.size() >= 10) {  // queueLength
-//                targetList.removeFirst();
+//    /**
+//     * 检查跌倒告警间隔 (对应Python版本的告警间隔检查逻辑)
+//     * @param currentTime 当前时间
+//     * @return true如果可以发送跌倒告警
+//     */
+//    public boolean checkFallAlarmInterval(Long currentTime) {
+//        try {
+//            lock.lock();
+//            // 检查告警确认状态 (对应Python: device.get_alarm_ack())
+//            if (Boolean.TRUE.equals(alarmAck)) {
+//                return false;
+//            }
+//
+//            // 检查告警间隔 (对应Python: now - device.last_report_fall_time() < device.alarm_interval())
+//            if (lastReportFallTime != null && currentTime != null) {
+//                long timeSinceLastFall = currentTime - lastReportFallTime;
+//                return timeSinceLastFall >= (alarmInterval != null ? alarmInterval : 30000L); // 默认30秒间隔
 //            }
-//            targetList.addLast(optimizedTarget);
-//
-//            return optimizedTarget;
-//        }
-//    }
-//
-//    // 目标稳定器实例 (对应Python版本device中的stabilizer)
-//    private TargetStabilizer stabilizer = new TargetStabilizer(10, 1.0f);
-
-    /**
-     * 构造函数,设置默认值
-     * @param devId 设备ID
-     */
-    public DeviceCache(String devId) {
-        this.devId = devId;
-        this.online = 0;
-        this.expireTime = 90000L; // 默认90秒
-        this.alarmAck = false;
-        this.alarmInterval = 30000L; // 默认30秒告警间隔
-        this.alarmAckInterval = 300000L; // 默认5分钟告警确认间隔
-//        this.realtimePose = new ArrayList<>();
-//        this.poseDurations = new HashMap<>();
-//        this.poseDistribution = new HashMap<>();
-//        this.areaRetentionTimes = new HashMap<>();
-//        this.alarmPlanMap = new HashMap<>();
-//        this.regions = new ArrayList<>();
-        this.debugParams = new HashMap<>();
-        
-//        // 初始化时间戳
-//        this.enterTs = -1L;
-//        this.leaveTs = -1L;
-//        this.stayTime = -1L;
-//
-//        // 初始化滞留相关参数 (参考Python版本)
-//        this.retentionTime = 60000L;     // 默认60秒
-//        this.retentionKeepTime = 30000L; // 默认30秒
-//        this.retentionAlarmTime = 180000L; // 默认180秒(3分钟)
-        
-        // 初始化跌倒状态 (对应Python版本)
-        this.falling_ = 0; // 默认无跌倒状态
-    }
-    
-    /**
-     * 安装参数 - 值对象(Value Object)
-     * 不可变对象,描述设备的安装参数。
-     */
-    @Getter
-    @Setter
-    @NoArgsConstructor
-    @AllArgsConstructor
-    @Builder
-    public static class InstallParam {
-        private String mountPlain;       // 安装面
-        private Integer isCeiling;       // 是否天花板安装
-        private Float height;            // 安装高度
-        private TrackingRegion trackingRegion; // 跟踪区域
-        
-        /**
-         * TODO: 完善安装参数类,参考dev_mng.py中的InstallParam类
-         * 1. 添加安装面属性 (参考dev_mng.py中的mount_plain和isCeiling属性)
-         * 2. 完善跟踪区域属性 (参考dev_mng.py中的tracking_region属性)
-         */
-    }
-    
-    /**
-     * 跟踪区域 - 值对象(Value Object)
-     * 不可变对象,描述设备的跟踪区域。
-     */
-    @Getter
-    @Setter
-    @NoArgsConstructor
-    @AllArgsConstructor
-    public static class TrackingRegion {
-        private Integer startX;          // 起始X
-        private Integer startY;          // 起始Y
-        private Integer startZ;          // 起始Z
-        private Integer stopX;           // 终止X
-        private Integer stopY;           // 终止Y
-        private Integer stopZ;           // 终止Z
-        
-        /**
-         * TODO: 完善跟踪区域类,参考dev_mng.py中的TrackingRegion类
-         * 1. 添加线程安全访问机制 (参考dev_mng.py中的lock_机制)
-         * 2. 完善区域属性 (参考dev_mng.py中的TrackingRegion类属性)
-         */
-    }
-    
-    /**
-     * 网络信息 - 值对象(Value Object)
-     * 不可变对象,描述设备的网络配置。
-     */
-    @Getter
-    @Setter
-    @NoArgsConstructor
-    @AllArgsConstructor
-    @Builder
-    public static class NetworkInfo {
-        private String ssid;             // WIFI SSID
-        private String password;         // WIFI 密码
-        private String ip;               // IP地址
-        
-        /**
-         * TODO: 完善网络信息类,参考dev_mng.py中的Network类
-         * 1. 添加线程安全访问机制 (参考dev_mng.py中的lock_机制)
-         * 2. 增加更多网络属性 (参考dev_mng.py中的Network类属性)
-         */
-    }
-    
-    /**
-     * 告警实体
-     */
-    @Getter
-    @Setter
-    @NoArgsConstructor
-    @AllArgsConstructor
-    @Builder
-    public static class Alarm {
-        private Long id;                 // 告警ID
-        private String type;             // 告警类型
-        private String description;      // 告警描述
-        private Integer severity;        // 严重程度
-        private Long timestamp;          // 时间戳
-        private Boolean acknowledged;    // 是否已确认
-        private Long acknowledgedTime;   // 确认时间
-        private Long userId;             // 确认用户ID
-        
-        /**
-         * 确认告警
-         * @param userId 用户ID
-         * @param timestamp 确认时间
-         */
-        public void acknowledge(Long userId, Long timestamp) {
-            this.acknowledged = true;
-            this.acknowledgedTime = timestamp;
-            this.userId = userId;
-        }
-    }
-    
-    /**
-     * 更新设备保活时间
-     * @param keepaliveTime 保活时间戳
-     */
-    public void updateKeepAliveTime(Long keepaliveTime) {
-        try {
-            lock.lock();
-            this.keepaliveTime = keepaliveTime;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 更新设备在线状态
-     * @param online 在线状态
-     * @return 返回旧的在线状态
-     */
-    public Integer updateOnlineStatus(Integer online) {
-        try {
-            lock.lock();
-            Integer oldStatus = this.online;
-            this.online = online;
-            return oldStatus;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 更新停留时间
-     */
-    public void updateStayTime() {
-        try {
-            lock.lock();
-            if (enterTs != null && leaveTs != null) {
-                stayTime = leaveTs - enterTs;
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 重置进入时间
-     */
-    public void resetEnterTs() {
-        try {
-            lock.lock();
-            this.enterTs = null;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 重置离开时间
-     */
-    public void resetLeaveTs() {
-        try {
-            lock.lock();
-            this.leaveTs = null;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 重置停留时间
-     */
-    public void resetStayTime() {
-        try {
-            lock.lock();
-            this.stayTime = 0L;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 检查设备是否超时
-     * @param currentTime 当前时间
-     * @return 是否超时
-     */
-    public boolean isExpired(long currentTime) {
-        if (online != null && online == 1 && keepaliveTime != null && expireTime != null) {
-            return (currentTime - keepaliveTime) > expireTime;
-        }
-        return false;
-    }
-    
-    /**
-     * 设置告警确认状态
-     * @param ack 确认状态
-     * @param timestamp 确认时间
-     */
-    public void setAlarmAcknowledgement(boolean ack, long timestamp) {
-        try {
-            lock.lock();
-            this.alarmAck = ack;
-            this.lastAlarmAckTime = timestamp;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 设置最后上报跌倒时间 (对应Python版本的set_last_report_fall_time方法)
-     * @param timestamp 时间戳
-     */
-    public void setLastReportFallTime(Long timestamp) {
-        try {
-            lock.lock();
-            this.lastReportFallTime = timestamp;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取最后上报跌倒时间 (对应Python版本的last_report_fall_time方法)
-     * @return 最后上报跌倒时间
-     */
-    public Long getLastReportFallTime() {
-        try {
-            lock.lock();
-            return lastReportFallTime != null ? lastReportFallTime : 0L;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 添加告警记录
-     * @param alarm 告警对象
-     */
-    public void addAlarm(Alarm alarm) {
-        try {
-            lock.lock();
-            alarmHistory.add(alarm);
-            lastAlarmType = alarm.getType();
-            lastAlarmTime = alarm.getTimestamp();
-            
-            // 更新最近活动时间
-            updateLastActivityTime(alarm.getType(), alarm.getTimestamp());
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 添加行为模式
-     * @param pattern 行为模式
-     */
-    public void addBehaviorPattern(BehaviorPattern pattern) {
-        try {
-            lock.lock();
-            behaviorHistory.add(pattern);
-            
-            // 如果是异常行为,更新相关状态
-            if (pattern.getBehaviorType() != null && 
-                    pattern.getBehaviorType() == 3) { // 3表示异常行为
-                
-                // 更新最近活动时间
-                updateLastActivityTime(pattern.getDescription(), pattern.getTimestamp());
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 更新最近活动时间
-     * @param activityType 活动类型
-     * @param timestamp 时间戳
-     */
-    private void updateLastActivityTime(String activityType, Long timestamp) {
-        if (activityType != null && timestamp != null) {
-            lastActivityTime.put(activityType, timestamp);
-        }
-    }
-    
-    /**
-     * 确认告警
-     * @param alarmId 告警ID
-     * @param userId 用户ID
-     * @param timestamp 确认时间
-     * @return 是否成功确认
-     */
-    public boolean acknowledgeAlarm(Long alarmId, Long userId, Long timestamp) {
-        try {
-            lock.lock();
-            for (Alarm alarm : alarmHistory) {
-                if (alarm.getId() != null && alarm.getId().equals(alarmId)) {
-                    alarm.acknowledge(userId, timestamp);
-                    return true;
-                }
-            }
-            return false;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取未确认的告警
-     * @return 未确认的告警列表
-     */
-    public List<Alarm> getUnacknowledgedAlarms() {
-        try {
-            lock.lock();
-            List<Alarm> unacknowledgedAlarms = new ArrayList<>();
-            for (Alarm alarm : alarmHistory) {
-                if (alarm.getAcknowledged() == null || !alarm.getAcknowledged()) {
-                    unacknowledgedAlarms.add(alarm);
-                }
-            }
-            return unacknowledgedAlarms;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 检查是否应该发送告警
-     * @param alarmType 告警类型
-     * @param timestamp 当前时间戳
-     * @param intervalThreshold 告警间隔阈值(毫秒)
-     * @return 是否应该发送告警
-     */
-    public boolean shouldSendAlarm(String alarmType, Long timestamp, Long intervalThreshold) {
-        try {
-            lock.lock();
-            
-            // 如果没有最近活动记录,应该发送告警
-            if (!lastActivityTime.containsKey(alarmType)) {
-                return true;
-            }
-            
-            // 获取上次该类型告警的时间
-            Long lastTime = lastActivityTime.get(alarmType);
-            if (lastTime == null) {
-                return true;
-            }
-            
-            // 检查告警间隔是否超过阈值
-            return (timestamp - lastTime) > intervalThreshold;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 检查设备是否存在持续滞留
-     * @param currentTime 当前时间
-     * @param areaName 区域名称
-     * @param retentionThreshold 滞留阈值(毫秒)
-     * @return 是否滞留
-     */
-    public boolean checkRetention(Long currentTime, String areaName, Long retentionThreshold) {
-        if (enterTs == null || currentTime == null) {
-            return false;
-        }
-        
-        long stayDuration = currentTime - enterTs;
-        
-        // 如果滞留时间超过阈值且未发送过滞留告警,则需要发送告警
-        if (stayDuration > retentionThreshold) {
-            // 如果没有发送过滞留告警或者距离上次告警时间已经超过阈值
-            if (retentionAlarmTime == null || (currentTime - retentionAlarmTime) > retentionThreshold) {
-                return true;
-            }
-        }
-        
-        return false;
-    }
-    
-    /**
-     * 更新设备姿态
-     * 
-     * @param pose 姿态
-     * @param timestamp 时间戳
-     */
-    public void updatePose(Integer pose, Long timestamp) {
-        try {
-            lock.lock();
-            
-            // 检查姿态是否变化
-            boolean poseChanged = false;
-            if (realtimePose == null) {
-                realtimePose = new ArrayList<>();
-            }
-            
-            if (realtimePose.isEmpty() || !pose.equals(realtimePose.get(0))) {
-                poseChanged = true;
-            }
-            
-            // 添加新姿态到列表开头
-            realtimePose.add(0, pose);
-            
-            // 保持列表长度不超过10
-            if (realtimePose.size() > 10) {
-                realtimePose.remove(realtimePose.size() - 1);
-            }
-            
-            // 如果姿态发生变化,更新姿态变化时间
-            if (poseChanged) {
-                lastPoseChangeTime = timestamp;
-                
-                // 更新姿态持续时间
-                updatePoseDuration(pose, timestamp);
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 更新姿态持续时间
-     * 
-     * @param pose 姿态
-     * @param timestamp 当前时间戳
-     */
-    private void updatePoseDuration(Integer pose, Long timestamp) {
-        if (poseDurations == null) {
-            poseDurations = new HashMap<>();
-        }
-        
-        // 初始化姿态持续时间
-        if (!poseDurations.containsKey(pose)) {
-            poseDurations.put(pose, 0L);
-        }
-    }
-    
-    /**
-     * 更新区域滞留时间
-     * 
-     * @param areaName 区域名称
-     * @param timestamp 时间戳
-     */
-    public void updateAreaRetentionTime(String areaName, Long timestamp) {
-        try {
-            lock.lock();
-            
-            if (areaRetentionTimes == null) {
-                areaRetentionTimes = new HashMap<>();
-            }
-            
-            // 记录区域滞留开始时间
-            if (!areaRetentionTimes.containsKey(areaName)) {
-                areaRetentionTimes.put(areaName, timestamp);
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 重置区域滞留时间
-     * 
-     * @param areaName 区域名称
-     */
-    public void resetAreaRetentionTime(String areaName) {
-        try {
-            lock.lock();
-            
-            if (areaRetentionTimes != null && areaRetentionTimes.containsKey(areaName)) {
-                areaRetentionTimes.remove(areaName);
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取区域滞留时间
-     * 
-     * @param areaName 区域名称
-     * @param currentTime 当前时间
-     * @return 滞留时间(毫秒)
-     */
-    public Long getAreaRetentionDuration(String areaName, Long currentTime) {
-        try {
-            lock.lock();
-            
-            if (areaRetentionTimes == null || !areaRetentionTimes.containsKey(areaName)) {
-                return 0L;
-            }
-            
-            Long startTime = areaRetentionTimes.get(areaName);
-            if (startTime == null) {
-                return 0L;
-            }
-            
-            return currentTime - startTime;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 添加告警计划
-     * 
-     * @param alarmPlan 告警计划
-     */
-    public void addAlarmPlan(AlarmPlan alarmPlan) {
-        try {
-            lock.lock();
-            
-            if (alarmPlan != null && alarmPlan.getName() != null) {
-                alarmPlanMap.put(alarmPlan.getName(), alarmPlan);
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 移除告警计划
-     * 
-     * @param planName 计划名称
-     * @return 被移除的告警计划
-     */
-    public AlarmPlan removeAlarmPlan(String planName) {
-        try {
-            lock.lock();
-            
-            return alarmPlanMap.remove(planName);
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取告警计划
-     * 
-     * @param planName 计划名称
-     * @return 告警计划
-     */
-    public AlarmPlan getAlarmPlan(String planName) {
-        try {
-            lock.lock();
-            
-            return alarmPlanMap.get(planName);
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取所有告警计划
-     * 
-     * @return 告警计划列表
-     */
-    public List<AlarmPlan> getAllAlarmPlans() {
-        try {
-            lock.lock();
-            
-            return new ArrayList<>(alarmPlanMap.values());
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 更新告警计划目标
-     * 
-     * @param targets 目标点列表
-     */
-    public void updateAlarmTargets(List<List<Float>> targets) {
-        if (targets == null || targets.isEmpty()) {
-            return;
-        }
-        
-        try {
-            lock.lock();
-            
-            long currentTime = System.currentTimeMillis();
-            
-            // 更新所有告警计划的目标
-            if (CollectionUtils.isEmpty(alarmPlanMap)) {
-                return;
-            }
-            for (AlarmPlan plan : alarmPlanMap.values()) {
-                plan.updateTarget(targets, currentTime);
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 检查所有告警计划
-     * 
-     * @return 需要触发告警的计划列表
-     */
-    public List<AlarmPlan> checkAlarmPlans() {
-        try {
-            lock.lock();
-            
-            List<AlarmPlan> alarmedPlans = new ArrayList<>();
-            long currentTime = System.currentTimeMillis();
-            
-            // 检查所有告警计划
-            for (AlarmPlan plan : alarmPlanMap.values()) {
-                if (plan.checkRetention(currentTime)) {
-                    alarmedPlans.add(plan);
-                }
-            }
-            
-            return alarmedPlans;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 添加区域
-     * 
-     * @param region 区域
-     */
-    public void addRegion(Region region) {
-        try {
-            lock.lock();
-            
-            if (region != null) {
-                // 检查是否已存在相同ID的区域
-                for (int i = 0; i < regions.size(); i++) {
-                    if (regions.get(i).getId().equals(region.getId())) {
-                        // 更新现有区域
-                        regions.set(i, region);
-                        return;
-                    }
-                }
-                
-                // 添加新区域
-                regions.add(region);
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 移除区域
-     * 
-     * @param regionId 区域ID
-     * @return 是否成功移除
-     */
-    public boolean removeRegion(String regionId) {
-        try {
-            lock.lock();
-            
-            for (int i = 0; i < regions.size(); i++) {
-                if (regions.get(i).getId().equals(regionId)) {
-                    regions.remove(i);
-                    return true;
-                }
-            }
-            
-            return false;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取区域
-     * 
-     * @param regionId 区域ID
-     * @return 区域
-     */
-    public Region getRegion(String regionId) {
-        try {
-            lock.lock();
-            
-            for (Region region : regions) {
-                if (region.getId().equals(regionId)) {
-                    return region;
-                }
-            }
-            
-            return null;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取所有区域
-     * 
-     * @return 区域列表
-     */
-    public List<Region> getAllRegions() {
-        try {
-            lock.lock();
-            
-            return new ArrayList<>(regions);
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 查找包含指定点的区域
-     * 
-     * @param x 点的x坐标
-     * @param y 点的y坐标
-     * @return 包含该点的区域列表
-     */
-    public List<Region> findRegionsContainingPoint(float x, float y) {
-        try {
-            lock.lock();
-            
-            List<Region> result = new ArrayList<>();
-            
-            for (Region region : regions) {
-                if (region.containsPoint(x, y)) {
-                    result.add(region);
-                }
-            }
-            
-            return result;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 更新告警配置
-     *
-     * @param retentionTime 停留时间阈值(毫秒)
-     * @param retentionKeepTime 停留保持时间(毫秒)
-     * @param retentionAlarmTime 停留告警时间(毫秒)
-     */
-    public void updateAlarmConfig(long retentionTime, long retentionKeepTime, long retentionAlarmTime) {
-        try {
-            lock.lock();
-            this.retentionTime = retentionTime;
-            this.retentionKeepTime = retentionKeepTime;
-            this.retentionAlarmTime = retentionAlarmTime;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 检查是否应该发送跌倒告警 (参考Python版本的deal_report_falling_event逻辑)
-     * @param currentTime 当前时间
-     * @return true如果应该发送告警
-     */
-    public boolean shouldSendFallAlarm(long currentTime) {
-        try {
-            lock.lock();
-            // 检查告警确认状态
-            if (Boolean.TRUE.equals(alarmAck)) {
-                return false;
-            }
-            
-            // 检查告警间隔
-            if (lastReportFallTime != null) {
-                long timeSinceLastAlarm = currentTime - lastReportFallTime;
-                if (timeSinceLastAlarm < alarmInterval) {
-                    return false;
-                }
-            }
-            
-            return true;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 检查心跳是否被调试参数拒绝 (参考Python版本的deal_dev_keepalive逻辑)
-     * @return true如果应该拒绝心跳
-     */
-    public boolean shouldRejectKeepAlive() {
-        try {
-            lock.lock();
-            Object keepaliveDebug = debugParams.get("keepalive");
-            return keepaliveDebug != null && Integer.valueOf(0).equals(keepaliveDebug);
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 设置设备参数信息
-     * 对应Python版本的set_param(self, param)方法
-     * @param param 完整的设备参数信息
-     */
-    public void setParam(Map<String, Object> param) {
-        try {
-            lock.lock();
-            this.param = param;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取设备参数信息
-     * 对应Python版本的param(self)方法
-     * @return 完整的设备参数信息
-     */
-    public Map<String, Object> getParam() {
-        try {
-            lock.lock();
-            return param;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 设置调试参数
-     * @param key 参数键
-     * @param value 参数值
-     */
-    public void setDebugParam(String key, Object value) {
-        try {
-            lock.lock();
-            debugParams.put(key, value);
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取调试参数
-     * @param key 参数键
-     * @return 参数值
-     */
-    public Object getDebugParam(String key) {
-        try {
-            lock.lock();
-            return debugParams.get(key);
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 检查停留时间并处理滞留告警 (参考Python版本的check_stay_time逻辑)
-     * @param currentTime 当前时间
-     * @return 如果检测到滞留事件返回滞留记录,否则返回null
-     */
-    public StayTimeRecord checkStayTime(long currentTime) {
-        try {
-            lock.lock();
-            
-            if (enterTs == null || enterTs == -1 || leaveTs == null || leaveTs == -1) {
-                return null;
-            }
-            
-            // 保留时间内,不认为停留事件结束
-            long timeSinceLeave = currentTime - leaveTs;
-            if (timeSinceLeave <= retentionKeepTime) {
-                return null;
-            }
-            
-            // 时间少于最小时间尺,忽略本次事件,并重置计时
-            long stayTimeMs = leaveTs - enterTs;
-            if (stayTimeMs < retentionTime) {
-                // 重置计时
-                this.enterTs = -1L;
-                this.leaveTs = -1L;
-                this.stayTime = -1L;
-                return null;
-            }
-            
-            // 创建停留时间记录
-            StayTimeRecord record = new StayTimeRecord();
-            record.setDevId(devId);
-            record.setEnterTime(enterTs);
-            record.setLeaveTime(leaveTs);
-            record.setStayTime(stayTimeMs);
-            
-            // 检查是否需要创建滞留告警 (超过3分钟视为异常滞留)
-            long stayTimeSeconds = stayTimeMs / 1000;
-            if (stayTimeSeconds >= (retentionAlarmTime / 1000)) {
-                record.setNeedAlarm(true);
-                record.setAlarmType("alarm_retention");
-                record.setAlarmDescription("设备滞留时间过长");
-            }
-            
-            // 重置计时
-            this.enterTs = -1L;
-            this.leaveTs = -1L;
-            this.stayTime = -1L;
-            
-            return record;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 检查告警确认是否超时 (参考Python版本的check_dev_alarm_ack逻辑)
-     * @param currentTime 当前时间
-     * @return true如果告警确认超时需要清除
-     */
-    public boolean shouldClearAlarmAck(long currentTime) {
-        try {
-            lock.lock();
-            if (Boolean.TRUE.equals(alarmAck) && lastAlarmAckTime != null) {
-                long timeSinceAck = currentTime - lastAlarmAckTime;
-                return timeSinceAck > alarmAckInterval;
-            }
-            return false;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 清除告警确认状态
-     */
-    public void clearAlarmAck() {
-        try {
-            lock.lock();
-            this.alarmAck = false;
-            this.lastAlarmAckTime = null;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-         /**
-      * 更新实时位置(平滑算法) - 重写以对应Python版本的update_targets方法
-      * @param newTargets 新的目标位置列表
-      * @return 稳定的目标位置列表
-      */
-     public List<List<Float>> updateTargets(List<List<Float>> newTargets) {
-        try {
-            lock.lock();
-            
-            // 对应Python版本的输入验证
-            if (newTargets == null || newTargets.isEmpty() || 
-                newTargets.get(0).size() < 3) {
-                // 对应Python: LOGERR(f"update_targets error: invalid new_targets")
-                return new ArrayList<>();
-            }
-            
-            // 对应Python: new_target = new_targets[0]
-            List<Float> newTarget = newTargets.get(0);
-            
-            // 对应Python: stable_target = self.stabilizer.update_target_list(new_target)
-            List<Float> stableTarget = stabilizer.updateTargetList(newTarget);
-            
-            // 更新targets字段
-            this.targets = stableTarget;
-            
-            // 对应Python: return [stable_target]
-            List<List<Float>> result = new ArrayList<>();
-            result.add(stableTarget);
-            return result;
-            
-        } catch (Exception e) {
-            // 对应Python: except Exception as e: LOGERR(f"update_targets error: {e}")
-            return new ArrayList<>();
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取实时姿态 (对应Python版本的realtime_pose方法)
-     * @return 实时姿态列表
-     */
-    public List<Integer> getRealtimePose() {
-        try {
-            lock.lock();
-            return realtimePose != null ? new ArrayList<>(realtimePose) : new ArrayList<>();
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 设置实时姿态 (对应Python版本的set_realtime_pose方法)
-     * @param pose 姿态列表
-     */
-    public void setRealtimePose(List<Integer> pose) {
-        try {
-            lock.lock();
-            this.realtimePose = pose != null ? new ArrayList<>(pose) : new ArrayList<>();
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取进入时间 (对应Python版本的enter_ts方法)
-     * @return 进入时间戳,如果未设置返回-1
-     */
-    public Long getEnterTime() {
-        try {
-            lock.lock();
-            return enterTs != null ? enterTs : -1L;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 设置进入时间 (对应Python版本的set_enter_ts方法)
-     * @param timestamp 时间戳
-     */
-    public void setEnterTime(Long timestamp) {
-        try {
-            lock.lock();
-            this.enterTs = timestamp;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取离开时间 (对应Python版本的leave_ts方法)
-     * @return 离开时间戳,如果未设置返回-1
-     */
-    public Long getLeaveTime() {
-        try {
-            lock.lock();
-            return leaveTs != null ? leaveTs : -1L;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 设置离开时间 (对应Python版本的set_leave_ts方法)
-     * @param timestamp 时间戳
-     */
-    public void setLeaveTime(Long timestamp) {
-        try {
-            lock.lock();
-            this.leaveTs = timestamp;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 检查告警间隔 (对应Python版本的告警间隔检查逻辑)
-     * @param eventType 事件类型
-     * @param currentTime 当前时间
-     * @return 是否应该发送告警
-     */
-    public boolean shouldSendAlarmForEvent(String eventType, Long currentTime) {
-        try {
-            lock.lock();
-            // 如果已经确认告警,则不发送
-            if (Boolean.TRUE.equals(alarmAck)) {
-                return false;
-            }
-            
-            // 检查告警间隔 (对应Python: now - device.last_fall_time(event) < device.alarm_interval())
-            Long lastEventTime = lastFallTimeByEvent.get(eventType);
-            if (lastEventTime != null && currentTime != null) {
-                long timeSinceLastAlarm = currentTime - lastEventTime;
-                return timeSinceLastAlarm >= (alarmInterval != null ? alarmInterval : 30000L); // 默认30秒间隔
-            }
-            
-            return true;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 设置最后跌倒时间 (对应Python版本的set_last_fall_time方法)
-     * @param eventType 事件类型
-     * @param timestamp 时间戳
-     */
-    public void setLastFallTime(String eventType, Long timestamp) {
-        try {
-            lock.lock();
-            this.lastReportFallTime = timestamp;
-            // 为每个事件类型单独记录时间 (对应Python版本的last_fall_time_[event] = time)
-            lastFallTimeByEvent.put(eventType, timestamp);
-            lastActivityTime.put("fall_" + eventType, timestamp);
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取指定事件类型的最后跌倒时间 (对应Python版本的last_fall_time(event))
-     * @param eventType 事件类型
-     * @return 最后跌倒时间,如果没有记录返回0
-     */
-    public Long getLastFallTime(String eventType) {
-        try {
-            lock.lock();
-            return lastFallTimeByEvent.getOrDefault(eventType, 0L);
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取当前跌倒状态 (对应Python版本的device.falling_)
-     * @return 跌倒状态:0-无跌倒,1-检测到跌倒,2-跌倒确认,3-跌倒呼救
-     */
-    public Integer getFalling() {
-        try {
-            lock.lock();
-            return falling_ != null ? falling_ : 0;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 设置当前跌倒状态 (对应Python版本的device.falling_)
-     * @param falling 跌倒状态:0-无跌倒,1-检测到跌倒,2-跌倒确认,3-跌倒呼救
-     */
-    public void setFalling(Integer falling) {
-        try {
-            lock.lock();
-            this.falling_ = falling;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 检查LNA设备的告警间隔 (对应Python版本的LNA特殊逻辑)
-     * 
-     * Python真实逻辑:
-     * - device.falling_字段永远为0(从不更新)
-     * - 当falling==0(无跌倒)时:falling_ == falling为true,检查报警间隔
-     * - 当falling!=0(有跌倒)时:falling_ == falling为false,跳过报警间隔检查,立即发送
-     * - 简化理解:只有无跌倒状态才检查报警间隔,任何跌倒状态都立即发送
-     * 
-     * @param newFalling 新的跌倒状态
-     * @param currentTime 当前时间
-     * @return 是否应该发送告警
-     */
-    public boolean shouldSendAlarmForLNA(Integer newFalling, Long currentTime) {
-        try {
-            lock.lock();
-            // 如果已经确认告警,则不发送
-            if (Boolean.TRUE.equals(alarmAck)) {
-                return false;
-            }
-            
-            // 对应Python逻辑:if device.falling_ == falling
-            // 由于falling_永远为0,所以只有当newFalling==0时才检查报警间隔
-            if (Objects.equals(falling_, newFalling)) {
-                // 检查报警间隔(使用lastReportFallTime,对应Python: device.last_report_fall_time())
-                if (lastReportFallTime != null && currentTime != null) {
-                    long timeSinceLastAlarm = currentTime - lastReportFallTime;
-                    return timeSinceLastAlarm >= (alarmInterval != null ? alarmInterval : 30000L);
-                }
-            }
-            
-            // 当falling_不等于newFalling时(即newFalling!=0时),或者没有历史时间时,直接发送
-            return true;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 根据设备类型处理跌倒事件 (参考Python版本的设备类型区分逻辑)
-     * @param event 事件类型
-     * @param pose 姿态
-     * @param location 位置坐标
-     * @return 处理结果
-     */
-    public FallEventResult processFallEvent(String event, int pose, List<Float> location) {
-        try {
-            lock.lock();
-            FallEventResult result = new FallEventResult();
-            result.setDevId(devId);
-            result.setEvent(event);
-            
-            if ("LNB".equals(devType)) {
-                // LNB设备的处理逻辑 (参考Python版本)
-                result.setPose("no_fall".equals(event) ? 4 : 0); // POSE_4 或 POSE_0
-                // 转换位置坐标格式 (参考Python版本的targets格式)
-                if (location != null && location.size() >= 3) {
-                    float[] targetPoint = {location.get(0)/100f, location.get(1)/100f, location.get(2)/100f};
-                    result.setLocation(targetPoint);
-                }
-                result.setShouldProcess(true);
-            } else if ("LNA".equals(devType)) {
-                // LNA设备的处理逻辑 (参考Python版本)
-                if (realtimePose == null || realtimePose.isEmpty() || !Integer.valueOf(0).equals(realtimePose.get(0))) {
-                    result.setShouldProcess(false);
-                    return result;
-                }
-                result.setPose(realtimePose.get(0));
-                // 转换位置坐标格式
-                if (location != null && location.size() >= 3) {
-                    float[] targetPoint = {location.get(0)/100f, location.get(1)/100f, location.get(2)/100f};
-                    result.setLocation(targetPoint);
-                }
-                result.setShouldProcess(true);
-            } else {
-                result.setShouldProcess(false);
-            }
-            
-            return result;
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 放入点云数据到队列 (对应Python版本的put_cloud_points_que方法)
-     * @param cloudPoints 点云数据
-     */
-    public void putCloudPointsQueue(List<List<Float>> cloudPoints) {
-        try {
-            lock.lock();
-            if (cloudPoints != null && !cloudPoints.isEmpty()) {
-                // 如果队列已满,移除最老的数据
-                while (cloudPointsQueue.size() >= MAX_CLOUD_POINTS_QUEUE_SIZE) {
-                    cloudPointsQueue.poll();
-                }
-                cloudPointsQueue.offer(new ArrayList<>(cloudPoints));
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取点云数据队列 (用于调试和分析)
-     * @return 点云数据队列的副本
-     */
-    public List<List<List<Float>>> getCloudPointsQueue() {
-        try {
-            lock.lock();
-            return new ArrayList<>(cloudPointsQueue);
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 清空点云数据队列
-     */
-    public void clearCloudPointsQueue() {
-        try {
-            lock.lock();
-            cloudPointsQueue.clear();
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 检查跌倒告警间隔 (对应Python版本的告警间隔检查逻辑)
-     * @param currentTime 当前时间
-     * @return true如果可以发送跌倒告警
-     */
-    public boolean checkFallAlarmInterval(Long currentTime) {
-        try {
-            lock.lock();
-            // 检查告警确认状态 (对应Python: device.get_alarm_ack())
-            if (Boolean.TRUE.equals(alarmAck)) {
-                return false;
-            }
-            
-            // 检查告警间隔 (对应Python: now - device.last_report_fall_time() < device.alarm_interval())
-            if (lastReportFallTime != null && currentTime != null) {
-                long timeSinceLastFall = currentTime - lastReportFallTime;
-                return timeSinceLastFall >= (alarmInterval != null ? alarmInterval : 30000L); // 默认30秒间隔
-            }
-            
-            return true; // 第一次跌倒或时间信息不完整时允许发送
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 设置调试参数集合 (对应应用层的setDebugParams需求)
-     * @param debugParams 调试参数集合
-     */
-    public void setDebugParams(Map<String, Object> debugParams) {
-        try {
-            lock.lock();
-            if (debugParams != null) {
-                this.debugParams.clear();
-                this.debugParams.putAll(debugParams);
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * 获取调试参数集合 (对应应用层的getDebugParams需求)
-     * @return 调试参数集合
-     */
-    public Map<String, Object> getDebugParams() {
-        try {
-            lock.lock();
-            return new HashMap<>(debugParams); // 返回副本确保线程安全
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * 停留时间记录
-     */
-    @Getter
-    @Setter
-    @NoArgsConstructor
-    @AllArgsConstructor
-    public static class StayTimeRecord {
-        private String devId;
-        private Long enterTime;
-        private Long leaveTime;
-        private Long stayTime;
-        private boolean needAlarm;
-        private String alarmType;
-        private String alarmDescription;
-    }
-    
-    /**
-     * 跌倒事件处理结果
-     */
-    @Getter
-    @Setter
-    @NoArgsConstructor
-    @AllArgsConstructor
-    public static class FallEventResult {
-        private String devId;
-        private String event;
-        private Integer pose;
-        private Object location;  // 修改为Object类型,匹配MqttGateway接口
-        private boolean shouldProcess;
-    }
-
-    /**
-     * 获取数据量最多的一组点云数据,然后清空cloud_points_que_ 
-     * (对应Python版本的get_max_len_cloud_points方法)
-     * @return 数据量最多的点云list,失败返回null
-     */
-    public List<List<Float>> getMaxLenCloudPoints() {
-        try {
-            lock.lock();
-            
-            // 对应Python: if self.dev_type_ == "LNB": return None
-            if ("LNB".equals(devType)) {
-                return null;
-            }
-            
-            // 对应Python: 取出数据量最多的的点云,成功返回点云list,失败返回None
-            int maxLen = 0;
-            List<List<Float>> maxLenList = null;
-            
-            // 对应Python: while not self.cloud_points_que_.empty():
-            while (!cloudPointsQueue.isEmpty()) {
-                List<List<Float>> currentList = cloudPointsQueue.poll();
-                // 对应Python: if len(current_list) >= max_len:
-                if (currentList != null && currentList.size() >= maxLen) {
-                    maxLen = currentList.size();
-                    maxLenList = currentList;
-                }
-            }
-            
-            return maxLenList;
-        } finally {
-            lock.unlock();
-        }
-    }
-} 
+//
+//            return true; // 第一次跌倒或时间信息不完整时允许发送
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 设置调试参数集合 (对应应用层的setDebugParams需求)
+//     * @param debugParams 调试参数集合
+//     */
+//    public void setDebugParams(Map<String, Object> debugParams) {
+//        try {
+//            lock.lock();
+//            if (debugParams != null) {
+//                this.debugParams.clear();
+//                this.debugParams.putAll(debugParams);
+//            }
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 获取调试参数集合 (对应应用层的getDebugParams需求)
+//     * @return 调试参数集合
+//     */
+//    public Map<String, Object> getDebugParams() {
+//        try {
+//            lock.lock();
+//            return new HashMap<>(debugParams); // 返回副本确保线程安全
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//
+//    /**
+//     * 停留时间记录
+//     */
+//    @Getter
+//    @Setter
+//    @NoArgsConstructor
+//    @AllArgsConstructor
+//    public static class StayTimeRecord {
+//        private String devId;
+//        private Long enterTime;
+//        private Long leaveTime;
+//        private Long stayTime;
+//        private boolean needAlarm;
+//        private String alarmType;
+//        private String alarmDescription;
+//    }
+//
+//    /**
+//     * 跌倒事件处理结果
+//     */
+//    @Getter
+//    @Setter
+//    @NoArgsConstructor
+//    @AllArgsConstructor
+//    public static class FallEventResult {
+//        private String devId;
+//        private String event;
+//        private Integer pose;
+//        private Object location;  // 修改为Object类型,匹配MqttGateway接口
+//        private boolean shouldProcess;
+//    }
+//
+//    /**
+//     * 获取数据量最多的一组点云数据,然后清空cloud_points_que_
+//     * (对应Python版本的get_max_len_cloud_points方法)
+//     * @return 数据量最多的点云list,失败返回null
+//     */
+//    public List<List<Float>> getMaxLenCloudPoints() {
+//        try {
+//            lock.lock();
+//
+//            // 对应Python: if self.dev_type_ == "LNB": return None
+//            if ("LNB".equals(devType)) {
+//                return null;
+//            }
+//
+//            // 对应Python: 取出数据量最多的的点云,成功返回点云list,失败返回None
+//            int maxLen = 0;
+//            List<List<Float>> maxLenList = null;
+//
+//            // 对应Python: while not self.cloud_points_que_.empty():
+//            while (!cloudPointsQueue.isEmpty()) {
+//                List<List<Float>> currentList = cloudPointsQueue.poll();
+//                // 对应Python: if len(current_list) >= max_len:
+//                if (currentList != null && currentList.size() >= maxLen) {
+//                    maxLen = currentList.size();
+//                    maxLenList = currentList;
+//                }
+//            }
+//
+//            return maxLenList;
+//        } finally {
+//            lock.unlock();
+//        }
+//    }
+//}

+ 0 - 15
device-service-domain/src/main/java/com/hfln/device/domain/gateway/sms/SmsGateway.java

@@ -1,15 +0,0 @@
-package com.hfln.device.domain.gateway.sms;
-
-/**
- * 验证码相关
- */
-public interface SmsGateway {
-
-    Boolean sendLoginSmsCode(String phone);
-
-
-    Boolean sendSignupSmsCode(String phone);
-
-
-
-}

+ 8 - 0
device-service-domain/src/main/java/com/hfln/device/domain/service/DeviceManagerService.java

@@ -3,6 +3,7 @@ package com.hfln.device.domain.service;
 import com.hfln.device.domain.entity.Device;
 
 import java.util.Collection;
+import java.util.Map;
 import java.util.Optional;
 
 /**
@@ -29,6 +30,13 @@ public interface DeviceManagerService {
      * @param device 设备对象
      */
     void updateDeviceInCache(Device device);
+
+    /**
+     * 更新设备缓存
+     * @param devId 设备ID
+     * @param map   设备更新属性
+     */
+    default void updateDeviceMapInCache(String devId, Map<String, Object> map) {};
     
     /**
      * 从缓存中删除设备

+ 1 - 1
device-service-domain/src/main/java/com/hfln/device/domain/service/impl/DeviceManagerServiceImpl.java

@@ -19,7 +19,7 @@ import org.springframework.stereotype.Service;
  * 负责设备状态管理、保活检查等功能
  */
 @Slf4j
-@Service
+//@Service
 public class DeviceManagerServiceImpl implements DeviceManagerService {
 
     /**

+ 138 - 32
device-service-domain/src/main/java/com/hfln/device/domain/service/impl/DeviceRedisManagerServiceImpl.java

@@ -1,15 +1,15 @@
 package com.hfln.device.domain.service.impl;
 
-import cn.hfln.framework.common.redis.service.RedisService;
+import cn.hfln.framework.redis.util.RedisUtil;
 import com.hfln.device.common.constant.redis.RedisCacheConstant;
 import com.hfln.device.domain.constant.DeviceConstants;
 import com.hfln.device.domain.entity.Device;
-import com.hfln.device.domain.entity.DeviceCache;
 import com.hfln.device.domain.service.DeviceManagerService;
 import com.hfln.device.domain.service.DeviceStatusService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -22,7 +22,7 @@ import java.util.concurrent.ConcurrentHashMap;
  * 负责设备状态管理、保活检查等功能
  */
 @Slf4j
-@Service
+@Service("deviceRedisManagerService")
 public class DeviceRedisManagerServiceImpl implements DeviceManagerService {
 
     /**
@@ -34,20 +34,107 @@ public class DeviceRedisManagerServiceImpl implements DeviceManagerService {
     private DeviceStatusService deviceStatusService;
 
     @Autowired
-    private RedisService redisService;
+    private RedisUtil redisService;
 
+    @Override
+    public Optional<Device> getDeviceFromCache(String devId) {
 
-    public Optional<Device> xx(String devId) {
+        Map<Object, Object> deviceMap = redisService.hGetAll(RedisCacheConstant.KEY_DEVICE_pre + devId);
+        if (CollectionUtils.isEmpty(deviceMap)) {
+            return Optional.empty();
+        }
 
+        Device device = new Device();
+        if (deviceMap.get("devId") != null) {
+            device.setDevId(deviceMap.get("devId").toString());
+        }
+        if (deviceMap.get("devType") != null) {
+            device.setDevType(deviceMap.get("devType").toString());
+        }
+        if (deviceMap.get("software") != null) {
+            device.setSoftware(deviceMap.get("software").toString());
+        }
+        if (deviceMap.get("hardware") != null) {
+            device.setHardware(deviceMap.get("hardware").toString());
+        }
+        if (deviceMap.get("bluVer") != null) {
+            device.setBluVer(deviceMap.get("bluVer").toString());
+        }
 
+        Device.NetworkInfo network = new Device.NetworkInfo();
+        if (deviceMap.get("ssid") != null) {
+            network.setSsid(deviceMap.get("ssid").toString());
+        }
+        if (deviceMap.get("ip") != null) {
+            network.setIp(deviceMap.get("ip").toString());
+        }
+        if (deviceMap.get("password") != null) {
+            network.setPassword(deviceMap.get("password").toString());
+        }
+        device.setNetwork(network);
 
-        return Optional.ofNullable(deviceCache.get(devId));
-    }
+        Device.InstallParam installParam = new Device.InstallParam();
+        if (deviceMap.get("mountPlain") != null) {
+            installParam.setMountPlain(deviceMap.get("mountPlain").toString());
+        }
+        if (deviceMap.get("isCeiling") != null) {
+            installParam.setIsCeiling(Integer.parseInt(deviceMap.get("isCeiling").toString()));
+        }
+        if (deviceMap.get("height") != null) {
+            installParam.setHeight(Float.parseFloat(deviceMap.get("height").toString()));
+        }
+        Device.TrackingRegion trackingRegion = new Device.TrackingRegion();
+        if (deviceMap.get("startX") != null) {
+            trackingRegion.setStartX(Integer.parseInt(deviceMap.get("startX").toString()));
+        }
+        if (deviceMap.get("startY") != null) {
+            trackingRegion.setStartY(Integer.parseInt(deviceMap.get("startY").toString()));
+        }
+        if (deviceMap.get("startZ") != null) {
+            trackingRegion.setStartZ(Integer.parseInt(deviceMap.get("startZ").toString()));
+        }
+        if (deviceMap.get("stopX") != null) {
+            trackingRegion.setStopX(Integer.parseInt(deviceMap.get("stopX").toString()));
+        }
+        if (deviceMap.get("stopY") != null) {
+            trackingRegion.setStopY(Integer.parseInt(deviceMap.get("stopY").toString()));
+        }
+        if (deviceMap.get("stopZ") != null) {
+            trackingRegion.setStopZ(Integer.parseInt(deviceMap.get("stopZ").toString()));
+        }
+        installParam.setTrackingRegion(trackingRegion);
+        device.setInstallParam(installParam);
 
+        if (deviceMap.get("online") != null) {
+            device.setOnline(Integer.parseInt(deviceMap.get("online").toString()));
+        }
+        if (deviceMap.get("keepAliveTime") != null) {
+            device.setKeepaliveTime(Long.parseLong(deviceMap.get("keepAliveTime").toString()));
+        }
+        if (deviceMap.get("expireTime") != null) {
+            device.setKeepaliveTime(Long.parseLong(deviceMap.get("expireTime").toString()));
+        }
 
-    @Override
-    public Optional<Device> getDeviceFromCache(String devId) {
-        return Optional.ofNullable(deviceCache.get(devId));
+        if (deviceMap.get("lastReportFallTime") != null) {
+            device.setLastReportFallTime(Long.parseLong(deviceMap.get("lastReportFallTime").toString()));
+        }
+        if (deviceMap.get("alarmInterval") != null) {
+            device.setAlarmInterval(Long.parseLong(deviceMap.get("alarmInterval").toString()));
+        }
+        if (deviceMap.get("alarmAck") != null) {
+            device.setAlarmAck(Boolean.parseBoolean(deviceMap.get("alarmAck").toString()));
+        }
+        if (deviceMap.get("lastAlarmAckTime") != null) {
+            device.setLastAlarmAckTime(Long.parseLong(deviceMap.get("lastAlarmAckTime").toString()));
+        }
+        if (deviceMap.get("alarmAckInterval") != null) {
+            device.setAlarmAckInterval(Long.parseLong(deviceMap.get("alarmAckInterval").toString()));
+        }
+        if (deviceMap.get("falling") != null) {
+            device.setFalling(Integer.valueOf(deviceMap.get("falling").toString()));
+        }
+
+        return Optional.ofNullable(device);
     }
 
     /**
@@ -56,7 +143,6 @@ public class DeviceRedisManagerServiceImpl implements DeviceManagerService {
      * @param device 设备信息
      */
     public void addDeviceToCache(Device device) {
-//        deviceCache.put(device.getDevId(), device);
 
         // 设置redis 存储设备的 hash对象的属性
         Map<String, Object> deviceMap = new HashMap<>();
@@ -67,7 +153,6 @@ public class DeviceRedisManagerServiceImpl implements DeviceManagerService {
         deviceMap.put("software", device.getSoftware());
         deviceMap.put("hardware", device.getHardware());
         deviceMap.put("bluVer", device.getBluVer());
-        deviceMap.put("online", device.getOnline());
 
         // 添加网络信息
         if (device.getNetwork() != null) {
@@ -111,7 +196,7 @@ public class DeviceRedisManagerServiceImpl implements DeviceManagerService {
         // 告警时间间隔(毫秒),默认30秒
         deviceMap.put("alarmInterval", device.getAlarmInterval());
         // 告警确认
-        deviceMap.put("alarmAck", device.getAlarmAck());
+        deviceMap.put("alarmAck", String.valueOf(device.getAlarmAck()));
         // 最后告警确认时间
         deviceMap.put("lastAlarmAckTime", device.getLastAlarmAckTime());
         // 告警确认时间间间隔(毫秒),默认5分钟
@@ -123,8 +208,8 @@ public class DeviceRedisManagerServiceImpl implements DeviceManagerService {
 //        deviceMap.put(RedisCacheConstant.KEY_DEVICE_DEBUG_PARAM_PRE + "", device.getDebugParam(""));
 
 
-        redisService.setNx(RedisCacheConstant.KEY_DEVICE + device.getDevId(), device);
-        redisService.setCacheMap(RedisCacheConstant.KEY_DEVICE + device.getDevId(), deviceMap);
+        redisService.sAdd(RedisCacheConstant.KEY_DEVICE_ID, device.getDevId());
+        redisService.hSetAll(RedisCacheConstant.KEY_DEVICE_pre + device.getDevId(), deviceMap);
         log.info("Device added to cache: {}", device.getDevId());
     }
 
@@ -134,10 +219,20 @@ public class DeviceRedisManagerServiceImpl implements DeviceManagerService {
         log.debug("Device updated in cache: {}", device.getDevId());
     }
 
+    public void updateDeviceMapInCache(String devId, Map<String, Object> map) {
+
+        redisService.hSetAll(RedisCacheConstant.KEY_DEVICE_pre + devId, map);
+        log.debug("Device updated in cache: {}", devId);
+    }
+
     @Override
     public void removeDeviceFromCache(String devId) {
 
-        redisService.deleteObject(RedisCacheConstant.KEY_DEVICE + devId);
+        if (redisService.sIsMember(RedisCacheConstant.KEY_DEVICE_ID, devId)) {
+
+            redisService.sRemove(RedisCacheConstant.KEY_DEVICE_ID, devId);
+            redisService.del(RedisCacheConstant.KEY_DEVICE_pre + devId);
+        }
         log.info("Device removed from cache: {}", devId);
     }
 
@@ -166,22 +261,33 @@ public class DeviceRedisManagerServiceImpl implements DeviceManagerService {
      */
     @Override
     public void checkDeviceAlarmAck(long currentTimeMillis, long timeoutMillis) {
-        deviceCache.forEach((devId, device) -> {
-            // 只检查未确认的告警
-            if (device.getAlarmAck() != null && !device.getAlarmAck()) {
-                Long lastAckTime = device.getLastAlarmAckTime();
-                
-                // 如果有告警且超时未确认,则自动确认
-                if (lastAckTime != null && (currentTimeMillis - lastAckTime) > timeoutMillis) {
-                    log.info("Device alarm auto acknowledge: {}, last alarm: {}", devId, lastAckTime);
-                    device.setAlarmAcknowledgement(true, currentTimeMillis);
-                    updateDeviceInCache(device);
-                    
-                    // 更新数据库中的告警确认状态
-                    // 这里应该调用相应的网关方法
-                }
-            }
-        });
+
+//        Set<Object> devIdSet = redisService.sMembers(RedisCacheConstant.KEY_DEVICE_ID);
+//        if (CollectionUtils.isEmpty(devIdSet)) {
+//            log.info("No devices in cache");
+//            return;
+//        }
+//
+//        for (Object devId : devIdSet) {
+//            redisService.hGet(RedisCacheConstant.KEY_DEVICE_pre + devId, "alarmAck")
+//        }
+//
+//        deviceCache.forEach((devId, device) -> {
+//            // 只检查未确认的告警
+//            if (device.getAlarmAck() != null && !device.getAlarmAck()) {
+//                Long lastAckTime = device.getLastAlarmAckTime();
+//
+//                // 如果有告警且超时未确认,则自动确认
+//                if (lastAckTime != null && (currentTimeMillis - lastAckTime) > timeoutMillis) {
+//                    log.info("Device alarm auto acknowledge: {}, last alarm: {}", devId, lastAckTime);
+//                    device.setAlarmAcknowledgement(true, currentTimeMillis);
+//                    updateDeviceInCache(device);
+//
+//                    // 更新数据库中的告警确认状态
+//                    // 这里应该调用相应的网关方法
+//                }
+//            }
+//        });
     }
 
     /**

+ 44 - 0
device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/config/FastJson2JsonRedisSerializer.java

@@ -0,0 +1,44 @@
+package com.hfln.device.infrastructure.config;//package cn.hfln.framework.common.redis;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONReader;
+import com.alibaba.fastjson2.JSONWriter;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+
+import java.nio.charset.Charset;
+
+/**
+ * Redis使用FastJson序列化
+ *
+ * @author cw
+ */
+public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
+    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
+
+    private Class<T> clazz;
+
+
+    public FastJson2JsonRedisSerializer(Class<T> clazz) {
+        super();
+        this.clazz = clazz;
+    }
+
+    @Override
+    public byte[] serialize(T t) throws SerializationException {
+        if (t == null) {
+            return new byte[0];
+        }
+        return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
+    }
+
+    @Override
+    public T deserialize(byte[] bytes) throws SerializationException {
+        if (bytes == null || bytes.length <= 0) {
+            return null;
+        }
+        String str = new String(bytes, DEFAULT_CHARSET);
+
+        return JSON.parseObject(str, clazz, JSONReader.Feature.SupportAutoType);
+    }
+}

+ 32 - 0
device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/config/RedisConfig.java

@@ -0,0 +1,32 @@
+package com.hfln.device.infrastructure.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * Redis 配置类
+ * 手动注册 RedisTemplate,确保与自研 Redis Starter 兼容
+ */
+@Configuration
+public class RedisConfig {
+
+    @Bean
+    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
+        RedisTemplate<String, Object> template = new RedisTemplate<>();
+        template.setConnectionFactory(connectionFactory);
+
+        // 使用 StringRedisSerializer 进行序列化
+        StringRedisSerializer stringSerializer = new StringRedisSerializer();
+        FastJson2JsonRedisSerializer jsonSerializer = new FastJson2JsonRedisSerializer<>(Object.class);
+        template.setKeySerializer(stringSerializer);
+        template.setValueSerializer(jsonSerializer);
+        template.setHashKeySerializer(stringSerializer);
+        template.setHashValueSerializer(jsonSerializer);
+
+        template.afterPropertiesSet();
+        return template;
+    }
+}

+ 0 - 204
device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/gateway/impl/UserGatewayImpl.java

@@ -1,204 +0,0 @@
-package com.hfln.device.infrastructure.gateway.impl;
-
-
-
-import cn.hfln.framework.common.redis.service.RedisService;
-import cn.hfln.framework.extension.BizException;
-import com.alibaba.fastjson2.JSONObject;
-import com.hfln.device.common.constant.redis.RedisCacheConstant;
-import com.hfln.device.common.dto.data.user.UserDto;
-import com.hfln.device.common.request.user.LoginBySmsCodeParams;
-import com.hfln.device.common.request.user.UserLoginParams;
-import com.hfln.device.common.request.user.UserSignupParams;
-import com.hfln.device.common.request.user.UserUpdatePasswordParams;
-import com.hfln.device.domain.customer.util.PasswordUtil;
-import com.hfln.device.domain.exception.ErrorEnum;
-import com.hfln.device.domain.gateway.UserGateway;
-import com.hfln.device.infrastructure.mapper.UserInfoMapper;
-import com.hfln.device.infrastructure.po.UserInfo;
-import com.hfln.device.infrastructure.service.UserService;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.BeanUtils;
-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.stereotype.Service;
-import org.springframework.web.client.RestTemplate;
-
-import java.util.Objects;
-
-@Service
-@Slf4j
-public class UserGatewayImpl implements UserGateway {
-
-    @Autowired
-    private RestTemplate restTemplate;
-
-    @Autowired
-    private RedisService redisService;
-
-    @Autowired
-    private UserInfoMapper userInfoMapper;
-
-    @Autowired
-    private UserService userService;
-
-    @Value("${lnxx.wechat.appid}")
-    private String appid;
-
-    @Value("${lnxx.wechat.secret}")
-    private String secret;
-
-
-
-
-    public static String WXX_CX_ACCESS_TOKEN = "";
-
-    @Override
-    public String getOpenId(String code) {
-        if (StringUtils.isEmpty(code)) {
-            throw new BizException(ErrorEnum.WECHAT_CODE_ISNULL.getErrorCode(), ErrorEnum.WECHAT_CODE_ISNULL.getErrorMessage());
-        }
-        String url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", appid, secret, code);
-        try {
-            String res = restTemplate.getForObject(url, String.class);
-            JSONObject obj = JSONObject.parseObject(res);
-            return Objects.requireNonNull(obj).getString("openid");
-        } catch (Exception e) {
-            log.error("微信登录接口异常", e);
-            throw new BizException(ErrorEnum.WECHAT_INTERFACE_CALL_EXCEPTION.getErrorCode(), ErrorEnum.WECHAT_INTERFACE_CALL_EXCEPTION.getErrorMessage());
-        }
-    }
-
-    @Override
-    public Boolean signup(UserSignupParams request) {
-        //校验验证码
-        String cacheCode = redisService.getCacheObject(RedisCacheConstant.SMS_SIGNUP_CODE + request.getPhone());
-        if (Objects.isNull(cacheCode)) {
-            throw new BizException(ErrorEnum.SMS_CODE_EXPIRED.getErrorCode(), ErrorEnum.SMS_CODE_EXPIRED.getErrorMessage());
-        }
-        if (!Objects.equals(cacheCode, request.getCode())) {
-            throw new BizException(ErrorEnum.SMS_CODE_ERROR.getErrorCode(), ErrorEnum.SMS_CODE_ERROR.getErrorMessage());
-
-        }
-        if (checkOpenId(request.getOpenId())) {
-            throw new BizException(ErrorEnum.USER_ALREADY_EXISTS.getErrorCode(), ErrorEnum.USER_ALREADY_EXISTS.getErrorMessage());
-        }
-        // 验证通过 清除验证码入库
-        redisService.deleteObject(RedisCacheConstant.SMS_SIGNUP_CODE + request.getPhone());
-        UserInfo user = new UserInfo();
-        user.setPhone(request.getPhone());
-        String encryptedPassword = PasswordUtil.encrypt(request.getPassword());
-        user.setPassword(encryptedPassword);
-        user.setOpenid(request.getOpenId());
-        userInfoMapper.insert(user);
-        return true;
-    }
-
-
-    @Override
-    public Boolean checkOpenId(String openId) {
-        return userService.checkOpenId(openId);
-    }
-
-    @Override
-    public UserDto loginBySmsCode(LoginBySmsCodeParams request) {
-        UserDto userDto = new UserDto();
-        String phone = request.getUserName();
-        UserInfo user = userService.checkUserByPassword(phone, null);
-        if (Objects.nonNull(user)) {
-            String cacheSmsCode = redisService.getCacheObject(RedisCacheConstant.SMS_LOGIN_CODE + phone);
-            if (Objects.isNull(cacheSmsCode)) {
-                throw new BizException(ErrorEnum.SMS_CODE_EXPIRED.getErrorCode(), ErrorEnum.SMS_CODE_EXPIRED.getErrorMessage());
-            }
-            if (!Objects.equals(request.getSmsCode(), cacheSmsCode)) {
-                throw new BizException(ErrorEnum.SMS_CODE_ERROR.getErrorCode(), ErrorEnum.SMS_CODE_ERROR.getErrorMessage());
-            }
-            redisService.deleteObject(RedisCacheConstant.SMS_LOGIN_CODE + phone);
-        }
-        BeanUtils.copyProperties(user, userDto);
-        userDto.setUserId(user.getUserInfoId()
-        );
-
-        /*
-        通过sa-token获取token
-         */
-        return userDto;
-    }
-
-
-    @Override
-    public UserDto loginByPassword(UserLoginParams request) {
-        UserDto userDto = new UserDto();
-        UserInfo user = userService.checkUserByPassword(request.getUserName(), request.getPassword());
-        if (Objects.isNull(user)) {
-            throw new BizException(ErrorEnum.USERNAME_OR_PASSWORD_ERROR.getErrorCode(), ErrorEnum.USERNAME_OR_PASSWORD_ERROR.getErrorMessage());
-        }
-        BeanUtils.copyProperties(user, userDto);
-        userDto.setUserId(user.getUserInfoId());
-        return userDto;
-    }
-
-
-    @Override
-    public String getUserPhone(String code) {
-        if (StringUtils.isEmpty(code)) {
-            throw new BizException(ErrorEnum.WECHAT_CODE_ISNULL.getErrorCode(), ErrorEnum.WECHAT_CODE_ISNULL.getErrorMessage());
-        }
-        try {
-            String url = String.format("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s", WXX_CX_ACCESS_TOKEN);
-
-            // 构建请求体
-            JSONObject param = new JSONObject();
-            param.put("code", code);
-
-            HttpHeaders headers = new HttpHeaders();
-            headers.setContentType(MediaType.APPLICATION_JSON);
-            HttpEntity<String> request = new HttpEntity<>(param.toJSONString(), headers);
-
-            // 发起请求
-            String response = restTemplate.postForObject(url, request, String.class);
-            JSONObject json = JSONObject.parseObject(response);
-
-            // 判断微信返回是否成功
-            if (Objects.requireNonNull(json).getIntValue("errcode") == 0) {
-                return json.getJSONObject("phone_info").getString("phoneNumber");
-            } else {
-                log.error("获取手机号失败,微信返回:{}", json.toJSONString());
-                throw new BizException(ErrorEnum.WECHAT_INTERFACE_CALL_EXCEPTION.getErrorCode(), ErrorEnum.WECHAT_INTERFACE_CALL_EXCEPTION.getErrorMessage());
-            }
-        } catch (Exception e) {
-            log.error("调用微信接口异常", e);
-            throw new BizException(ErrorEnum.WECHAT_INTERFACE_CALL_EXCEPTION.getErrorCode(), ErrorEnum.WECHAT_INTERFACE_CALL_EXCEPTION.getErrorMessage());
-        }
-    }
-
-    @Override
-    // @MqttSubscribes(value = {})
-    public void test() {
-//        mqttPublisher.send("test", "test1");
-    }
-
-
-    @Override
-    public void updatePassword(UserUpdatePasswordParams request) {
-        if (request.getNewPassword().equals(request.getOldPassword())) {
-            throw new BizException(ErrorEnum.PASSWORD_IS_REPEAT.getErrorCode(), ErrorEnum.PASSWORD_IS_REPEAT.getErrorMessage());
-        }
-
-        UserInfo userInfo = userService.getById(request.getUserId());
-        if (Objects.isNull(userInfo)) {
-            throw new BizException(ErrorEnum.USER_IS_NOT_EXIST.getErrorCode(), ErrorEnum.USER_IS_NOT_EXIST.getErrorMessage());
-        }
-        if (!PasswordUtil.matches(request.getOldPassword(), userInfo.getPassword())) {
-            throw new BizException(ErrorEnum.OLD_PASSWORD_ERROR.getErrorCode(), ErrorEnum.OLD_PASSWORD_ERROR.getErrorMessage());
-        }
-        UserInfo info = new UserInfo();
-        info.setUserInfoId(request.getUserId());
-        info.setPassword(request.getNewPassword());
-        userService.updateById(userInfo);
-    }
-}

+ 0 - 65
device-service-infrastructure/src/main/java/com/hfln/device/infrastructure/gateway/impl/sms/SmsGatewayImpl.java

@@ -1,65 +0,0 @@
-package com.hfln.device.infrastructure.gateway.impl.sms;
-
-import cn.hfln.framework.common.redis.service.RedisService;
-import cn.hfln.framework.extension.BizException;
-import com.hfln.device.common.constant.redis.RedisCacheConstant;
-import com.hfln.device.domain.customer.util.MsgClient;
-import com.hfln.device.domain.exception.ErrorEnum;
-import com.hfln.device.domain.gateway.sms.SmsGateway;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.Objects;
-import java.util.concurrent.TimeUnit;
-
-@Service
-public class SmsGatewayImpl implements SmsGateway {
-
-
-    @Autowired
-    private MsgClient msgClient;
-
-    @Autowired
-    private RedisService redisService;
-
-
-    @Override
-    public Boolean sendLoginSmsCode(String phone) {
-        // 限制短信发送不超过一分钟一次
-        String key = RedisCacheConstant.SMS_SEND_LOGIN_TIME + phone;
-        Boolean hasKey = redisService.hasKey(key);
-        if (hasKey) {
-            throw new BizException(ErrorEnum.FREQUENT_SMS_SENDING.getErrorCode(), ErrorEnum.FREQUENT_SMS_SENDING.getErrorMessage());
-        }
-        redisService.setCacheObject(key, 1, 1L, TimeUnit.MINUTES);
-        int captcha = (int) ((Math.random() * 9 + 1) * 1000);
-        String sentLoginMsg = msgClient.sendLoginMsg(phone, String.valueOf(captcha));
-        if (Objects.nonNull(sentLoginMsg)) {
-            // 存入redis  过期时间十分钟
-            redisService.setCacheObject(RedisCacheConstant.SMS_LOGIN_CODE + phone, captcha,10L, TimeUnit.MINUTES);
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public Boolean sendSignupSmsCode(String phone) {
-        // 限制短信发送不超过一分钟一次
-        String key = RedisCacheConstant.SMS_SEND_SIGNUP_TIME + phone;
-        Boolean hasKey = redisService.hasKey(key);
-        if (hasKey) {
-            throw new BizException(ErrorEnum.FREQUENT_SMS_SENDING.getErrorCode(), ErrorEnum.FREQUENT_SMS_SENDING.getErrorMessage());
-        }
-        int captcha = (int) ((Math.random() * 9 + 1) * 1000);
-        String sentLoginMsg = msgClient.sendRegisterMsg(phone, String.valueOf(captcha));
-        if (Objects.nonNull(sentLoginMsg)) {
-            // 存入redis  过期时间十分钟
-            redisService.setCacheObject(RedisCacheConstant.SMS_SIGNUP_CODE + phone, captcha,10L, TimeUnit.MINUTES);
-            return true;
-        }
-        return false;
-    }
-
-
-
-}

+ 2 - 2
device-service-server/src/main/java/com/hfln/device/server/DeviceApplication.java

@@ -1,7 +1,7 @@
 package com.hfln.device.server;
 
 import cn.hfln.framework.common.jackson.JacksonConfiguration;
-import cn.hfln.framework.common.redis.RedisConfig;
+
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -20,7 +20,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
 @EnableFeignClients(basePackages = "com.hfln.device.client.api")
 @SpringBootApplication(
     scanBasePackages = {"com.hfln.device.**"}, 
-    scanBasePackageClasses = {RedisConfig.class, JacksonConfiguration.class}
+    scanBasePackageClasses = {JacksonConfiguration.class}
 )
 @ComponentScan(
     basePackages = {"com.hfln.device.**"}

+ 0 - 2
device-service-server/src/main/resources/application-local.yml → device-service-server/src/main/resources/bootstrap-local.yml

@@ -1,6 +1,4 @@
 spring:
-  config:
-    import: "optional:nacos:"
   cloud:
     nacos:
       discovery:

+ 1 - 1
device-service-server/src/main/resources/bootstrap.yml

@@ -7,7 +7,7 @@ spring:
     pathmatch:
       matching-strategy: ant_path_matcher
   profiles:
-    active: test
+    active: local
   application:
     name: device-service-server
 

+ 5 - 0
pom.xml

@@ -68,6 +68,11 @@
             </dependency>
             <dependency>
                 <groupId>cn.hfln.framework</groupId>
+                <artifactId>redis-spring-boot-starter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>cn.hfln.framework</groupId>
                 <artifactId>knife4j-doc-spring-boot-starter</artifactId>
                 <version>${project.version}</version>
             </dependency>