This commit is contained in:
@@ -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) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,9 @@ public class LocationPack extends DataPack {
|
||||
// GMT+8 时间,本标准中之后涉及的时间均采用此时区
|
||||
private Date time;
|
||||
|
||||
// Bluetooth Extension Data
|
||||
private java.util.List<BluetoothInfo> bluetoothInfos;
|
||||
|
||||
public LocationPack() {
|
||||
}
|
||||
|
||||
@@ -92,6 +95,14 @@ public class LocationPack extends DataPack {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public java.util.List<BluetoothInfo> getBluetoothInfos() {
|
||||
return bluetoothInfos;
|
||||
}
|
||||
|
||||
public void setBluetoothInfos(java.util.List<BluetoothInfo> 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 + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<BluetoothInfo> 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; k<mac.length(); k+=2) {
|
||||
if(k>0) 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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user