Estimando beacon proximidade / distância baseada em RSSI - Bluetooth LE

? JakeP @ | Original: StackOverFlow
---

Eu tenho um app iOS simples que mostra a proximidade do Bluetooth LE balizas detecta usando expressões como "imediata", " próximo" e etc. Eu preciso escrever algo semelhante no Android.

Eu segui o tutorial em https://developer.android.com/guide/topics/connectivity/bluetooth-le.html e eu sou capaz de listar os dispositivos detectados e agora deseja estimar a distância / proximidade - este é o lugar onde é tornar-se um problema. De acordo com http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing é apenas um punhado de cálculos matemáticos . No entanto, eles me exigem para fornecer um valor txpower .

De acordo com https://thenewcircle.com/s/post/1553/bluetooth_smart_le_android_tutorial (e referência cruzada com esta https://www.bluetooth.org/en-us/specification/assigned-numbers/generic-access-profile ), deve ser transmitida pelos dispositivos de beacon como uma " estrutura o AD " do tipo 0x0A . Então, o que eu faço é analisar as estruturas de AD e olhar para a carga útil do que combine com o tipo .

Problema : Eu tenho quatro beacons - 2 estimotes e 2 appflares . Os estimotes não transmitir o txpower em tudo e os appflares deles difundidos como 0 .

Existe alguma coisa que eu estou ausente aqui? O app iOS parece estar lidando com isso tudo, sem qualquer problema, mas usando o SDK iOS fá-lo nos bastidores para que eu não tenho certeza de como produzir o comportamento exatamente o mesmo ou similar. Existe alguma outra maneira que eu poderia resolver o meu problema ?

No caso de você gostaria de dar uma olhada no código que estou usando para analisar as estruturas anúncio, é retirado do github do supracitado Dave Smith e pode ser encontrado https://github.com/devunwired/accessory-samples/blob/master/BluetoothGatt/src/com/example/bluetoothgatt/AdRecord.java . A única mudança que eu fiz para essa classe foi adicionar o seguinte método:

public byte[] getData() {

    return mData;
}

E é assim que eu lidar com a resposta a partir dos scans :

// 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 o que vejo no 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 Responder

1davidgyoung @

Não está claro se a sua incapacidade de ler o " txpower " ou " measuredPower " constante de calibração é devido ao AdRecord classe ou devido à informação estar faltando os anúncios que você está tentando analisar. Não me parece que a classe irá analisar uma iBeacon anúncio padrão. De qualquer maneira, existe uma solução :

Solução 1: Se as suas balizas enviar uma propaganda iBeacon padrão que inclui a constante de calibração, é possível analisá-lo fora usando o código no código aberto http://developer.radiusnetworks.com/ibeacon/android/ ' s classe IBeacon https://github.com/RadiusNetworks/android-ibeacon-service/blob/master/src/main/java/com/radiusnetworks/ibeacon/IBeacon.java

Solução 2: Se os seus beacons NÃO envie um iBeacon anúncio padrão ou não incluir uma constante de calibração :

Você deve embutir uma constante de calibração em seu aplicativo para cada tipo de dispositivo que você pode usar. Tudo o que você realmente precisa da propaganda para estimar a distância é a medição da RSSI . Todo o ponto de incorporação de uma constante de calibração na transmissão é permitir que uma ampla variedade de balizas com potência de saída do transmissor bastante diferente de trabalhar com o mesmo algoritmo de estimativa de distância .

A constante de calibração, conforme definido pela Apple, basicamente diz que o RSSI deve ser se o seu dispositivo é exatamente um metro de distância da baliza . Se o sinal é mais forte ( RSSI menos negativa ), em seguida, o dispositivo é inferior a um metro de distância . Se o sinal é fraco ( RSSI mais negativo ), em seguida, o dispositivo é mais de um metro de distância . Você pode usar uma fórmula para fazer uma estimativa numérica de distância . http://stackoverflow.com/a/20434019/1461050

Se você não está lidando com as propagandas que contêm um " txpower " ou " measuredPower " constante de calibração, então você pode embutir uma tabela de pesquisa em seu aplicativo que armazena as constantes de calibração conhecidos para os vários transmissores . Você primeiro precisa para medir a RSSI média de cada transmissor a um metro de distância. Então você vai precisar de algum tipo de chave para procurar esses constantes de calibração na tabela. (Talvez você pode usar a alguma parte da cadeia da estrutura AD, ou o endereço MAC ?) Então a sua mesa pode ter esta aparência :

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));

Em seguida, após a análise de um anúncio publicitário, você pode olhar -se a constante de calibração em sua onLeScan método como este :

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

O txPower mencionado por davidgyoung é dada pela fórmula :

RSSI = + A -10nlogd

onde d = distância, A = txpower, n = sinal constante de propagação e [ RSSI ] = dBm .

No espaço livre n = 2, mas ela varia com base na geometria local, - por exemplo, uma parede irá reduzir rssi por ~ 3dBm e irá afectar n em conformidade.

Se você quiser a maior precisão possível, ele pode ser útil para determinar experimentalmente esses valores para o seu sistema particular.

Referência: ver http://www.rn.inf.tu-dresden.de/dargie/papers/icwcuca.pdf para uma explicação mais detalhada sobre a derivação e calibração .

3user1423561 @

usar o método getAccuracy () na biblioteca, dá-lhe a distância da baliza

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));
}