Stima faro di prossimità / distanza basato su RSSI - Bluetooth LE

? JakeP @ | Original: StackOverFlow
---

Ho una semplice applicazione iOS che visualizza la vicinanza del LE Bluetooth beacons rileva usando espressioni come " immediata", " vicino ", ecc e ho bisogno di scrivere qualcosa di simile su Android .

Ho seguito il tutorial a https://developer.android.com/guide/topics/connectivity/bluetooth-le.html e sono in grado di elencare i dispositivi rilevati e ora vuole stimare la distanza / vicinanza - è qui è diventato un problema . Secondo http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing è solo una manciata di calcoli matematici . Tuttavia, mi hanno bisogno per fornire un valore txpower .

Secondo https://thenewcircle.com/s/post/1553/bluetooth_smart_le_android_tutorial ( e riferimenti incrociati con questo https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile ), dovrebbe essere trasmesso dai dispositivi beacon come una "struttura AD " di tipo 0x0A . Quindi quello che faccio è analizzare le strutture AD e cercare il payload di quello che corrisponde al tipo .

Problema : Ho 4 fari - 2 estimotes e 2 appflares . I estimotes non trasmettono il txpower a tutti e le appflares loro trasmessi come 0 .

C'è qualcosa mi manca qui ? L'applicazione iOS sembra essere la manipolazione tutto senza alcun problema, ma utilizzando l'SDK di iOS lo fa dietro le quinte, quindi non sono sicuro di come produrre la stessa o simile esatto comportamento . C'è un altro modo ho potuto risolvere il mio problema ?

In caso vuoi dare un'occhiata al codice che sto usando per analizzare le strutture AD, è preso dalla GitHub del citato Dave Smith e può essere trovato https://github.com/devunwired/accessory-samples/blob/master/BluetoothGatt/src/com/example/bluetoothgatt/AdRecord.java . L' unico cambiamento che ho fatto a quella classe era aggiungere il seguente metodo :

public byte[] getData() {

    return mData;
}

E questo è come gestire il callback dalle scansioni :

// Prepare the callback for BLE device scan
this.leScanCallback = new BluetoothAdapter.LeScanCallback() {

    @Override
    public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {

        if (!deviceList.contains(device)) {

            MyService.this.deviceList.add(device);
            Log.e("Test", "Device: " + device.getName());

            List<AdRecord> adRecords = AdRecord.parseScanRecord(scanRecord);

            for (AdRecord adRecord : adRecords) {

                if (adRecord.getType() == AdRecord.TYPE_TRANSMITPOWER) {

                    Log.e("Test", "size of payload: " + adRecord.getData().length);
                    Log.e("Test", "payload: " + Byte.toString(adRecord.getData()[0]));
                }
            }
        }
    }
};

E quello che vedo nella console è :

04-01 11:33:35.864: E/Test(15061): Device: estimote
04-01 11:33:36.304: E/Test(15061): Device: estimote
04-01 11:33:36.475: E/Test(15061): Device: n86
04-01 11:33:36.475: E/Test(15061): size of payload: 1
04-01 11:33:36.475: E/Test(15061): payload: 0
04-01 11:33:36.525: E/Test(15061): Device: f79
04-01 11:33:36.525: E/Test(15061): size of payload: 1
04-01 11:33:36.525: E/Test(15061): payload: 0
---

Top 5 Risposta

1davidgyoung @

Non è chiaro se la vostra incapacità di leggere il o costante di calibrazione " txpower " " measuredPower " è dovuto alla classe AdRecord o per le informazioni essere mancante gli annunci si sta cercando di analizzare . Non sembra a me come quella classe sarà analizzare un iBeacon annuncio standard. In entrambi i casi, c'è una soluzione :

SOLUZIONE 1 : Se i fari inviare una pubblicità iBeacon standard che include la costante di calibrazione, è possibile analizzarlo utilizzando codice nella classe IBeacon open source http://developer.radiusnetworks.com/ibeacon/android/ s ' https://github.com/RadiusNetworks/android-ibeacon-service/blob/master/src/main/java/com/radiusnetworks/ibeacon/IBeacon.java

SOLUZIONE 2 : Se i fari non inviare un iBeacon pubblicità standard o non includono una costante di calibrazione :

È necessario codificare una costante di calibrazione in app per ogni tipo di dispositivo che si potrebbe utilizzare . Tutto ciò che dovete dalla pubblicità per stimare la distanza è la misurazione RSSI . Il punto di incorporare una costante calibrazione nella trasmissione è di consentire una grande varietà di fari con ben diversa potenza di uscita del trasmettitore di lavorare con lo stesso algoritmo distanza stima .

La costante di calibrazione, come definito da Apple, in sostanza dice quello che il RSSI dovrebbe essere se il vostro dispositivo è esattamente un metro di distanza dal faro . Se il segnale è più forte ( RSSI meno negativo ), allora il dispositivo è inferiore a un metro di distanza . Se il segnale è più debole ( RSSI più negativo ), allora il dispositivo è più di un metro di distanza . È possibile utilizzare una formula per fare una stima numerica della distanza . http://stackoverflow.com/a/20434019/1461050

Se non si tratta di pubblicità che contengono una o " measuredPower " costante di calibrazione " txpower ", allora si può codificare una tabella di ricerca nel vostro app che memorizza le costanti di calibrazione noti per vari trasmettitori . Per prima cosa è necessario misurare la RSSI media di ogni trasmettitore a un metro di distanza . Avrete quindi bisogno di un qualche tipo di chiave per cercare queste costanti di calibrazione nella tabella. ( Forse è possibile utilizzare la una parte della stringa dalla struttura dC, o l' indirizzo MAC ? ) Quindi la tabella potrebbe assomigliare a questo :

HashMap<String,Integer> txPowerLookupTable = new HashMap<String,Integer>();
txPowerLookupTable.put("a5:09:37:78:c3:22", new Integer(-65));
txPowerLookupTable.put("d2:32:33:5c:87:09", new Integer(-78));

Poi, dopo l'analisi di un annuncio, è possibile cercare la costante di calibrazione nel metodo onLeScan come questo :

String macAddress = device.getAddress();
Integer txPower = txPowerLookupTable.get(macAddress);
2tep @

Il txPower menzionato da davidgyoung è dato dalla formula :

RSSI = -10nlogd + A

dove d = distanza, A = txpower, n = segnale costante di propagazione e [ RSSI ] = dBm .

Nello spazio libero n = 2, ma può variare in base alla geometria locale - per esempio, un muro ridurrà rssi di ~ 3dBm e interesserà n conseguenza.

Se si desidera la massima precisione possibile, può essere utile per determinare sperimentalmente questi valori per il sistema particolare .

Riferimento : vedi http://www.rn.inf.tu-dresden.de/dargie/papers/icwcuca.pdf per una spiegazione più dettagliata di derivazione e calibrazione .

3user1423561 @

utilizzare il metodo getAccuracy ( ) nella libreria, ti dà la distanza del faro

4snayde @
double getDistance(int rssi, int txPower) {
    /*
     * RSSI = TxPower - 10 * n * lg(d)
     * n = 2 (in free space)
     * 
     * d = 10 ^ ((TxPower - RSSI) / (10 * n))
     */

    return Math.pow(10d, ((double) txPower - rssi) / (10 * 2));
}