From 8d52e9e413b54301663389fa08b70be766879d98 Mon Sep 17 00:00:00 2001 From: lzh Date: Fri, 26 Dec 2025 17:58:36 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Djava.lang.RuntimeExcep?= =?UTF-8?q?tion:=20JT808=20=E6=B6=88=E6=81=AF=E7=BC=96=E7=A0=81=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5:=20=E6=B6=88=E6=81=AF=E5=8F=82=E6=95=B0=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E9=94=99=E8=AF=AF=EF=BC=8Cparams=20=E5=BF=85=E9=A1=BB?= =?UTF-8?q?=E6=98=AF=20Map=20=E7=B1=BB=E5=9E=8B=20=20=20=20=20=20=20=20=09?= =?UTF-8?q?at=20com.viewshanghai.module.iot.gateway.codec.jt808.IotJt808De?= =?UTF-8?q?viceMessageCodec.encode(IotJt808DeviceMessageCodec.java:77)=20~?= =?UTF-8?q?[!/:na]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jt808/IotJt808DeviceMessageCodec.java | 137 +++++++++++++----- 1 file changed, 101 insertions(+), 36 deletions(-) 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 761c67b..684722d 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 @@ -598,98 +598,163 @@ public class IotJt808DeviceMessageCodec implements IotDeviceMessageCodec { /** * 提取终端手机号 - * + * * 优先级: * 1. 从 params._deviceName 中获取(下发场景,IotTcpDownstreamHandler 自动注入) * 2. 从 params._metadata.terminalPhone 中获取(上行消息回复场景) * 3. 从 params.phone 中获取(手动指定,向下兼容,不推荐) + * 4. 从 data.phone 中获取(应答消息场景,使用 replyOf 构建的消息) */ private String extractPhoneNumber(IotDeviceMessage message) { - if (!(message.getParams() instanceof Map)) { - log.error("[extractPhoneNumber][params 不是 Map 类型,消息: {}]", message); - throw new IllegalArgumentException("消息参数格式错误,params 必须是 Map 类型"); + // 尝试从 params 提取 + if (message.getParams() instanceof Map) { + Map params = (Map) message.getParams(); + String phone = extractPhoneFromMap(params); + if (phone != null) { + return phone; + } } - - Map params = (Map) message.getParams(); - + + // 尝试从 data 提取(应答消息使用 replyOf 时,参数在 data 字段) + if (message.getData() instanceof Map) { + Map data = (Map) message.getData(); + String phone = extractPhoneFromMap(data); + if (phone != null) { + return phone; + } + } + + // 如果都获取不到,抛出异常 + log.error("[extractPhoneNumber][无法提取终端手机号,params: {}, data: {}]", + message.getParams(), message.getData()); + throw new IllegalArgumentException( + "消息中缺少终端手机号。请确保设备的 deviceName 为终端手机号(纯数字),例如: \"13800138000\""); + } + + /** + * 从 Map 中提取终端手机号 + */ + private String extractPhoneFromMap(Map map) { + if (map == null) { + return null; + } + // 1. 优先从 _deviceName 获取(下发场景,由 IotTcpDownstreamHandler 注入) - Object deviceName = params.get("_deviceName"); + Object deviceName = map.get("_deviceName"); if (deviceName != null && StrUtil.isNotBlank(deviceName.toString())) { String deviceNameStr = deviceName.toString().trim(); // 验证是否为数字(终端手机号应该是纯数字) if (deviceNameStr.matches("\\d+")) { return deviceNameStr; } else { - log.warn("[extractPhoneNumber][_deviceName 不是纯数字: {}]", deviceNameStr); + log.warn("[extractPhoneFromMap][_deviceName 不是纯数字: {}]", deviceNameStr); } } - + // 2. 从 metadata 中获取(上行消息回复场景) - if (params.get("_metadata") instanceof Map) { - Map metadata = (Map) params.get("_metadata"); + if (map.get("_metadata") instanceof Map) { + Map metadata = (Map) map.get("_metadata"); Object terminalPhone = metadata.get("terminalPhone"); if (terminalPhone != null && StrUtil.isNotBlank(terminalPhone.toString())) { return terminalPhone.toString(); } } - + // 3. 从 phone 字段获取(向下兼容,不推荐) - Object phone = params.get("phone"); + Object phone = map.get("phone"); if (phone != null && StrUtil.isNotBlank(phone.toString())) { String phoneStr = phone.toString().trim(); if (phoneStr.matches("\\d+")) { return phoneStr; } } - - // 4. 如果都获取不到,抛出异常 - log.error("[extractPhoneNumber][无法提取终端手机号,params: {}]", params); - throw new IllegalArgumentException( - "消息中缺少终端手机号。请确保设备的 deviceName 为终端手机号(纯数字),例如: \"13800138000\""); + + return null; } /** * 提取流水号 - * + * * 对于下发消息,如果没有指定流水号,则生成一个随机流水号 */ private int extractFlowId(IotDeviceMessage message) { + // 尝试从 params 提取 if (message.getParams() instanceof Map) { Map params = (Map) message.getParams(); - - // 尝试获取显式指定的流水号 - Object flowId = params.get("flowId"); - if (flowId instanceof Number) { - return ((Number) flowId).intValue(); - } - - // 尝试从 metadata 中获取(上行消息的流水号) - if (params.get("_metadata") instanceof Map) { - Map metadata = (Map) params.get("_metadata"); - Object metaFlowId = metadata.get("flowId"); - if (metaFlowId instanceof Number) { - return ((Number) metaFlowId).intValue(); - } + Integer flowId = extractFlowIdFromMap(params); + if (flowId != null) { + return flowId; } } - + + // 尝试从 data 提取(应答消息使用 replyOf 时,参数在 data 字段) + if (message.getData() instanceof Map) { + Map data = (Map) message.getData(); + Integer flowId = extractFlowIdFromMap(data); + if (flowId != null) { + return flowId; + } + } + // 生成随机流水号(1-65535) return (int) (System.currentTimeMillis() % 65535) + 1; } + /** + * 从 Map 中提取流水号 + */ + private Integer extractFlowIdFromMap(Map map) { + if (map == null) { + return null; + } + + // 尝试获取显式指定的流水号 + Object flowId = map.get("flowId"); + if (flowId instanceof Number) { + return ((Number) flowId).intValue(); + } + + // 尝试从 metadata 中获取(上行消息的流水号) + if (map.get("_metadata") instanceof Map) { + Map metadata = (Map) map.get("_metadata"); + Object metaFlowId = metadata.get("flowId"); + if (metaFlowId instanceof Number) { + return ((Number) metaFlowId).intValue(); + } + } + + return null; + } + /** * 获取参数为Map + * + * 优先从 params 获取,如果 params 为空则从 data 获取(应答消息场景) */ @SuppressWarnings("unchecked") private Map getParamsAsMap(IotDeviceMessage message) { + // 优先从 params 获取 if (message.getParams() instanceof Map) { return (Map) message.getParams(); } - // 尝试JSON转换 + + // 从 data 获取(应答消息使用 replyOf 时,参数在 data 字段) + if (message.getData() instanceof Map) { + return (Map) message.getData(); + } + + // 尝试JSON转换 params if (message.getParams() != null) { String json = JsonUtils.toJsonString(message.getParams()); return JsonUtils.parseObject(json, Map.class); } + + // 尝试JSON转换 data + if (message.getData() != null) { + String json = JsonUtils.toJsonString(message.getData()); + return JsonUtils.parseObject(json, Map.class); + } + return new HashMap<>(); }