diff --git a/viewshanghai-module-iot/viewshanghai-module-iot-gateway/src/main/java/com/viewshanghai/module/iot/gateway/codec/jt808/IotJt808DeviceMessageCodec.java b/viewshanghai-module-iot/viewshanghai-module-iot-gateway/src/main/java/com/viewshanghai/module/iot/gateway/codec/jt808/IotJt808DeviceMessageCodec.java index 0c1a87f..2c7c44d 100644 --- a/viewshanghai-module-iot/viewshanghai-module-iot-gateway/src/main/java/com/viewshanghai/module/iot/gateway/codec/jt808/IotJt808DeviceMessageCodec.java +++ b/viewshanghai-module-iot/viewshanghai-module-iot-gateway/src/main/java/com/viewshanghai/module/iot/gateway/codec/jt808/IotJt808DeviceMessageCodec.java @@ -100,34 +100,74 @@ public class IotJt808DeviceMessageCodec implements IotDeviceMessageCodec { /** * 将 JT808 数据包转换为 IotDeviceMessage + * + * @param dataPack JT808 数据包 + * @return IotDeviceMessage 消息对象 */ private IotDeviceMessage convertToIotDeviceMessage(Jt808DataPack dataPack) { - Jt808DataPack.PackHead head = dataPack.getPackHead(); - int msgId = head.getId(); + Assert.notNull(dataPack, "JT808 数据包不能为空"); - // 生成消息ID(使用流水号作为标识) - String messageId = head.getTerminalPhone() + "_" + head.getFlowId(); + Jt808DataPack.PackHead head = dataPack.getPackHead(); + Assert.notNull(head, "JT808 数据包头部不能为空"); + + int msgId = head.getId(); + String terminalPhone = head.getTerminalPhone(); + int flowId = head.getFlowId(); + + // 生成请求ID(用于追踪和关联,格式:终端手机号_流水号_时间戳) + // 添加时间戳确保唯一性,避免同一终端同一流水号重复 + String requestId = String.format("%s_%d_%d", terminalPhone, flowId, System.currentTimeMillis()); // 根据消息ID确定物模型标准方法名 String method = getStandardMethodName(msgId); + + // 解析消息参数 Object params = parseMessageParams(dataPack, msgId); - // 构建元数据(保留在 params 中,用于调试和追踪) + // 构建元数据并添加到 params 中(用于调试和追踪) + params = enrichParamsWithMetadata(params, msgId, terminalPhone, flowId, head.getEncryptionType()); + + // 创建 IotDeviceMessage(of 方法会自动生成 id 和 reportTime) + return IotDeviceMessage.of(requestId, method, params, null, null, null); + } + + /** + * 为参数对象添加元数据 + * + * @param params 原始参数对象 + * @param msgId JT808 消息ID + * @param terminalPhone 终端手机号 + * @param flowId 流水号 + * @param encryptionType 加密类型 + * @return 包含元数据的参数对象 + */ + private Object enrichParamsWithMetadata(Object params, int msgId, String terminalPhone, + int flowId, int encryptionType) { + // 构建元数据 Map + Map metadata = new HashMap<>(4); + metadata.put("jt808MsgId", String.format("0x%04X", msgId)); + metadata.put("terminalPhone", terminalPhone); + metadata.put("flowId", flowId); + metadata.put("encryptionType", encryptionType); + + // 如果 params 是 Map 类型,则添加元数据 if (params instanceof Map) { @SuppressWarnings("unchecked") Map paramsMap = (Map) params; - Map metadata = new HashMap<>(); - metadata.put("jt808MsgId", String.format("0x%04X", msgId)); - metadata.put("terminalPhone", head.getTerminalPhone()); - metadata.put("flowId", head.getFlowId()); - metadata.put("encryptionType", head.getEncryptionType()); - paramsMap.put("_metadata", metadata); + + // 创建新的可变 Map,确保可以添加元数据 + // 注意:某些解析方法可能返回不可变的 Map(如 Map.of()),需要转换为可变 Map + Map enrichedParams = new HashMap<>(paramsMap); + enrichedParams.put("_metadata", metadata); + return enrichedParams; } - // 创建 IotDeviceMessage - IotDeviceMessage message = IotDeviceMessage.of(messageId, method, params, null, null, null); - message.setReportTime(LocalDateTime.now()); - return message; + // 如果 params 不是 Map,则包装为包含元数据的 Map + // 保留原始 params 在 _data 字段中 + Map wrapper = new HashMap<>(2); + wrapper.put("_data", params); + wrapper.put("_metadata", metadata); + return wrapper; } /**