fix: 修复java.lang.RuntimeException: JT808 消息编码失败: 消息参数格式错误,params 必须是 Map 类型
All checks were successful
aiot-platform CI/CD / build-and-deploy (push) Successful in 7m41s
All checks were successful
aiot-platform CI/CD / build-and-deploy (push) Successful in 7m41s
at com.viewshanghai.module.iot.gateway.codec.jt808.IotJt808DeviceMessageCodec.encode(IotJt808DeviceMessageCodec.java:77) ~[!/:na]
This commit is contained in:
@@ -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<String, Object> getParamsAsMap(IotDeviceMessage message) {
|
||||
// 优先从 params 获取
|
||||
if (message.getParams() instanceof Map) {
|
||||
return (Map<String, Object>) message.getParams();
|
||||
}
|
||||
// 尝试JSON转换
|
||||
|
||||
// 从 data 获取(应答消息使用 replyOf 时,参数在 data 字段)
|
||||
if (message.getData() instanceof Map) {
|
||||
return (Map<String, Object>) 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<>();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user