2

我現在有一個問題,因爲我試圖從我的Onyx iBeacon讀取tx-Power。我已閱讀了多個建議,並在互聯網上嘗試了很多代碼,但我仍然無法弄清楚。Android:iBeacon - 閱讀其廣告(例如txPower)

我正在使用android棒棒糖,並嘗試從https://github.com/devunwired/accessory-samples/tree/master/BluetoothGatt 的iBeacon教程中提取BLUETOOTH_THERM_SERVICE的藍牙應用程序。

我發現了發射機功率兩個值從廣告: Bluetooth LE TX Power reading

0x1804及其特點0x2A07,所以我適應了包裹UUID與0x1804過濾我ScanResults:如上所述

public static final ParcelUuid THERM_SERVICE = ParcelUuid.fromString("00001809-0000-1000-8000-00805f9b34fb"); 
    public static final ParcelUuid TX_POWER_SERVICE = ParcelUuid.fromString("00001804-0000-1000-8000-00805F9B34FB"); 
    public static final ParcelUuid ONYX_STANDARD_SERVICE = ParcelUuid.fromString("0000180a-0000-1000-8000-00805f9b34fb"); 

在教程中:

byte[] data = record.getServiceData(TX_POWER_SERVICE); 

應該存儲一個字節數組,但它總是返回null!存儲字節數組,但我認爲它存儲了整個記錄的唯一的事情是:

byte[] data = record.getServiceData(ONYX_STANDARD_SERVICE); 

試圖移動並使用我可以ONYX_STANDARD_SERVICE獲取數據,我可以看到一個scanResult:

onScanResult() - ScanResult{mDevice=78:A5:04:07:AE:96, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=null, mManufacturerSpecificData={76=[2, 21, 32, -54, -24, -96, -87, -49, 17, -29, -91, -30, 8, 0, 32, 12, -102, 102, 0, 7, -82, -106, -78]}, mServiceData={0000180a-0000-1000-8000-00805f9b34fb=[120, -91, 4, 7, -82, -106, -78, 32, -54, -24, -96, 0, 7, -82, -106]}, mTxPowerLevel=-2147483648, mDeviceName=OnyxBeacon], mRssi=-63, mTimestampNanos=174691272168825} 

我覺得我的紀錄的重要組成部分是:

mServiceData={0000180a-0000-1000-8000-00805f9b34fb=[120, -91, 4, 7, -82, -106, -78, 32, -54, -24, -96, 0, 7, -82, -106]} 

如何從這個ServiceData提取我的TXPOWER價值?我檢查了幾個應用程序,我的TX功率是-78。

通過使用ONYX_STANDARD_SERVICE檢查結果,我可以通過scanResult[6] = -78得到該值。

這是做到這一點的正確方法,如果是的話,爲什麼?

我也發現了這個問題,即另一個值提到從記錄讀一些有趣的例子:

https://github.com/google/uribeacon/blob/master/android-uribeacon/uribeacon-library/src/main/java/org/uribeacon/scan/compat/ScanRecord.java

如果你看看這裏,你會發現代碼:

private static final int DATA_TYPE_TX_POWER_LEVEL = 0x0A; 

其中哪一個(0x1804,0x2A070x0A)是正確的?

這也將是不錯,但有人可以解釋我沒有必要從如何獲得THERM_SERVICE工程示例代碼:

private float parseTemp(byte[] serviceData) { 
     /* 
     * Temperature data is two bytes, and precision is 0.5degC. 
     * LSB contains temperature whole number 
     * MSB contains a bit flag noting if fractional part exists 
     */ 
     float temp = (serviceData[0] & 0xFF); 
     if ((serviceData[1] & 0x80) != 0) { 
      temp += 0.5f; 
     } 

     return temp; 
    } 

請幫我在閱讀廣告數據和提取發射機功率。

回答

7

可以從廣告數據包中獲得OnyxBeacon的傳輸(TX)功率,以及任何其他與IBeacon兼容的BLE設備的功率。這不需要連接到設備。而且,TX功率值將根據功率水平而變化,因爲TX功率值是針對設備的每個功率水平校準的。 TX功率是廣告有效載荷的最後一個字節。在iBeacon顯示數據包的結構的詳細信息可以在這裏找到:http://www.havlena.net/en/location-technologies/ibeacons-how-do-they-technically-work/

下面是如何解析的iBeacon顯示數據包並獲得TX功率樣本:

BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { 
    @Override 
    public void onLeScan(final BluetoothDevice bluetoothDevice, final int rssi, final byte[] scanData) { 
     if (scanData[7] == 0x02 && scanData[8] == 0x15) { // iBeacon indicator 
      System.out.println("iBeacon Packet: %s", bytesToHexString(scanData)); 
      UUID uuid = getGuidFromByteArray(Arrays.copyOfRange(scanData, 9, 25)); 
      int major = (scanData[25] & 0xff) * 0x100 + (scanData[26] & 0xff); 
      int minor = (scanData[27] & 0xff) * 0x100 + (scanData[28] & 0xff); 
      byte txpw = scanData[29]; 
      System.out.println("iBeacon Major = " + major + " | Minor = " + minor + " TxPw " + (int)txpw + " | UUID = " + uuid.toString()); 
     } 
    } 
}; 

public static String bytesToHexString(byte[] bytes) { 
    StringBuilder buffer = new StringBuilder(); 
    for(int i=0; i<bytes.length; i++) { 
     buffer.append(String.format("%02x", bytes[i]); 
    } 
    return buffer.toString(); 
} 
public static UUID getGuidFromByteArray(byte[] bytes) 
{ 
    ByteBuffer bb = ByteBuffer.wrap(bytes); 
    UUID uuid = new UUID(bb.getLong(), bb.getLong()); 
    return uuid; 
} 
+0

非常感謝你的榜樣! 你能解釋一下主要和次要代碼嗎? 就像'&0xff'用'scanData [25]'做的那樣,爲什麼你用'0x100'來乘它呢? 我想事後我可以理解一切方式,即使你已經幫助了我很多:) – BigPenguin

+1

主要和次要無符號短整型,所以他們有2個字節的長度。 'scanData'是一個字節數組,所以我們必須從兩個字節構造一個'unsigned short'。主要值字節位於'scanData [25]'和'scanData [26]',其中'scanData [25]'是最高有效字節,'scanData [26]'是最低有效字節。 '&0xff'確保字節的掩碼,以確保只使用最後一個字節。 * 0x100等同於「<< 8」。因此,位置25處的字節向左移動8位,爲位置26處的字節留出空間。將這些值相加後得出主要的無符號短值。 – istirbu

1

1.如何從此ServiceData提取我的txPower值?我檢查了幾個應用程序,我的TX功率是-78

那麼,從實際的角度來看,在iBeacon配置文件中有兩種類型的廣告數據。

第一個是製造商數據。由於這些類型,您可以閱讀您的信標的Proximity UUID,Major,Minor或Transmission Power值。無論ibeacon設備製造商如何,都可以從任何iBeacon的廣告數據包中讀取此類型。您可以看到how the layout of the data looks like並對其進行解析以提取特定於接近度的值(您也可以找到information about it here at page no 3)。

第二個是服務數據。與第一種類型相反,這個可以定製,例如kontakt.io iBeacon提供了由4個ASCII符號固件版本和發射功率電平(從0到7)組成的唯一ID。

2.檢查與ONYX_STANDARD_SERVICE結果我可以得到scanResult這個值[6] = -78 這是做正確的方式,如果是這樣,爲什麼?

我還沒有看到Onyx Beacon規範,但是如果tx Power包含在服務數據中,那麼我建議找出描述Tx Power的字節/字節在哪個位置。您的iBeacon提供商應該知道它。

3.如何從此ServiceData中提取我的txPower值?我檢查了幾個應用程序,我的TX功率是-78

如上所述,您可以從製造商數據默認讀取計算的傳輸功率。但是,如果Onyx beacon提供有關服務數據中的tx功率的任何其他信息,則應從Onyx spec-or-sth-like文件中獲取信息。

4.檢查與ONYX_STANDARD_SERVICE結果我可以得到scanResult這個值[6] = -78 這是做正確的方式,如果是這樣,爲什麼?

URI Beacon specification明確指出在哪個位置可以找到包含txPower的每條信息。我不認爲瑪瑙燈塔與Uri Beacon有許多共同之處。

5.這也將是不錯,但有人可以解釋我獲得THERM_SERVICE示例代碼是如何工作的沒有必要的:

沒有什麼困難在這裏。從代碼片段中,我假設在位置0處的服務數據中存在描述溫度的值(範圍從0到255)。下一個字節指定小數位。 這是你問的,順便說一句?

6.請幫我在閱讀廣告數據和提取TXPOWER :)

爲了這裏解析任何iBeacon顯示相關的數據是一個簡單的代碼返回SparseArray哪裏綁定表示數據類型的按鍵和字節幀類型。該代碼在假設您解析從遠程IBeacon設備讀取的整個字節幀的情況下工作。

private static SparseArray<byte[]> extractMetaData(final byte[] scanRecord) { 
    int index = 0; 
    final SparseArray<byte[]> map = new SparseArray<byte[]>(); 
    final int scanRecordLength = scanRecord.length; 
    while (index < scanRecordLength) { 
     final int length = scanRecord[index++]; 

     if (length == 0) { 
      break; 
     } 

     final int type = Converter.asInt(scanRecord[index]); 

     if (type == 0) { 
      break; 
     } 

     final byte[] data = Arrays.copyOfRange(scanRecord, index + 1, index + length); 

     map.put(type, data); 

     index += length; 
    } 

    return map; 
} 

我建議深入探究Bluetooth-LE--Android project。通過檢查代碼,我學到了 有價值的信息。並且不要忘記明星。

希望我至少澄清一下你的問題。

+0

非常感謝您爲您詳細解釋關於這個話題。我發現Bluetooth-LE-Android項目非常容易理解,現在我只是在從scanRecord中提取它們之後過濾UUID。 – BigPenguin

+0

我建議嘗試使用kontakt.io SDK和kontakt-beacon-admin-sample-app(https://github.com/kontaktio/kontakt-beacon-admin-sample-app)。 –