fix(iot): 修复JT808事件消息identifier字段不匹配问题
- 修复 parseButtonEventAsEvent 使用 eventId 而非 identifier - 添加消息体长度校验,防止越界访问 - 解码失败时返回 null 而非抛异常,避免断开连接 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -90,11 +90,20 @@ public class IotJt808DeviceMessageCodec implements IotDeviceMessageCodec {
|
||||
// 2. 解析为 JT808 数据包
|
||||
Jt808DataPack dataPack = decoder.bytes2PackageData(unescapedBytes);
|
||||
|
||||
// 3. 转换为统一的 IotDeviceMessage
|
||||
// 3. 检查消息体是否有效(null 表示长度不匹配错误,空数组表示合法的空消息体如心跳)
|
||||
if (dataPack.getBodyBytes() == null) {
|
||||
// 长度不匹配,返回 null 由上层跳过该消息
|
||||
log.warn("[decode][消息体长度不匹配,跳过该消息,消息ID=0x{}]",
|
||||
Integer.toHexString(dataPack.getPackHead().getId()));
|
||||
return null;
|
||||
}
|
||||
|
||||
// 4. 转换为统一的 IotDeviceMessage(包括空消息体的消息如心跳)
|
||||
return convertToIotDeviceMessage(dataPack);
|
||||
} catch (Exception e) {
|
||||
log.error("[decode][JT808 消息解码失败,数据长度: {}]", bytes.length, e);
|
||||
throw new RuntimeException("JT808 消息解码失败: " + e.getMessage(), e);
|
||||
// 解码失败返回 null,不断开连接
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +217,7 @@ public class IotJt808DeviceMessageCodec implements IotDeviceMessageCodec {
|
||||
*
|
||||
* 物模型标准格式:
|
||||
* {
|
||||
* "eventId": "button_event",
|
||||
* "identifier": "button_event",
|
||||
* "eventTime": 1234567890,
|
||||
* "params": {
|
||||
* "keyId": 1,
|
||||
@@ -225,7 +234,8 @@ public class IotJt808DeviceMessageCodec implements IotDeviceMessageCodec {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
// 统一使用一个事件标识符,通过 isLongPress 参数区分短按和长按
|
||||
result.put("eventId", "button_event");
|
||||
// 注意:必须使用 "identifier" 字段,以便 IotDeviceMessageUtils.getIdentifier() 正确提取
|
||||
result.put("identifier", "button_event");
|
||||
|
||||
// 事件时间戳
|
||||
result.put("eventTime", System.currentTimeMillis());
|
||||
|
||||
@@ -43,6 +43,29 @@ public class Jt808Decoder {
|
||||
msgBodyByteStartIndex = 16;
|
||||
}
|
||||
|
||||
// 验证消息体长度,防止越界
|
||||
int expectedBodyLength = msgHeader.getBodyLength();
|
||||
int actualAvailableLength = data.length - msgBodyByteStartIndex - 1; // -1 for checksum
|
||||
|
||||
// 检查数据长度是否足够(至少要包含消息头和校验码)
|
||||
if (data.length < msgBodyByteStartIndex + 1) {
|
||||
log.warn("[bytes2PackageData][数据长度不足: 头部需要={}, 实际={}, 消息ID=0x{}]",
|
||||
msgBodyByteStartIndex + 1, data.length, Integer.toHexString(msgHeader.getId()));
|
||||
ret.setBodyBytes(null); // 使用 null 标记错误状态
|
||||
ret.setCheckSum(0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (expectedBodyLength > actualAvailableLength) {
|
||||
log.warn("[bytes2PackageData][消息体长度不匹配: 头部声明={}, 实际可用={}, 数据总长度={}, 消息ID=0x{}]",
|
||||
expectedBodyLength, actualAvailableLength, data.length,
|
||||
Integer.toHexString(msgHeader.getId()));
|
||||
// 使用 null 标记长度不匹配(区别于合法的空消息体如心跳)
|
||||
ret.setBodyBytes(null);
|
||||
ret.setCheckSum(data[data.length - 1]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
byte[] bodyBytes = new byte[msgHeader.getBodyLength()];
|
||||
System.arraycopy(data, msgBodyByteStartIndex, bodyBytes, 0, bodyBytes.length);
|
||||
ret.setBodyBytes(bodyBytes);
|
||||
|
||||
Reference in New Issue
Block a user