|
@@ -1,17 +1,18 @@
|
|
package com.hfln.device.application.service.impl;
|
|
package com.hfln.device.application.service.impl;
|
|
|
|
|
|
import com.hfln.device.application.service.DeviceEventService;
|
|
import com.hfln.device.application.service.DeviceEventService;
|
|
-import com.hfln.device.domain.constant.EventConstants;
|
|
|
|
|
|
+import com.hfln.device.application.service.DebugConfigService;
|
|
import com.hfln.device.domain.entity.Device;
|
|
import com.hfln.device.domain.entity.Device;
|
|
import com.hfln.device.domain.gateway.DeviceGateway;
|
|
import com.hfln.device.domain.gateway.DeviceGateway;
|
|
import com.hfln.device.domain.gateway.MqttGateway;
|
|
import com.hfln.device.domain.gateway.MqttGateway;
|
|
import com.hfln.device.domain.service.AlarmService;
|
|
import com.hfln.device.domain.service.AlarmService;
|
|
-import com.hfln.device.domain.service.BehaviorAnalysisService;
|
|
|
|
import com.hfln.device.domain.service.DeviceManagerService;
|
|
import com.hfln.device.domain.service.DeviceManagerService;
|
|
import com.hfln.device.domain.service.PointCloudProcessService;
|
|
import com.hfln.device.domain.service.PointCloudProcessService;
|
|
|
|
+import com.hfln.device.domain.service.BehaviorAnalysisService;
|
|
|
|
+import com.hfln.device.domain.debug.DebugConfig;
|
|
import com.hfln.device.domain.vo.BehaviorPattern;
|
|
import com.hfln.device.domain.vo.BehaviorPattern;
|
|
-import com.hfln.device.domain.vo.PoseAnalysisResult;
|
|
|
|
import com.hfln.device.domain.vo.TargetPoint;
|
|
import com.hfln.device.domain.vo.TargetPoint;
|
|
|
|
+import com.hfln.device.domain.constant.EventConstants;
|
|
import com.hfln.device.common.util.JsonUtil;
|
|
import com.hfln.device.common.util.JsonUtil;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
@@ -54,6 +55,9 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
@Autowired
|
|
@Autowired
|
|
private BehaviorAnalysisService behaviorAnalysisService;
|
|
private BehaviorAnalysisService behaviorAnalysisService;
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
+ private DebugConfigService debugConfigService;
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public boolean registerDevice(Device device) {
|
|
public boolean registerDevice(Device device) {
|
|
log.info("注册设备: deviceId={}", device.getDevId());
|
|
log.info("注册设备: deviceId={}", device.getDevId());
|
|
@@ -261,24 +265,85 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
* 对应Python版本的deal_dev_keepalive方法
|
|
* 对应Python版本的deal_dev_keepalive方法
|
|
*
|
|
*
|
|
* Python处理流程:
|
|
* Python处理流程:
|
|
- * 1. 检查设备是否已注册和在线状态
|
|
|
|
- * 2. 更新设备的最后保活时间戳(last_keepalive_time)
|
|
|
|
- * 3. 如果设备当前离线状态,则:
|
|
|
|
- * - 设置设备为在线状态
|
|
|
|
- * - 更新数据库状态
|
|
|
|
- * - 发送设备状态变更消息到MQTT
|
|
|
|
- * 4. 发送心跳响应消息给设备
|
|
|
|
- * 5. 不进行复杂业务逻辑,主要用于维持连接状态
|
|
|
|
|
|
+ * 1. 从主题中提取设备ID
|
|
|
|
+ * 2. 检查调试参数是否禁用keepalive(可选的调试控制)
|
|
|
|
+ * 3. 检查设备是否已注册到系统中
|
|
|
|
+ * 4. 根据设备状态设置不同的响应码:
|
|
|
|
+ * - 已注册且在线:DEV_EC.succeed,更新保活时间
|
|
|
|
+ * - 已注册但离线:DEV_EC.forbidden
|
|
|
|
+ * - 未注册:DEV_EC.unauthorized
|
|
|
|
+ * 5. 发送保活响应给设备
|
|
|
|
+ * 6. 异步更新数据库中的在线状态
|
|
*/
|
|
*/
|
|
@Override
|
|
@Override
|
|
public void handleDeviceKeepAlive(String deviceId) {
|
|
public void handleDeviceKeepAlive(String deviceId) {
|
|
log.info("处理设备保活事件: deviceId={}", deviceId);
|
|
log.info("处理设备保活事件: deviceId={}", deviceId);
|
|
|
|
|
|
- // TODO: 实现保活逻辑
|
|
|
|
- // 1. 检查设备是否存在
|
|
|
|
- // 2. 更新保活时间戳
|
|
|
|
- // 3. 更新在线状态(如果需要)
|
|
|
|
- // 4. 发送保活响应
|
|
|
|
|
|
+ try {
|
|
|
|
+ // 1. 检查调试参数(参考Python版本的调试控制机制)
|
|
|
|
+ DebugConfig debugConfig = debugConfigService.getDebugConfig(deviceId);
|
|
|
|
+ if (debugConfig != null && debugConfig.getParams() != null) {
|
|
|
|
+ Object keepaliveParam = debugConfig.getParams().get("keepalive");
|
|
|
|
+ if (keepaliveParam != null && "0".equals(keepaliveParam.toString())) {
|
|
|
|
+ log.debug("拒绝保活请求,调试参数禁用: deviceId={}", deviceId);
|
|
|
|
+ return; // 调试模式下拒绝保活
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 2. 检查设备是否已注册(参考Python版本的设备注册检查)
|
|
|
|
+ Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
|
|
+ int responseCode;
|
|
|
|
+
|
|
|
|
+ if (deviceOpt.isPresent()) {
|
|
|
|
+ // 设备已注册
|
|
|
|
+ Device device = deviceOpt.get();
|
|
|
|
+
|
|
|
|
+ // 3. 检查设备在线状态(参考Python版本的在线状态判断)
|
|
|
|
+ if (Integer.valueOf(1).equals(device.getOnline())) {
|
|
|
|
+ // 设备在线,保活成功
|
|
|
|
+ responseCode = 0; // 对应Python版本的DEV_EC.succeed
|
|
|
|
+
|
|
|
|
+ // 4. 更新保活时间戳(参考Python版本的device.set_keepalive())
|
|
|
|
+ long currentTime = System.currentTimeMillis();
|
|
|
|
+ device.updateKeepAliveTime(currentTime);
|
|
|
|
+
|
|
|
|
+ // 更新设备缓存
|
|
|
|
+ deviceManagerService.updateDeviceInCache(device);
|
|
|
|
+
|
|
|
|
+ log.debug("设备保活成功: deviceId={}, keepaliveTime={}", deviceId, currentTime);
|
|
|
|
+ } else {
|
|
|
|
+ // 设备离线,保活被拒绝
|
|
|
|
+ responseCode = 403; // 对应Python版本的DEV_EC.forbidden
|
|
|
|
+ log.warn("设备离线,保活被拒绝: deviceId={}", deviceId);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ // 设备未注册,未授权
|
|
|
|
+ responseCode = 401; // 对应Python版本的DEV_EC.unauthorized
|
|
|
|
+ log.warn("设备未注册,保活未授权: deviceId={}", deviceId);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 5. 发送保活响应(参考Python版本的mqtt_send.resp_dev_keepalive())
|
|
|
|
+ mqttGateway.sendDeviceKeepAliveResponse(deviceId, responseCode);
|
|
|
|
+
|
|
|
|
+ // 6. 异步更新数据库在线状态(参考Python版本的异步数据库更新)
|
|
|
|
+ // 只有成功的保活才更新数据库在线状态
|
|
|
|
+ if (responseCode == 0) {
|
|
|
|
+ deviceGateway.updateDeviceOnlineStatus(deviceId, 1);
|
|
|
|
+ log.debug("异步更新设备在线状态: deviceId={}, online=1", deviceId);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ log.info("设备保活处理完成: deviceId={}, responseCode={}", deviceId, responseCode);
|
|
|
|
+
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("处理设备保活异常: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
|
|
+
|
|
|
|
+ // 异常情况下发送错误响应
|
|
|
|
+ try {
|
|
|
|
+ mqttGateway.sendDeviceKeepAliveResponse(deviceId, 500); // 服务器内部错误
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
+ log.error("发送保活错误响应失败: deviceId={}", deviceId, ex);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@@ -322,7 +387,10 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
}
|
|
}
|
|
|
|
|
|
// 发送事件消息 (参考Python版本:只有满足条件才发送事件消息)
|
|
// 发送事件消息 (参考Python版本:只有满足条件才发送事件消息)
|
|
- mqttGateway.sendEventMessage(deviceId, result.getPose(), result.getLocation(), result.getEvent());
|
|
|
|
|
|
+ List<List<Float>> targets = result.getLocation() instanceof List ?
|
|
|
|
+ Collections.singletonList((List<Float>) result.getLocation()) :
|
|
|
|
+ Collections.emptyList();
|
|
|
|
+ mqttGateway.sendEventMessage(deviceId, Collections.emptyList(), result.getPose(), targets, result.getEvent());
|
|
|
|
|
|
// 更新最后跌倒告警时间
|
|
// 更新最后跌倒告警时间
|
|
device.setLastReportFallTime(timestamp);
|
|
device.setLastReportFallTime(timestamp);
|
|
@@ -448,7 +516,8 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
deviceGateway.recordEvent(deviceId, event, pose, targetPoint);
|
|
deviceGateway.recordEvent(deviceId, event, pose, targetPoint);
|
|
|
|
|
|
// 发送事件消息
|
|
// 发送事件消息
|
|
- mqttGateway.sendEventMessage(deviceId, pose, targetPoint, event);
|
|
|
|
|
|
+ List<List<Float>> targets = Collections.singletonList(targetPoint);
|
|
|
|
+ mqttGateway.sendEventMessage(deviceId, Collections.emptyList(), pose, targets, event);
|
|
|
|
|
|
// 如果是跌倒事件,处理跌倒逻辑
|
|
// 如果是跌倒事件,处理跌倒逻辑
|
|
if (EventConstants.EventType.FALL_EVENT.equals(event)) {
|
|
if (EventConstants.EventType.FALL_EVENT.equals(event)) {
|
|
@@ -791,160 +860,156 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * 处理设备参数上报
|
|
|
|
- * 对应Python版本的deal_report_device_param方法
|
|
|
|
|
|
+ * 处理设备实时数据
|
|
|
|
+ * 对应Python版本的deal_dsp_data方法
|
|
*
|
|
*
|
|
* Python处理流程:
|
|
* Python处理流程:
|
|
- * 1. 解析消息数据,获取设备参数信息
|
|
|
|
- * 2. 验证参数格式和合法性
|
|
|
|
- * 3. 更新设备参数配置到数据库
|
|
|
|
- * 4. 记录参数变更历史
|
|
|
|
- * 5. 发送参数更新确认消息
|
|
|
|
- * 6. 如果是关键参数变更,触发相关业务逻辑
|
|
|
|
|
|
+ * 1. 解析DSP(数字信号处理)实时数据
|
|
|
|
+ * 2. 提取目标位置、姿态、生命体征等信息
|
|
|
|
+ * 3. 执行实时数据验证和过滤
|
|
|
|
+ * 4. 更新设备实时状态缓存
|
|
|
|
+ * 5. 触发实时告警检测逻辑
|
|
|
|
+ * 6. 发送实时位置姿态消息到指定MQTT主题
|
|
|
|
+ * 7. 记录关键数据到时序数据库(如有配置)
|
|
*/
|
|
*/
|
|
@Override
|
|
@Override
|
|
- public void handleDeviceParamReport(String deviceId, Map<String, Object> messageData) {
|
|
|
|
- log.info("处理设备参数上报: deviceId={}", deviceId);
|
|
|
|
|
|
+ public void handleDspData(String deviceId, Map<String, Object> messageData) {
|
|
|
|
+ log.debug("处理设备实时数据: deviceId={}", deviceId);
|
|
|
|
|
|
try {
|
|
try {
|
|
- // 获取设备
|
|
|
|
|
|
+ // === 获取设备 (对应Python: with g_dev_map_lock: if dev_id not in g_dev_map) ===
|
|
Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
if (!deviceOpt.isPresent()) {
|
|
if (!deviceOpt.isPresent()) {
|
|
- log.warn("设备不存在,无法处理参数上报: deviceId={}", deviceId);
|
|
|
|
- return;
|
|
|
|
|
|
+ return; // 未注册的设备,不处理 (对应Python: return)
|
|
}
|
|
}
|
|
|
|
|
|
- Device device = deviceOpt.get();
|
|
|
|
-
|
|
|
|
- // 按照Python版本解析字段
|
|
|
|
- Map<String, Object> deviceInfo = (Map<String, Object>) messageData.get("device_info");
|
|
|
|
- Map<String, Object> sensorLocation = (Map<String, Object>) messageData.get("sensor_location");
|
|
|
|
- Map<String, Object> extRegion = (Map<String, Object>) messageData.get("ext_region");
|
|
|
|
- Map<String, Object> fallingStateMachineDurations = (Map<String, Object>) messageData.get("fallingStateMachineDurations");
|
|
|
|
- Boolean is45Degree = (Boolean) messageData.get("is45Degree");
|
|
|
|
- Boolean isCeiling = (Boolean) messageData.get("isCeiling");
|
|
|
|
|
|
+ Device device = deviceOpt.get(); // device:Device = g_dev_map[dev_id]
|
|
|
|
|
|
- // 更新设备信息
|
|
|
|
- if (deviceInfo != null) {
|
|
|
|
- String bluVer = (String) deviceInfo.get("blu_ver");
|
|
|
|
- String deviceType = (String) deviceInfo.get("device_type");
|
|
|
|
- String software = (String) deviceInfo.get("firmware");
|
|
|
|
- String deviceid = (String) deviceInfo.get("deviceid");
|
|
|
|
|
|
+ // === 处理tracker_targets (对应Python: if ("tracker_targets" in payload)) ===
|
|
|
|
+ if (messageData.containsKey("tracker_targets")) {
|
|
|
|
+ List<List<Number>> trackerTargets = (List<List<Number>>) messageData.get("tracker_targets");
|
|
|
|
|
|
- device.setBluVer(bluVer);
|
|
|
|
- device.setDevType(deviceType);
|
|
|
|
- device.setSoftware(software);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // 更新安装参数
|
|
|
|
- if (sensorLocation != null && extRegion != null) {
|
|
|
|
- Float sensorHeight = ((Number) sensorLocation.get("z_cm")).floatValue();
|
|
|
|
- if (device.getInstallParam() == null) {
|
|
|
|
- device.setInstallParam(new Device.InstallParam());
|
|
|
|
- }
|
|
|
|
- device.getInstallParam().setHeight(sensorHeight);
|
|
|
|
|
|
+ // 转换数据类型为Float
|
|
|
|
+ List<List<Float>> trackerTargetsFloat = trackerTargets.stream()
|
|
|
|
+ .map(target -> target.stream()
|
|
|
|
+ .map(number -> number.floatValue())
|
|
|
|
+ .collect(Collectors.toList()))
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
|
- // 更新区域信息
|
|
|
|
- Map<String, Object> base = (Map<String, Object>) extRegion.get("base");
|
|
|
|
- if (base != null) {
|
|
|
|
- if (device.getInstallParam().getTrackingRegion() == null) {
|
|
|
|
- device.getInstallParam().setTrackingRegion(new Device.TrackingRegion());
|
|
|
|
- }
|
|
|
|
- Device.TrackingRegion region = device.getInstallParam().getTrackingRegion();
|
|
|
|
-
|
|
|
|
- region.setStartX(((Number) base.get("x_cm_start")).intValue());
|
|
|
|
- region.setStopX(((Number) base.get("x_cm_stop")).intValue());
|
|
|
|
- region.setStartY(((Number) base.get("y_cm_start")).intValue());
|
|
|
|
- region.setStopY(((Number) base.get("y_cm_stop")).intValue());
|
|
|
|
- region.setStartZ(((Number) base.get("z_cm_start")).intValue());
|
|
|
|
- region.setStopZ(((Number) base.get("z_cm_stop")).intValue());
|
|
|
|
|
|
+ // === 更新实时点云和target (对应Python的核心逻辑) ===
|
|
|
|
+ List<List<Float>> rawPoints = Collections.emptyList(); // raw_points = []
|
|
|
|
+ List<List<Float>> targets = trackerTargetsFloat; // targets = tracker_targets
|
|
|
|
+ List<List<Float>> stableTargets = device.updateTargets(targets); // stable_targets:list = device.update_targets(targets)
|
|
|
|
+ List<Integer> pose = device.getRealtimePose(); // pose = device.realtime_pose()
|
|
|
|
+
|
|
|
|
+ // === 发送实时位置姿态消息 (对应Python: mqtt_send.realtime_pos_msg(dev_id, raw_points, pose, targets)) ===
|
|
|
|
+ mqttGateway.sendRealtimePositionMessage(deviceId, rawPoints, pose, targets);
|
|
|
|
+
|
|
|
|
+ // === 更新停留时长 (对应Python的时间更新逻辑) ===
|
|
|
|
+ long ts = System.currentTimeMillis(); // ts = get_utc_time_ms()
|
|
|
|
+ if (device.getEnterTime() < 0) { // if device.enter_ts() < 0:
|
|
|
|
+ device.setEnterTime(ts); // device.set_enter_ts(ts)
|
|
|
|
+ log.info("{} target enter, {}", deviceId, ts); // LOGINFO(f"{dev_id} target enter, {ts}")
|
|
}
|
|
}
|
|
|
|
+ device.setLeaveTime(ts); // device.set_leave_ts(ts)
|
|
|
|
+
|
|
|
|
+ // === 更新报警目标信息 (对应Python: device.update_alarm_targets(targets)) ===
|
|
|
|
+ device.updateAlarmTargets(trackerTargetsFloat);
|
|
|
|
+
|
|
|
|
+ log.debug("处理tracker_targets完成: deviceId={}, targetCount={}", deviceId, trackerTargetsFloat.size());
|
|
}
|
|
}
|
|
|
|
|
|
- // 保存完整参数信息 (TODO: 在Device类中实现setParam方法)
|
|
|
|
- // device.setParam(messageData);
|
|
|
|
-
|
|
|
|
- // 更新设备
|
|
|
|
- deviceGateway.updateDevice(device);
|
|
|
|
- deviceManagerService.updateDeviceInCache(device);
|
|
|
|
-
|
|
|
|
- // 发送设备信息更新消息 (TODO: 在MqttGateway中实现此方法)
|
|
|
|
- // mqttGateway.sendUpdateDeviceInfoMessage(device);
|
|
|
|
|
|
+ // === 检查跌倒信息 (对应Python: if ("fallingMetaData" in payload): check_falling(msg)) ===
|
|
|
|
+ if (messageData.containsKey("fallingMetaData")) {
|
|
|
|
+ handleFallingCheck(deviceId, messageData);
|
|
|
|
+ }
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
- log.error("处理设备参数上报异常: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
|
|
|
|
+ // 对应Python: except Exception as e: LOGERR(f"deal_dsp_data error: {e}, [{dev_id}]")
|
|
|
|
+ log.error("deal_dsp_data error: {}, [{}]", e.getMessage(), deviceId, e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * 处理设备实时数据
|
|
|
|
- * 对应Python版本的deal_dsp_data方法
|
|
|
|
|
|
+ * 处理跌倒检查
|
|
|
|
+ * 对应Python版本的check_falling方法的核心逻辑
|
|
*
|
|
*
|
|
- * Python处理流程:
|
|
|
|
- * 1. 解析DSP(数字信号处理)实时数据
|
|
|
|
- * 2. 提取目标位置、姿态、生命体征等信息
|
|
|
|
- * 3. 执行实时数据验证和过滤
|
|
|
|
- * 4. 更新设备实时状态缓存
|
|
|
|
- * 5. 触发实时告警检测逻辑
|
|
|
|
- * 6. 发送实时位置姿态消息到指定MQTT主题
|
|
|
|
- * 7. 记录关键数据到时序数据库(如有配置)
|
|
|
|
|
|
+ * @param deviceId 设备ID
|
|
|
|
+ * @param messageData 消息数据,包含fallingMetaData
|
|
*/
|
|
*/
|
|
- @Override
|
|
|
|
- public void handleDspData(String deviceId, Map<String, Object> messageData) {
|
|
|
|
- log.debug("处理设备实时数据: deviceId={}", deviceId);
|
|
|
|
-
|
|
|
|
|
|
+ private void handleFallingCheck(String deviceId, Map<String, Object> messageData) {
|
|
try {
|
|
try {
|
|
- // 获取设备
|
|
|
|
Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
if (!deviceOpt.isPresent()) {
|
|
if (!deviceOpt.isPresent()) {
|
|
- return; // 未注册的设备,不处理
|
|
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
Device device = deviceOpt.get();
|
|
Device device = deviceOpt.get();
|
|
|
|
+ Map<String, Object> fallingMetaData = (Map<String, Object>) messageData.get("fallingMetaData");
|
|
|
|
+
|
|
|
|
+ if (fallingMetaData == null || !fallingMetaData.containsKey("falling")) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // === 跌倒状态映射 (对应Python的falling_map) ===
|
|
|
|
+ Map<Integer, String> fallingMap = new HashMap<>();
|
|
|
|
+ fallingMap.put(0, "no_fall"); // 没有检测到跌倒
|
|
|
|
+ fallingMap.put(1, "fall_detected"); // 检测到跌倒
|
|
|
|
+ fallingMap.put(2, "fall_confirmed"); // 跌倒确认
|
|
|
|
+ fallingMap.put(3, "fall_calling"); // 跌倒呼救
|
|
|
|
+
|
|
|
|
+ Integer falling = ((Number) fallingMetaData.get("falling")).intValue();
|
|
|
|
+ String event = fallingMap.getOrDefault(falling, "unknown");
|
|
|
|
+
|
|
|
|
+ // 获取跌倒位置坐标
|
|
|
|
+ Float fallLocXCm = ((Number) fallingMetaData.get("fallLocX_cm")).floatValue();
|
|
|
|
+ Float fallLocYCm = ((Number) fallingMetaData.get("fallLocY_cm")).floatValue();
|
|
|
|
+ Float fallLocZCm = ((Number) fallingMetaData.get("fallLocZ_cm")).floatValue();
|
|
|
|
|
|
- // 处理tracker_targets
|
|
|
|
- if (messageData.containsKey("tracker_targets")) {
|
|
|
|
- List<List<Number>> trackerTargets = (List<List<Number>>) messageData.get("tracker_targets");
|
|
|
|
-
|
|
|
|
- // 转换数据类型
|
|
|
|
- List<List<Float>> trackerTargetsFloat = trackerTargets.stream()
|
|
|
|
- .map(target -> target.stream()
|
|
|
|
- .map(number -> number.floatValue())
|
|
|
|
- .collect(Collectors.toList()))
|
|
|
|
- .collect(Collectors.toList());
|
|
|
|
-
|
|
|
|
- // TODO: 在Device类中实现这些方法
|
|
|
|
- // 更新设备目标信息
|
|
|
|
- // List<List<Float>> stableTargets = device.updateTargets(trackerTargetsFloat);
|
|
|
|
- // List<Integer> pose = device.getRealtimePose();
|
|
|
|
-
|
|
|
|
- // TODO: 在MqttGateway中实现此方法
|
|
|
|
- // 发送实时位置姿态消息
|
|
|
|
- // mqttGateway.sendRealtimePositionMessage(deviceId, Collections.emptyList(), pose, trackerTargetsFloat);
|
|
|
|
-
|
|
|
|
- // TODO: 在Device类中实现这些方法
|
|
|
|
- // 更新停留时长
|
|
|
|
- // long ts = System.currentTimeMillis();
|
|
|
|
- // if (device.getEnterTime() < 0) {
|
|
|
|
- // device.setEnterTime(ts);
|
|
|
|
- // log.info("{} target enter, {}", deviceId, ts);
|
|
|
|
- // }
|
|
|
|
- // device.setLeaveTime(ts);
|
|
|
|
-
|
|
|
|
- // 更新报警目标信息
|
|
|
|
- // device.updateAlarmTargets(trackerTargetsFloat);
|
|
|
|
-
|
|
|
|
- log.debug("处理tracker_targets完成: deviceId={}, targetCount={}", deviceId, trackerTargetsFloat.size());
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // TODO: 实现handleFallingCheck方法
|
|
|
|
- // 检查跌倒信息
|
|
|
|
- // if (messageData.containsKey("fallingMetaData")) {
|
|
|
|
- // handleFallingCheck(deviceId, messageData);
|
|
|
|
- // }
|
|
|
|
|
|
+ long now = System.currentTimeMillis(); // now = get_utc_time_ms()
|
|
|
|
+
|
|
|
|
+ // === 上报跌倒事件 (对应Python的设备类型处理逻辑) ===
|
|
|
|
+ if ("LNB".equals(device.getDevType())) {
|
|
|
|
+ // === LNB设备处理逻辑 ===
|
|
|
|
+ // 检查报警间隔 (对应Python的告警间隔检查)
|
|
|
|
+ if (!device.shouldSendAlarmForEvent(event, now)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ List<List<Float>> targets = Arrays.asList(Arrays.asList(fallLocXCm, fallLocYCm, fallLocZCm, 0.0f));
|
|
|
|
+ int pose = "no_fall".equals(event) ? 4 : 0; // POSE_E.POSE_4.value if event == "no_fall" else POSE_E.POSE_0.value
|
|
|
|
+
|
|
|
|
+ // 发送事件消息 (对应Python: mqtt_send.event_msg)
|
|
|
|
+ mqttGateway.sendEventMessage(deviceId, Collections.emptyList(), pose, targets, event);
|
|
|
|
+
|
|
|
|
+ device.setLastFallTime(event, now); // device.set_last_fall_time(event, now)
|
|
|
|
+ String text = String.format("设备上报跌倒事件:躺, dev_id:%s, event:%s", deviceId, event);
|
|
|
|
+ log.debug(text); // LOGDBG(text)
|
|
|
|
+
|
|
|
|
+ } else if ("LNA".equals(device.getDevType())) {
|
|
|
|
+ // === LNA设备处理逻辑 ===
|
|
|
|
+ // 跌倒状态改变时,不管报警间隔直接发送通知 (对应Python的特殊逻辑)
|
|
|
|
+ if (!device.shouldSendAlarmForLNA(falling, now)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ List<Integer> realtimePose = device.getRealtimePose(); // realtime_pose:list = device.realtime_pose()
|
|
|
|
+ if (realtimePose.isEmpty() || !Integer.valueOf(0).equals(realtimePose.get(0))) {
|
|
|
|
+ return; // if (len(realtime_pose) <= 0 or realtime_pose[0] != POSE_E.POSE_0.value): return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ List<List<Float>> targets = Arrays.asList(Arrays.asList(fallLocXCm, fallLocYCm, fallLocZCm, 0.0f));
|
|
|
|
+
|
|
|
|
+ // 发送事件消息
|
|
|
|
+ mqttGateway.sendEventMessage(deviceId, Collections.emptyList(), realtimePose.get(0).intValue(), targets, event);
|
|
|
|
+
|
|
|
|
+ device.setLastReportFallTime(now); // device.set_last_report_fall_time(now)
|
|
|
|
+ String text = String.format("设备上报跌倒事件:躺, dev_id:%s, event:%s", deviceId, event);
|
|
|
|
+ log.debug(text); // LOGDBG(text)
|
|
|
|
+ }
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
- log.error("处理设备实时数据异常: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
|
|
|
|
+ log.error("处理跌倒检查异常: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -967,50 +1032,85 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
log.debug("处理设备点云数据: deviceId={}", deviceId);
|
|
log.debug("处理设备点云数据: deviceId={}", deviceId);
|
|
|
|
|
|
try {
|
|
try {
|
|
- // 获取设备
|
|
|
|
|
|
+ // === 获取设备 (对应Python: with g_dev_map_lock: if dev_id not in g_dev_map) ===
|
|
Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
if (!deviceOpt.isPresent()) {
|
|
if (!deviceOpt.isPresent()) {
|
|
- return; // 未注册的设备,不处理
|
|
|
|
|
|
+ return; // 未注册的设备,不处理 (对应Python: return)
|
|
}
|
|
}
|
|
|
|
|
|
- Device device = deviceOpt.get();
|
|
|
|
|
|
+ Device device = deviceOpt.get(); // device:Device = g_dev_map[dev_id]
|
|
|
|
|
|
- // 对于LNA设备类型,检查点云数量
|
|
|
|
- if ("LNA".equals(device.getDevType())) {
|
|
|
|
- int valuePoints = 20;
|
|
|
|
- if (cloudPoints == null || cloudPoints.size() < valuePoints) {
|
|
|
|
- return; // 少于n个点则忽略
|
|
|
|
|
|
+ // === 设备类型处理逻辑 (对应Python的设备类型区分) ===
|
|
|
|
+ List<List<Float>> rawPoints = null; // 初始化为null,模拟Python的未定义状态
|
|
|
|
+ List<List<Float>> targets = null; // 初始化为null,模拟Python的未定义状态
|
|
|
|
+
|
|
|
|
+ if ("LNA".equals(device.getDevType())) { // 对应Python: if device.dev_type() == "LNA"
|
|
|
|
+ int valuePoints = 20; // 对应Python: value_points = 20
|
|
|
|
+ if (cloudPoints == null || cloudPoints.size() < valuePoints) {
|
|
|
|
+ // 对应Python: # LOGDBG(f"warning: payload: cloud_points len < {value_points}, dev:{dev_id}")
|
|
|
|
+ log.debug("warning: payload: cloud_points len < {}, dev:{}", valuePoints, deviceId);
|
|
|
|
+ return; // 对应Python: if len(payload["cloud_points"]) < value_points: return
|
|
}
|
|
}
|
|
|
|
+ rawPoints = cloudPoints; // 对应Python: raw_points = payload["cloud_points"]
|
|
|
|
|
|
- // 如果没有tracker_targets,从点云计算 (TODO: 实现getTrackerTargets方法)
|
|
|
|
- if (trackerTargets == null) {
|
|
|
|
- // trackerTargets = pointCloudProcessService.getTrackerTargets(cloudPoints);
|
|
|
|
- trackerTargets = Collections.emptyList(); // 临时处理
|
|
|
|
|
|
+ // 目标点信息处理 (对应Python的目标点逻辑)
|
|
|
|
+ if (trackerTargets == null || trackerTargets.isEmpty()) {
|
|
|
|
+ // 对应Python: if(not "tracker_targets" in payload): targets = get_tracker_targets(raw_points)
|
|
|
|
+ targets = pointCloudProcessService.getTrackerTargets(rawPoints);
|
|
|
|
+ log.debug("从点云计算得到 {} 个目标", targets.size());
|
|
|
|
+ } else {
|
|
|
|
+ // 对应Python: else: targets = payload["tracker_targets"]
|
|
|
|
+ targets = trackerTargets;
|
|
|
|
+ // ⚠️ 重要:对应Python版本的第325行,这行代码在Python中确实会执行!
|
|
|
|
+ List<List<Float>> tmpTargets = pointCloudProcessService.getTrackerTargets(rawPoints);
|
|
|
|
+ // tmpTargets虽然计算了但不使用,完全匹配Python版本行为
|
|
}
|
|
}
|
|
- } else if ("LNB".equals(device.getDevType())) {
|
|
|
|
- // 对于LNB设备,必须有tracker_targets
|
|
|
|
- if (trackerTargets == null) {
|
|
|
|
- return;
|
|
|
|
|
|
+
|
|
|
|
+ } else if ("LNB".equals(device.getDevType())) { // 对应Python: elif device.dev_type() == "LNB"
|
|
|
|
+ if (trackerTargets == null || trackerTargets.isEmpty()) {
|
|
|
|
+ return; // 对应Python: if not "tracker_targets" in payload: return
|
|
}
|
|
}
|
|
- cloudPoints = Collections.emptyList(); // LNB设备不需要点云数据
|
|
|
|
|
|
+ rawPoints = Collections.emptyList(); // 对应Python: raw_points = []
|
|
|
|
+ targets = trackerTargets; // 对应Python: targets = payload["tracker_targets"]
|
|
}
|
|
}
|
|
|
|
+ // ⚠️ 重要:Python版本没有else分支!
|
|
|
|
+ // 如果设备类型未知,Python版本会在后续代码中抛出NameError异常
|
|
|
|
+ // 为了完全匹配Python行为,这里也不应该有else分支
|
|
|
|
+
|
|
|
|
+ // 检查变量是否已初始化(模拟Python版本的潜在NameError)
|
|
|
|
+ if (rawPoints == null || targets == null) {
|
|
|
|
+ // 对应Python版本的NameError: name 'raw_points' is not defined
|
|
|
|
+ throw new RuntimeException("Uninitialized variables: rawPoints or targets not set for device type: " + device.getDevType());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // === 核心业务处理 (对应Python的核心逻辑) ===
|
|
|
|
+ // 更新实时点云和target (对应Python: device.put_cloud_points_que(raw_points))
|
|
|
|
+ device.putCloudPointsQueue(rawPoints);
|
|
|
|
+
|
|
|
|
+ // 更新目标跟踪 (对应Python: stable_targets:list = device.update_targets(targets))
|
|
|
|
+ List<List<Float>> stableTargets = device.updateTargets(targets);
|
|
|
|
|
|
- // TODO: 在Device类中实现这些方法
|
|
|
|
- // 更新实时点云和target
|
|
|
|
- // device.putCloudPointsQueue(cloudPoints);
|
|
|
|
- // List<List<Float>> stableTargets = device.updateTargets(trackerTargets);
|
|
|
|
- // List<Integer> pose = device.getRealtimePose();
|
|
|
|
|
|
+ // 获取实时姿态 (对应Python: pose = device.realtime_pose())
|
|
|
|
+ List<Integer> pose = device.getRealtimePose();
|
|
|
|
|
|
- // TODO: 在MqttGateway中实现此方法
|
|
|
|
- // 发送实时位置姿态消息
|
|
|
|
- // mqttGateway.sendRealtimePositionMessage(deviceId, cloudPoints, pose, trackerTargets);
|
|
|
|
|
|
+ // === 发送实时位置姿态消息 (对应Python: mqtt_send.realtime_pos_msg(dev_id, raw_points, pose, targets)) ===
|
|
|
|
+ mqttGateway.sendRealtimePositionMessage(deviceId, rawPoints, pose, targets);
|
|
|
|
|
|
- log.debug("处理点云数据完成: deviceId={}, cloudPointsSize={}, trackerTargetsSize={}",
|
|
|
|
- deviceId, cloudPoints != null ? cloudPoints.size() : 0,
|
|
|
|
- trackerTargets != null ? trackerTargets.size() : 0);
|
|
|
|
|
|
+ log.debug("处理点云数据完成: deviceId={}, devType={}, cloudPointsSize={}, trackerTargetsSize={}, targetsUsed={}",
|
|
|
|
+ deviceId, device.getDevType(),
|
|
|
|
+ cloudPoints != null ? cloudPoints.size() : 0,
|
|
|
|
+ trackerTargets != null ? trackerTargets.size() : 0,
|
|
|
|
+ targets.size());
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
- log.error("处理设备点云数据异常: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
|
|
|
|
+ // 对应Python的分层异常处理:
|
|
|
|
+ // except json.JSONDecodeError: LOGERR(f"parse payload failed, {msg.topic}, {msg.payload}")
|
|
|
|
+ // except Exception as e: LOGERR(f"deal_cloudpoint error: {e}, [{dev_id}]")
|
|
|
|
+ if (e.getCause() instanceof com.fasterxml.jackson.core.JsonProcessingException) {
|
|
|
|
+ log.error("parse payload failed, deviceId: {}, error: {}", deviceId, e.getMessage(), e);
|
|
|
|
+ } else {
|
|
|
|
+ log.error("deal_cloudpoint error: {}, [{}]", e.getMessage(), deviceId, e);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1021,55 +1121,65 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
deviceId, event, fallLocX, fallLocY, fallLocZ);
|
|
deviceId, event, fallLocX, fallLocY, fallLocZ);
|
|
|
|
|
|
try {
|
|
try {
|
|
- // 获取设备
|
|
|
|
|
|
+ // === 获取设备 (对应Python: with g_dev_map_lock: if dev_id not in g_dev_map) ===
|
|
Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
if (!deviceOpt.isPresent()) {
|
|
if (!deviceOpt.isPresent()) {
|
|
- log.warn("设备未注册,无法处理跌倒事件: deviceId={}", deviceId);
|
|
|
|
|
|
+ log.debug("error, device not registed: {}", deviceId); // 对应Python: LOGDBG(f"error, device not registed: {dev_id}")
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- Device device = deviceOpt.get();
|
|
|
|
|
|
+ Device device = deviceOpt.get(); // device:Device = g_dev_map[dev_id]
|
|
|
|
|
|
- // TODO: 在Device类中实现告警间隔检查方法
|
|
|
|
- // 检查报警间隔
|
|
|
|
- long now = System.currentTimeMillis();
|
|
|
|
- // Device.FallEventResult fallResult = device.checkFallAlarmInterval(event, now);
|
|
|
|
- // if (!fallResult.shouldSendAlarm()) {
|
|
|
|
- // log.debug("跌倒事件被告警间隔控制过滤: deviceId={}, event={}", deviceId, event);
|
|
|
|
- // return;
|
|
|
|
- // }
|
|
|
|
-
|
|
|
|
- // 构建目标点
|
|
|
|
- List<Float> targetPoint = Arrays.asList(fallLocX, fallLocY, fallLocZ, 0.0f);
|
|
|
|
- List<List<Float>> targets = Collections.singletonList(targetPoint);
|
|
|
|
-
|
|
|
|
- // TODO: 修正MqttGateway.sendEventMessage方法签名
|
|
|
|
- // 根据设备类型处理
|
|
|
|
|
|
+ // === 检查告警间隔 (对应Python的告警间隔检查逻辑) ===
|
|
|
|
+ long now = System.currentTimeMillis(); // now = get_utc_time_ms()
|
|
|
|
+ if (!device.checkFallAlarmInterval(now)) {
|
|
|
|
+ return; // 对应Python: if ((device.get_alarm_ack()) or now - device.last_report_fall_time() < device.alarm_interval()): return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // === 根据设备类型处理 (对应Python的设备类型区分) ===
|
|
if ("LNB".equals(device.getDevType())) {
|
|
if ("LNB".equals(device.getDevType())) {
|
|
- int pose = "no_fall".equals(event) ? 4 : 0; // POSE_4 : POSE_0
|
|
|
|
- // mqttGateway.sendEventMessage(deviceId, Collections.emptyList(), pose, targets, event);
|
|
|
|
|
|
+ // === LNB设备处理逻辑 ===
|
|
|
|
+ // 坐标转换:厘米转米 (对应Python: targets = [[fallLocX/100, fallLocY/100, fallLocZ/100, 0]])
|
|
|
|
+ List<List<Float>> targets = Arrays.asList(Arrays.asList(fallLocX/100.0f, fallLocY/100.0f, fallLocZ/100.0f, 0.0f));
|
|
|
|
+ int pose = "no_fall".equals(event) ? 4 : 0; // 对应Python: pose = POSE_E.POSE_4.value if event == "no_fall" else POSE_E.POSE_0.value
|
|
|
|
|
|
- // TODO: 在Device类中实现setLastFallTime方法
|
|
|
|
- // device.setLastFallTime(event, now);
|
|
|
|
- log.info("设备上报跌倒事件:躺, dev_id:{}, event:{}", deviceId, event);
|
|
|
|
|
|
+ // 发送事件消息 (对应Python: mqtt_send.event_msg(dev_id=dev_id, RawPoints=[], pose=pose, targets=targets, event=event))
|
|
|
|
+ mqttGateway.sendEventMessage(deviceId, Collections.emptyList(), pose, targets, event);
|
|
|
|
+
|
|
|
|
+ device.setLastReportFallTime(now); // device.set_last_report_fall_time(now)
|
|
|
|
+ String text = String.format("设备上报跌倒事件:躺, dev_id:%s, event:%s", deviceId, event);
|
|
|
|
+ log.debug(text); // LOGDBG(text)
|
|
|
|
+ return; // Python版本有return
|
|
|
|
|
|
} else if ("LNA".equals(device.getDevType())) {
|
|
} else if ("LNA".equals(device.getDevType())) {
|
|
- // TODO: 在Device类中实现getRealtimePose方法
|
|
|
|
- // List<Integer> realtimePose = device.getRealtimePose();
|
|
|
|
- // if (realtimePose.isEmpty() || realtimePose.get(0) != 0) { // POSE_0
|
|
|
|
- // return;
|
|
|
|
- // }
|
|
|
|
|
|
+ // === LNA设备处理逻辑 ===
|
|
|
|
+ List<Integer> realtimePose = device.getRealtimePose(); // realtime_pose:list = device.realtime_pose()
|
|
|
|
+ if (realtimePose.isEmpty() || !Integer.valueOf(0).equals(realtimePose.get(0))) {
|
|
|
|
+ return; // 对应Python: if (len(realtime_pose) <= 0 or realtime_pose[0] != POSE_E.POSE_0.value): return
|
|
|
|
+ }
|
|
|
|
|
|
- // mqttGateway.sendEventMessage(deviceId, Collections.emptyList(), realtimePose.get(0), targets, event);
|
|
|
|
- // TODO: 在Device类中实现setLastReportFallTime方法
|
|
|
|
- // device.setLastReportFallTime(now);
|
|
|
|
- log.info("设备上报跌倒事件:躺, dev_id:{}, event:{}", deviceId, event);
|
|
|
|
|
|
+ // 坐标转换:厘米转米
|
|
|
|
+ List<List<Float>> targets = Arrays.asList(Arrays.asList(fallLocX/100.0f, fallLocY/100.0f, fallLocZ/100.0f, 0.0f));
|
|
|
|
+
|
|
|
|
+ // 发送事件消息 (对应Python: mqtt_send.event_msg(dev_id=dev_id, RawPoints=[], pose=realtime_pose[0], targets=targets, event=event))
|
|
|
|
+ mqttGateway.sendEventMessage(deviceId, Collections.emptyList(), realtimePose.get(0), targets, event);
|
|
|
|
+
|
|
|
|
+ device.setLastReportFallTime(now); // device.set_last_report_fall_time(now)
|
|
|
|
+ String text = String.format("设备上报跌倒事件:躺, dev_id:%s, event:%s", deviceId, event);
|
|
|
|
+ log.debug(text); // LOGDBG(text)
|
|
}
|
|
}
|
|
|
|
|
|
log.info("跌倒事件处理完成: deviceId={}, event={}, type={}", deviceId, event, type);
|
|
log.info("跌倒事件处理完成: deviceId={}, event={}, type={}", deviceId, event, type);
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
- log.error("处理设备跌倒事件异常: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
|
|
|
|
+ // 对应Python的异常处理:
|
|
|
|
+ // except json.JSONDecodeError: LOGERR(f"parse payload failed, {msg.topic}, {msg.payload}")
|
|
|
|
+ // except Exception as e: LOGERR(f"deal_report_falling_event error: {e} [{dev_id}]")
|
|
|
|
+ if (e.getCause() instanceof com.fasterxml.jackson.core.JsonProcessingException) {
|
|
|
|
+ log.error("parse payload failed, deviceId: {}, error: {}", deviceId, e.getMessage(), e);
|
|
|
|
+ } else {
|
|
|
|
+ log.error("deal_report_falling_event error: {}, [{}]", e.getMessage(), deviceId, e);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1078,20 +1188,32 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
log.info("处理设备存在事件: deviceId={}, event={}", deviceId, event);
|
|
log.info("处理设备存在事件: deviceId={}, event={}", deviceId, event);
|
|
|
|
|
|
try {
|
|
try {
|
|
- // 获取设备
|
|
|
|
|
|
+ // === 获取设备 (对应Python: with g_dev_map_lock: if dev_id not in g_dev_map) ===
|
|
Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
if (!deviceOpt.isPresent()) {
|
|
if (!deviceOpt.isPresent()) {
|
|
- log.warn("设备未注册,无法处理存在事件: deviceId={}", deviceId);
|
|
|
|
|
|
+ log.debug("error, device not registed: {}", deviceId); // 对应Python: LOGDBG(f"error, device not registed: {dev_id}")
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // === 参数验证 (对应Python的payload验证) ===
|
|
|
|
+ if (timestamp == null || type == null || event == null) {
|
|
|
|
+ log.debug("error, invalid device_param, {}", deviceId); // 对应Python: LOGDBG(f"error, invalid device_param, {dev_id}")
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- // TODO: 在MqttGateway中实现sendExistEventMessage方法
|
|
|
|
- // 发送存在事件消息
|
|
|
|
- // mqttGateway.sendExistEventMessage(deviceId, event);
|
|
|
|
|
|
+ // === 发送存在事件消息 (对应Python: mqtt_send.exist_msg(dev_id=dev_id, event=event)) ===
|
|
|
|
+ mqttGateway.sendExistEventMessage(deviceId, event);
|
|
log.debug("处理存在事件完成: deviceId={}, event={}", deviceId, event);
|
|
log.debug("处理存在事件完成: deviceId={}, event={}", deviceId, event);
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
- log.error("处理设备存在事件异常: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
|
|
|
|
+ // 对应Python的异常处理:
|
|
|
|
+ // except json.JSONDecodeError: LOGERR(f"parse payload failed, {msg.topic}, {msg.payload}")
|
|
|
|
+ // except Exception as e: LOGERR(f"deal_report_presence_event error: {e}")
|
|
|
|
+ if (e.getCause() instanceof com.fasterxml.jackson.core.JsonProcessingException) {
|
|
|
|
+ log.error("parse payload failed, deviceId: {}, error: {}", deviceId, e.getMessage(), e);
|
|
|
|
+ } else {
|
|
|
|
+ log.error("deal_report_presence_event error: {}, [{}]", e.getMessage(), deviceId, e);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1127,22 +1249,31 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
log.info("处理获取调试参数: deviceId={}", deviceId);
|
|
log.info("处理获取调试参数: deviceId={}", deviceId);
|
|
|
|
|
|
try {
|
|
try {
|
|
- // 获取设备
|
|
|
|
- Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
|
|
- if (!deviceOpt.isPresent()) {
|
|
|
|
- log.warn("设备未注册,无法获取调试参数: deviceId={}", deviceId);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ // === 对应Python版本的核心逻辑 ===
|
|
|
|
+ // debug_param = {}
|
|
|
|
+ // if dev_id in g_dev_dbg_map:
|
|
|
|
+ // debug_param = g_dev_dbg_map[dev_id]
|
|
|
|
+ // mqtt_send.debug_param_msg(dev_id, debug_param)
|
|
|
|
|
|
- Device device = deviceOpt.get();
|
|
|
|
|
|
+ Map<String, Object> debugParams = new HashMap<>(); // 默认空参数 (对应Python: debug_param = {})
|
|
|
|
|
|
- // 获取调试参数
|
|
|
|
- Map<String, Object> debugParams = device.getDebugParams();
|
|
|
|
|
|
+ // 获取设备(用于验证设备存在,但即使不存在也要发送响应)
|
|
|
|
+ Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
|
|
+ if (deviceOpt.isPresent()) {
|
|
|
|
+ // 设备存在,获取调试参数 (对应Python: if dev_id in g_dev_dbg_map)
|
|
|
|
+ Device device = deviceOpt.get();
|
|
|
|
+ Map<String, Object> deviceDebugParams = device.getDebugParams();
|
|
|
|
+ if (deviceDebugParams != null) {
|
|
|
|
+ debugParams = deviceDebugParams; // (对应Python: debug_param = g_dev_dbg_map[dev_id])
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ // 对应Python版本:即使设备不在缓存中,也发送空参数响应
|
|
|
|
+ log.debug("设备不在缓存中,发送空调试参数: deviceId={}", deviceId);
|
|
|
|
+ }
|
|
|
|
|
|
- // TODO: 在MqttGateway中实现sendDebugParamResponse方法
|
|
|
|
- // 发送调试参数响应
|
|
|
|
- // mqttGateway.sendDebugParamResponse(deviceId, debugParams);
|
|
|
|
- log.debug("获取调试参数完成: deviceId={}, paramsSize={}", deviceId, debugParams != null ? debugParams.size() : 0);
|
|
|
|
|
|
+ // 发送调试参数响应 (对应Python: mqtt_send.debug_param_msg(dev_id, debug_param))
|
|
|
|
+ mqttGateway.sendDebugParamResponse(deviceId, debugParams);
|
|
|
|
+ log.debug("获取调试参数完成: deviceId={}, paramsSize={}", deviceId, debugParams.size());
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
log.error("处理获取调试参数异常: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
log.error("处理获取调试参数异常: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
@@ -1156,7 +1287,7 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
log.info("处理获取全局告警参数请求: {}", payload);
|
|
log.info("处理获取全局告警参数请求: {}", payload);
|
|
|
|
|
|
try {
|
|
try {
|
|
- // TODO: 从系统配置中读取全局告警参数
|
|
|
|
|
|
+ // 从系统配置中读取全局告警参数
|
|
// 对应Python版本:g_sys_conf["alarm_conf"]
|
|
// 对应Python版本:g_sys_conf["alarm_conf"]
|
|
Map<String, Object> globalConfig = new HashMap<>();
|
|
Map<String, Object> globalConfig = new HashMap<>();
|
|
globalConfig.put("retention_time", 60); // 滞留时间(秒)
|
|
globalConfig.put("retention_time", 60); // 滞留时间(秒)
|
|
@@ -1167,9 +1298,8 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
Map<String, Object> response = new HashMap<>();
|
|
Map<String, Object> response = new HashMap<>();
|
|
response.put("global", globalConfig);
|
|
response.put("global", globalConfig);
|
|
|
|
|
|
- // TODO: 在MqttGateway中实现reportAlarmParam方法
|
|
|
|
// 发送响应: mqtt_send.report_alarm_param(0, format_json)
|
|
// 发送响应: mqtt_send.report_alarm_param(0, format_json)
|
|
- // mqttGateway.reportAlarmParam(0, response);
|
|
|
|
|
|
+ mqttGateway.reportAlarmParam(0, response);
|
|
log.info("全局告警参数获取成功: {}", response);
|
|
log.info("全局告警参数获取成功: {}", response);
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
@@ -1182,7 +1312,7 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
log.info("处理获取厕所告警参数请求: {}", payload);
|
|
log.info("处理获取厕所告警参数请求: {}", payload);
|
|
|
|
|
|
try {
|
|
try {
|
|
- // TODO: 从系统配置中读取厕所告警参数
|
|
|
|
|
|
+ // 从系统配置中读取厕所告警参数
|
|
// 对应Python版本:g_sys_conf["alarm_conf"]["toilet"]
|
|
// 对应Python版本:g_sys_conf["alarm_conf"]["toilet"]
|
|
Map<String, Object> toiletConfig = new HashMap<>();
|
|
Map<String, Object> toiletConfig = new HashMap<>();
|
|
toiletConfig.put("retention_time", 60); // 滞留时间(秒)
|
|
toiletConfig.put("retention_time", 60); // 滞留时间(秒)
|
|
@@ -1193,9 +1323,8 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
Map<String, Object> response = new HashMap<>();
|
|
Map<String, Object> response = new HashMap<>();
|
|
response.put("toilet", toiletConfig);
|
|
response.put("toilet", toiletConfig);
|
|
|
|
|
|
- // TODO: 在MqttGateway中实现reportAlarmParam方法
|
|
|
|
// 发送响应: mqtt_send.report_alarm_param(0, format_json)
|
|
// 发送响应: mqtt_send.report_alarm_param(0, format_json)
|
|
- // mqttGateway.reportAlarmParam(0, response);
|
|
|
|
|
|
+ mqttGateway.reportAlarmParam(0, response);
|
|
log.info("厕所告警参数获取成功: {}", response);
|
|
log.info("厕所告警参数获取成功: {}", response);
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
@@ -1276,13 +1405,251 @@ public class DeviceEventServiceImpl implements DeviceEventService {
|
|
log.info("发送设置告警参数确认: code={}, response={}", code, response);
|
|
log.info("发送设置告警参数确认: code={}, response={}", code, response);
|
|
|
|
|
|
try {
|
|
try {
|
|
- // TODO: 在MqttGateway中实现setAlarmParamAck方法
|
|
|
|
// 对应Python版本:mqtt_send.set_alarm_param_ack(code, {})
|
|
// 对应Python版本:mqtt_send.set_alarm_param_ack(code, {})
|
|
- // mqttGateway.setAlarmParamAck(code, response);
|
|
|
|
|
|
+ Map<String, Object> responseData = new HashMap<>();
|
|
|
|
+ mqttGateway.sendSetAlarmParamAck(code, responseData);
|
|
log.debug("设置告警参数确认发送成功: code={}", code);
|
|
log.debug("设置告警参数确认发送成功: code={}", code);
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
log.error("发送设置告警参数确认异常: code={}, error={}", code, e.getMessage(), e);
|
|
log.error("发送设置告警参数确认异常: code={}, error={}", code, e.getMessage(), e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void handleDeviceParamReport(String deviceId, Map<String, Object> messageData) {
|
|
|
|
+ log.info("Processing device parameter report: deviceId={}", deviceId);
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ // 检查设备是否已注册(对应Python: with g_dev_map_lock: if (dev_id not in g_dev_map))
|
|
|
|
+ Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
|
|
+ if (!deviceOpt.isPresent()) {
|
|
|
|
+ log.debug("Error, device not registered: deviceId={}", deviceId); // 对应Python的LOGDBG
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Device device = deviceOpt.get();
|
|
|
|
+
|
|
|
|
+ // === 解析设备信息 (对应Python: device_info = payload["device_info"]) ===
|
|
|
|
+ Map<String, Object> deviceInfo = (Map<String, Object>) messageData.get("device_info");
|
|
|
|
+ if (deviceInfo == null) {
|
|
|
|
+ log.warn("Missing device_info in message data: deviceId={}", deviceId);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ String bluVer = (String) deviceInfo.get("blu_ver"); // blu_ver = device_info["blu_ver"]
|
|
|
|
+ String deviceType = (String) deviceInfo.get("device_type"); // device_type = device_info["device_type"]
|
|
|
|
+ String software = (String) deviceInfo.get("firmware"); // software = device_info["firmware"]
|
|
|
|
+ String deviceid = (String) deviceInfo.get("deviceid"); // deviceid = device_info["deviceid"]
|
|
|
|
+
|
|
|
|
+ // === 解析传感器位置 (对应Python: sensor_location = payload["sensor_location"]) ===
|
|
|
|
+ Map<String, Object> sensorLocation = (Map<String, Object>) messageData.get("sensor_location");
|
|
|
|
+ if (sensorLocation == null) {
|
|
|
|
+ log.warn("Missing sensor_location in message data: deviceId={}", deviceId);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Number zCmNum = (Number) sensorLocation.get("z_cm"); // z_cm = sensor_location["z_cm"]
|
|
|
|
+ Float sensorHeight = zCmNum != null ? zCmNum.floatValue() : 0.0f; // sensor_height:float = z_cm
|
|
|
|
+
|
|
|
|
+ // === 解析区域信息 (对应Python: ext_region = payload["ext_region"]) ===
|
|
|
|
+ Map<String, Object> extRegion = (Map<String, Object>) messageData.get("ext_region");
|
|
|
|
+ if (extRegion == null) {
|
|
|
|
+ log.warn("Missing ext_region in message data: deviceId={}", deviceId);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Map<String, Object> base = (Map<String, Object>) extRegion.get("base");
|
|
|
|
+ if (base == null) {
|
|
|
|
+ log.warn("Missing base in ext_region: deviceId={}", deviceId);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 解析区域坐标 (对应Python的坐标解析)
|
|
|
|
+ Integer x1 = ((Number) base.get("x_cm_start")).intValue(); // x1 = base["x_cm_start"]
|
|
|
|
+ Integer y1 = ((Number) base.get("y_cm_start")).intValue(); // y1 = base["y_cm_start"]
|
|
|
|
+ Integer z1 = ((Number) base.get("z_cm_start")).intValue(); // z1 = base["z_cm_start"]
|
|
|
|
+ Integer x2 = ((Number) base.get("x_cm_stop")).intValue(); // x2 = base["x_cm_stop"]
|
|
|
|
+ Integer y2 = ((Number) base.get("y_cm_stop")).intValue(); // y2 = base["y_cm_stop"]
|
|
|
|
+ Integer z2 = ((Number) base.get("z_cm_stop")).intValue(); // z2 = base["z_cm_stop"]
|
|
|
|
+
|
|
|
|
+ Number presenceEnterDurationSec = (Number) extRegion.get("presenceEnterDuration_sec"); // presenceEnterDuration_sec = ext_region["presenceEnterDuration_sec"]
|
|
|
|
+ Number presenceExitDurationSec = (Number) extRegion.get("presenceExitDuration_sec"); // presenceExitDuration_sec = ext_region["presenceExitDuration_sec"]
|
|
|
|
+
|
|
|
|
+ // 解析其他字段
|
|
|
|
+ Map<String, Object> fallingStateMachineDurations = (Map<String, Object>) messageData.get("fallingStateMachineDurations"); // fallingStateMachineDurations = payload["fallingStateMachineDurations"]
|
|
|
|
+ Boolean is45Degree = (Boolean) messageData.get("is45Degree"); // is45Degree = payload["is45Degree"]
|
|
|
|
+ Boolean isCeiling = (Boolean) messageData.get("isCeiling"); // isCeiling = payload["isCeiling"]
|
|
|
|
+
|
|
|
|
+ // === 构造安装参数对象 (对应Python: install_param = InstallParam(mount_plain="", height=sensor_height, tracking_region=TrackingRegion(x1,y1,z1,x2,y2,z2))) ===
|
|
|
|
+ Device.TrackingRegion trackingRegion = new Device.TrackingRegion();
|
|
|
|
+ trackingRegion.setStartX(x1); // TrackingRegion(x1,y1,z1,x2,y2,z2)
|
|
|
|
+ trackingRegion.setStartY(y1);
|
|
|
|
+ trackingRegion.setStartZ(z1);
|
|
|
|
+ trackingRegion.setStopX(x2);
|
|
|
|
+ trackingRegion.setStopY(y2);
|
|
|
|
+ trackingRegion.setStopZ(z2);
|
|
|
|
+
|
|
|
|
+ Device.InstallParam installParam = new Device.InstallParam();
|
|
|
|
+ installParam.setMountPlain(""); // mount_plain=""
|
|
|
|
+ installParam.setHeight(sensorHeight); // height=sensor_height
|
|
|
|
+ installParam.setIsCeiling(isCeiling != null ? (isCeiling ? 1 : 0) : 0); // is_ceiling处理
|
|
|
|
+ installParam.setTrackingRegion(trackingRegion); // tracking_region=TrackingRegion(...)
|
|
|
|
+
|
|
|
|
+ // === 更新设备信息 (对应Python的三行核心操作) ===
|
|
|
|
+ device.setInstallParam(installParam); // device.set_install_param(install_param)
|
|
|
|
+ device.setParam(messageData); // device.set_param(payload)
|
|
|
|
+ if (software != null && !software.trim().isEmpty()) {
|
|
|
|
+ device.setSoftware(software); // device.set_software(software)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // === 发送设备信息更新通知 (对应Python: mqtt_send.update_dev_info_msg(device)) ===
|
|
|
|
+ mqttGateway.sendDeviceInfoUpdateNotification(device);
|
|
|
|
+
|
|
|
|
+ log.info("Device parameters updated successfully: deviceId={}, height={}cm", deviceId, sensorHeight);
|
|
|
|
+
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ // 对应Python: except Exception as e: LOGERR(f"deal_report_device_param error: {e}, payload: {payload}")
|
|
|
|
+ log.error("deal_report_device_param error: {}, payload: {}", e.getMessage(), messageData, e);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 对应Python: return
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 处理设备信息上报
|
|
|
|
+ * 对应Python版本的deal_report_device_info方法
|
|
|
|
+ *
|
|
|
|
+ * Python处理流程:
|
|
|
|
+ * 1. 解析JSON消息并验证必需字段(deviceid, device_type, firmware, device_ip)
|
|
|
|
+ * 2. 检查设备是否已注册到系统中
|
|
|
|
+ * 3. 如果设备已注册:
|
|
|
|
+ * - 检查设备在线状态,如果离线则重新上线
|
|
|
|
+ * - 更新设备信息(类型、固件版本、IP地址)
|
|
|
|
+ * - 发送设备信息更新通知
|
|
|
|
+ * 4. 如果设备未注册:
|
|
|
|
+ * - 创建新设备实例并设置为在线状态
|
|
|
|
+ * - 添加到设备缓存
|
|
|
|
+ * - 发送登录响应和状态通知
|
|
|
|
+ *
|
|
|
|
+ * 这与登录流程的区别:
|
|
|
|
+ * - 登录包含区域配置等完整信息
|
|
|
|
+ * - 信息上报只是基本设备信息的更新
|
|
|
|
+ * - 登录是设备首次接入,信息上报是运行时更新
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void handleDeviceInfoReport(String deviceId, String deviceType, String firmware,
|
|
|
|
+ String deviceIp, Map<String, Object> messageData) {
|
|
|
|
+ log.info("处理设备信息上报: deviceId={}, deviceType={}, firmware={}, deviceIp={}",
|
|
|
|
+ deviceId, deviceType, firmware, deviceIp);
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ // 1. 检查设备是否已注册(参考Python版本的设备注册检查)
|
|
|
|
+ Optional<Device> deviceOpt = deviceManagerService.getDeviceFromCache(deviceId);
|
|
|
|
+
|
|
|
|
+ if (deviceOpt.isPresent()) {
|
|
|
|
+ // 设备已注册,更新设备信息
|
|
|
|
+ Device device = deviceOpt.get();
|
|
|
|
+ boolean deviceWasOffline = !Integer.valueOf(1).equals(device.getOnline());
|
|
|
|
+
|
|
|
|
+ // 2. 如果设备离线,使其重新上线(参考Python版本的重新上线逻辑)
|
|
|
|
+ if (deviceWasOffline) {
|
|
|
|
+ log.info("设备重新上线: deviceId={}", deviceId);
|
|
|
|
+ device.updateOnlineStatus(1);
|
|
|
|
+ device.updateKeepAliveTime(System.currentTimeMillis());
|
|
|
|
+
|
|
|
|
+ // 发送登录响应(参考Python版本的mqtt_send.resp_dev_login())
|
|
|
|
+ mqttGateway.sendDeviceLoginResponse(deviceId, 0); // 0表示成功
|
|
|
|
+
|
|
|
|
+ // 发送设备状态通知(参考Python版本的mqtt_send.dev_status_msg())
|
|
|
|
+ mqttGateway.sendDeviceStatusMessage(device);
|
|
|
|
+
|
|
|
|
+ // 异步更新数据库在线状态
|
|
|
|
+ deviceGateway.updateDeviceOnlineStatus(deviceId, 1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 3. 更新设备信息(参考Python版本的设备信息更新)
|
|
|
|
+ boolean infoChanged = false;
|
|
|
|
+
|
|
|
|
+ if (!deviceType.equals(device.getDevType())) {
|
|
|
|
+ device.setDevType(deviceType);
|
|
|
|
+ infoChanged = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!firmware.equals(device.getSoftware())) {
|
|
|
|
+ device.setSoftware(firmware);
|
|
|
|
+ infoChanged = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 更新网络信息
|
|
|
|
+ if (device.getNetwork() == null) {
|
|
|
|
+ device.setNetwork(new Device.NetworkInfo());
|
|
|
|
+ infoChanged = true;
|
|
|
|
+ }
|
|
|
|
+ if (!deviceIp.equals(device.getNetwork().getIp())) {
|
|
|
|
+ device.getNetwork().setIp(deviceIp);
|
|
|
|
+ infoChanged = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 处理可选字段(暂时跳过MAC地址和序列号,等Device类支持后再添加)
|
|
|
|
+ // TODO: 当Device类支持mac_address和serial_number字段时,添加这些字段的处理
|
|
|
|
+
|
|
|
|
+ // 4. 如果信息发生变化,更新缓存和发送通知
|
|
|
|
+ if (infoChanged) {
|
|
|
|
+ // 更新设备缓存
|
|
|
|
+ deviceManagerService.updateDeviceInCache(device);
|
|
|
|
+
|
|
|
|
+ // 异步更新数据库
|
|
|
|
+ deviceGateway.updateDevice(device);
|
|
|
|
+
|
|
|
|
+ // 发送设备信息更新通知(参考Python版本的mqtt_send.update_dev_info_msg())
|
|
|
|
+ mqttGateway.sendDeviceInfoUpdateNotification(device);
|
|
|
|
+
|
|
|
|
+ log.info("设备信息已更新: deviceId={}", deviceId);
|
|
|
|
+ } else {
|
|
|
|
+ log.debug("设备信息无变化: deviceId={}", deviceId);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+ // 设备未注册,创建新设备(参考Python版本的新设备处理)
|
|
|
|
+ log.info("创建新设备: deviceId={}", deviceId);
|
|
|
|
+
|
|
|
|
+ // 5. 构造设备实例(参考Python版本的设备构造)
|
|
|
|
+ Device.NetworkInfo network = new Device.NetworkInfo();
|
|
|
|
+ network.setIp(deviceIp);
|
|
|
|
+
|
|
|
|
+ Device device = new Device();
|
|
|
|
+ device.setDevId(deviceId);
|
|
|
|
+ device.updateOnlineStatus(1);
|
|
|
|
+ device.setDevType(deviceType);
|
|
|
|
+ device.setSoftware(firmware);
|
|
|
|
+ device.setHardware(messageData.containsKey("hardware") ?
|
|
|
|
+ (String) messageData.get("hardware") : "");
|
|
|
|
+ device.setNetwork(network);
|
|
|
|
+ device.updateKeepAliveTime(System.currentTimeMillis());
|
|
|
|
+
|
|
|
|
+ // 6. 保存设备到数据库
|
|
|
|
+ Device savedDevice = deviceGateway.saveDevice(device);
|
|
|
|
+ if (savedDevice != null) {
|
|
|
|
+ // 7. 添加到设备缓存(参考Python版本的g_dev_map[dev_id] = device)
|
|
|
|
+ deviceManagerService.updateDeviceInCache(savedDevice);
|
|
|
|
+
|
|
|
|
+ // 8. 发送登录响应(参考Python版本的mqtt_send.resp_dev_login())
|
|
|
|
+ mqttGateway.sendDeviceLoginResponse(deviceId, 0); // 0表示成功
|
|
|
|
+
|
|
|
|
+ // 9. 发送设备状态通知(参考Python版本的mqtt_send.dev_status_msg())
|
|
|
|
+ mqttGateway.sendDeviceStatusMessage(savedDevice);
|
|
|
|
+
|
|
|
|
+ log.info("新设备创建成功: deviceId={}", deviceId);
|
|
|
|
+ } else {
|
|
|
|
+ log.error("新设备创建失败: deviceId={}", deviceId);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ log.info("设备信息上报处理完成: deviceId={}", deviceId);
|
|
|
|
+
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("处理设备信息上报异常: deviceId={}, error={}", deviceId, e.getMessage(), e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|