diff --git a/src/main/java/com/hua/transport/jt808/entity/request/BluetoothInfo.java b/src/main/java/com/hua/transport/jt808/entity/request/BluetoothInfo.java new file mode 100644 index 0000000..f7101c2 --- /dev/null +++ b/src/main/java/com/hua/transport/jt808/entity/request/BluetoothInfo.java @@ -0,0 +1,63 @@ +package com.hua.transport.jt808.entity.request; + +import java.util.List; + +public class BluetoothInfo { + private String mac; + private int rssi; + // 0xF3 specific fields + private String customData; + + // Type of bluetooth info: 0xF3 or 0xF4 + private int type; + + public BluetoothInfo() {} + + public BluetoothInfo(String mac, int rssi) { + this.mac = mac; + this.rssi = rssi; + } + + public String getMac() { + return mac; + } + + public void setMac(String mac) { + this.mac = mac; + } + + public int getRssi() { + return rssi; + } + + public void setRssi(int rssi) { + this.rssi = rssi; + } + + public String getCustomData() { + return customData; + } + + public void setCustomData(String customData) { + this.customData = customData; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + @Override + public String toString() { + return "BluetoothInfo{" + + "mac='" + mac + '\'' + + ", rssi=" + rssi + + ", customData='" + customData + '\'' + + ", type=" + String.format("0x%02X", type) + + '}'; + } +} + diff --git a/src/main/java/com/hua/transport/jt808/entity/request/LocationPack.java b/src/main/java/com/hua/transport/jt808/entity/request/LocationPack.java index 2e6ed4c..c0b4685 100644 --- a/src/main/java/com/hua/transport/jt808/entity/request/LocationPack.java +++ b/src/main/java/com/hua/transport/jt808/entity/request/LocationPack.java @@ -32,6 +32,9 @@ public class LocationPack extends DataPack { // byte[22-x] 时间(BCD[6]) YY-MM-DD-hh-mm-ss // GMT+8 时间,本标准中之后涉及的时间均采用此时区 private Date time; + + // Bluetooth Extension Data + private java.util.List bluetoothInfos; public LocationPack() { } @@ -92,6 +95,14 @@ public class LocationPack extends DataPack { this.time = time; } + public java.util.List getBluetoothInfos() { + return bluetoothInfos; + } + + public void setBluetoothInfos(java.util.List bluetoothInfos) { + this.bluetoothInfos = bluetoothInfos; + } + public int getWarningFlagField() { return warningFlagField; } @@ -112,7 +123,7 @@ public class LocationPack extends DataPack { public String toString() { return "LocationInfoUploadMsg [warningFlagField=" + warningFlagField + ", statusField=" + statusField + ", latitude=" + latitude + ", longitude=" + longitude + ", elevation=" + elevation + ", speed=" - + speed + ", direction=" + direction + ", time=" + time + "]"; + + speed + ", direction=" + direction + ", time=" + time + ", bluetoothInfos=" + bluetoothInfos + "]"; } } diff --git a/src/main/java/com/hua/transport/jt808/service/codec/DataDecoder.java b/src/main/java/com/hua/transport/jt808/service/codec/DataDecoder.java index 18f9292..324e58a 100644 --- a/src/main/java/com/hua/transport/jt808/service/codec/DataDecoder.java +++ b/src/main/java/com/hua/transport/jt808/service/codec/DataDecoder.java @@ -12,6 +12,11 @@ import com.hua.transport.jt808.entity.request.RegisterPack.TerminalRegInfo; import com.hua.transport.jt808.util.BCDUtil; import com.hua.transport.jt808.util.BitUtil; +import com.hua.transport.jt808.entity.request.BluetoothInfo; +import com.hua.transport.jt808.util.HexUtil; +import java.util.ArrayList; +import java.util.List; + /** * 数据包解码器 * @author huaxl @@ -219,7 +224,7 @@ public class DataDecoder { // 5. byte[16-17] 高程(WORD(16)) 海拔高度,单位为米( m) ret.setElevation(this.parseIntFromBytes(data, 16, 2)); // byte[18-19] 速度(WORD) 1/10km/h - ret.setSpeed(this.parseFloatFromBytes(data, 18, 2)); + ret.setSpeed(this.parseIntFromBytes(data, 18, 2) / 10.0f); // byte[20-21] 方向(WORD) 0-359,正北为 0,顺时针 ret.setDirection(this.parseIntFromBytes(data, 20, 2)); // byte[22-x] 时间(BCD[6]) YY-MM-DD-hh-mm-ss @@ -229,6 +234,95 @@ public class DataDecoder { byte[] tmp = new byte[6]; System.arraycopy(data, 22, tmp, 0, 6); String time = this.parseBcdStringFromBytes(data, 22, 6); + + // 扩展协议解析 (Starting from index 28) + int index = 28; + List bluetoothInfos = new ArrayList<>(); + + while (index < data.length) { + int extId = data[index] & 0xFF; + // Ensure we have at least ID and Length bytes + if (index + 1 >= data.length) break; + int extLen = data[index + 1] & 0xFF; + + if (extId == 0xF3) { + // F3 扩展 (蓝牙信标扫描附加信息) + // index+2: 特定标识 0xE6 + // index+3: 特定标识 0x0C + // index+4: 扫描到的蓝牙数据组数 + if (index + 4 < data.length) { + int groupCount = data[index + 4] & 0xFF; + int currentOffset = index + 5; + + for (int i = 0; i < groupCount; i++) { + if (currentOffset + 7 > data.length) break; + + // MAC (6 bytes) + byte[] macBytes = new byte[6]; + System.arraycopy(data, currentOffset, macBytes, 0, 6); + String mac = HexUtil.toHexString(macBytes); + // Add colons to MAC + StringBuilder sb = new StringBuilder(); + for(int k=0; k0) sb.append(":"); + sb.append(mac.substring(k, k+2)); + } + String macStr = sb.toString().toUpperCase(); + + // RSSI (1 byte) + int rssi = data[currentOffset + 6]; // Signed byte + + BluetoothInfo info = new BluetoothInfo(macStr, rssi); + info.setType(0xF3); + bluetoothInfos.add(info); + + currentOffset += 7; + } + + // Try to capture custom data if present at the end of the block + int expectedEnd = index + 2 + extLen; + if (currentOffset < expectedEnd && expectedEnd <= data.length) { + int customLen = expectedEnd - currentOffset; + byte[] customBytes = new byte[customLen]; + System.arraycopy(data, currentOffset, customBytes, 0, customLen); + String customHex = HexUtil.toHexString(customBytes); + if (!bluetoothInfos.isEmpty()) { + bluetoothInfos.get(bluetoothInfos.size() - 1).setCustomData(customHex); + } + } + } + + } else if (extId == 0xF4) { + // F4 扩展 (蓝牙BLE扫描周围同类产品) + // index+2: 扫描到的蓝牙数据组数 + if (index + 2 < data.length) { + int groupCount = data[index + 2] & 0xFF; + int currentOffset = index + 3; + + for (int i = 0; i < groupCount; i++) { + // Each group: 6 bytes MAC (from IMEI) + 1 byte RSSI = 7 bytes + if (currentOffset + 7 > data.length) break; + + byte[] macBytes = new byte[6]; + System.arraycopy(data, currentOffset, macBytes, 0, 6); + String mac = HexUtil.toHexString(macBytes); // This is partial IMEI + // RSSI (1 byte) + int rssi = data[currentOffset + 6]; + + BluetoothInfo info = new BluetoothInfo(mac, rssi); // raw hex as mac for now + info.setType(0xF4); + bluetoothInfos.add(info); + + currentOffset += 7; + } + } + } + + index += (2 + extLen); + } + + ret.setBluetoothInfos(bluetoothInfos); + return ret; }