藍牙廣播數(shù)據(jù)解析
從上一篇我們提到的那樣我們從系統(tǒng)的接收到了 關于藍牙數(shù)據(jù)的相關信息,藍牙的設備對象、藍牙信號、標準藍牙廣播數(shù)據(jù)包等數(shù)據(jù)。
==================================================================================================================
作為我們開發(fā)的場景來說,我們需要對我們的設備進行必要的過濾,但是這個過濾的數(shù)據(jù)來源除了廣播數(shù)據(jù)包,好像是沒有其他辦法的。當然名字也還是那么靠譜的,會有系統(tǒng)的緩存的。
所以我們需要做一些藍牙廣播的數(shù)據(jù)的解析。說到藍牙的數(shù)據(jù)的數(shù)據(jù)解析的問題,就不得不提關于藍牙的數(shù)據(jù)結構,不過這個網(wǎng)上有很多,百度一下,出來的結果能嚇死你,哈哈。畢竟度娘是厲害的。-------言歸正傳:
藍牙的數(shù)據(jù)結構采用的方式。這有一篇文章還不錯的推薦給大家
http://blog.chinaunix.net/uid-28852942-id-5176579.html
其實在我們android 開發(fā)的數(shù)據(jù)解析中 倒是沒有說的那么復雜,比方來說,
0201060303f1fe03190000020a080aff0000000000000000041509efbbbfe5beaee699ba426561636f6ee6a0bc5a690
上方是一個藍牙數(shù)據(jù)(這個數(shù)據(jù)是我隨便弄得只是做為示范)
對于我們開發(fā)來說
我們知道這樣的數(shù)據(jù)構成就OK了
- 020106
- 這是一個完全的“最小單元有意義的藍牙廣播數(shù)據(jù)”了吧。
- 02表示這個數(shù)據(jù)的長度,也就是Length.
- 01表示這個信息的標識,也就是Tag.
- 01后面開始就是這個數(shù)據(jù)含有真正的數(shù)據(jù),
- 此時需要注意的是02表示長度是除去自身以外的長度, 如果你要數(shù)字節(jié)個數(shù)的話 你需要加1
0303f1fe
03190000
020a08
0a ff 00 00 00 00 00 00 00 00 04
15 09 efbbbfe5beaee699ba426561636
其他的都是一樣的 我就不做一一解析了。
所以我們解析這個數(shù)據(jù)的時候都是解析相關的TAG,然后可以拿到我們需要的數(shù)據(jù),我記得剛剛開始的時候,我是拿著這個數(shù)據(jù)直姐用索引取值,結果我們的固件版本一升級,索引值變了。我那個寫死的數(shù)據(jù)就完蛋了。結果當然是教育了啦。
提一些的是關于常見的Tag,01一般表示是否可連接的狀態(tài)。08、09一般都是可以表示設備的名稱。但是也有很多是不廣播名稱的。
好吧BB那么多貼上源碼才是關鍵以下是源碼:
public static class BTScanInfo {
//數(shù)據(jù)庫
public BleDevice dev;
public byte[] advt;
public double rssi = -10000.0;
public static final int
BT_ADVT_FIELD_SHORT_SVC_UUID_MORE = 0x02,
BT_ADVT_FIELD_SHORT_SVC_UUID_COMP = 0x03,
BT_ADVT_FIELD_MANU_INFO = 0xFF,
BT_ADVT_FIEFD_NAME_INFO = 0x09,
BT_ADVT_FIEFD_SUPPROTS_INFO = 0xFF;
public int svcMoreOffset = -1, svcMoreLen = -1,
svcOffset = -1, svcLen = -1, isSupprots = 14,
manuOffset = -1, manuLen = -1,
nameOffset = -1, nameLen = -1,
lightOffset = -1, lightLen = -1;
public BTScanInfo(BleDevice dev_, byte[] advt_, double rssi_) {
Log.i(dev_.getAddress(), "BtScanInfo==" + dev_.getAddress());
dev = dev_;
advt = advt_;
rssi = rssi_;
ParseAdvt();
}
public void ParseAdvt() {
if (advt == null)
return;
for (int offset = 0 ; offset < advt.length ; ) {
int fieldLen = (advt[ offset ] & 0xFF);
if (fieldLen < 1) {
offset += fieldLen + 1;
// Log.v(TAG, "Find a invalid scan advert field length: " + fieldLen );
continue;
}
// a valid field.
if (offset + fieldLen <= advt.length) {
int fieldType = advt[ offset + 1 ] & 0xFF;
if (fieldType == BT_ADVT_FIELD_SHORT_SVC_UUID_MORE) {
svcMoreOffset = offset;
svcMoreLen = fieldLen;
} else if (fieldType == BT_ADVT_FIELD_SHORT_SVC_UUID_COMP) {
svcOffset = offset;
svcLen = fieldLen;
} else if (fieldType == BT_ADVT_FIELD_MANU_INFO & fieldLen == BT_ADVT_FIEFD_NAME_INFO) {
manuOffset = offset;
manuLen = fieldLen;
} else if (fieldType == BT_ADVT_FIEFD_NAME_INFO) {
//獲取到名字信息
nameOffset = offset;
nameLen = fieldLen;
}
}
offset += fieldLen + 1;
}
}