tecnologia studio low dispositivos detectar buscar ble android bluetooth-lowenergy android-bluetooth

android - studio - modulo bluetooth hc 08



Direcciones privadas vs públicas en Bluetooth de baja energía en Android (5)

Un dispositivo Bluetooth de baja energía se identifica de forma única por su dirección (en la API de Android lo llaman la dirección MAC y la designan como valores hexadecimales separados por dos puntos, por ejemplo, 11: aa: 22: bb: 33: cc).

Pero para identificar de manera única una dirección BLE, debe saber si es una dirección pública o privada. En esencia, son necesarios 49 bits para identificar una dirección, no 48.

Las direcciones aleatorias pueden ser estáticas, aleatorias, privadas no resuelvebles o privadas resuelvebles, y estos tipos están separados por un patrón de bits en los dos bytes más significativos (11, 00 y 10 respectivamente).

Pero no veo en ningún lugar que pueda separar direcciones públicas y aleatorias simplemente mirando los 48 bits en la dirección.

Entonces, ¿cómo funciona esto en la API de Android? ¿Cómo saben a qué dispositivo conectarse cuando no saben si la dirección que ha especificado son públicas o aleatorias?

La API en cuestión es, por ejemplo, la función getRemoteDevice . Dice:

Valid Bluetooth hardware addresses must be upper case, in a format such as "00:11:22:33:AA:BB". The helper checkBluetoothAddress(String) is available to validate a Bluetooth address. A BluetoothDevice will always be returned for a valid hardware address, even if this adapter has never seen that device.

Entonces le das a la función 48 bits de datos y no hay forma de saber si la dirección es pública o privada. Esto significa que el dispositivo no está identificado de forma única.


Como nadie más parece tener una respuesta para ofrecer, comencé a probar por mi cuenta.

Intenté crear una aplicación que crea un dispositivo a partir de una representación de cadena de una dirección e intenté configurar mi dispositivo con la dirección de 48 bits alternando el bit público o privado para ver qué hace la pila de Android.

private final BluetoothGattCallback leGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { Log.i("Fisken", "Gatt connected " + gatt.getDevice().getAddress() + " status " + status); if (status != BluetoothGatt.GATT_SUCCESS) { Log.w("Fisken", "Disconnect and close"); gatt.disconnect(); gatt.close(); } } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { Log.i("Fisken", "Gatt disconnected " + gatt.getDevice().getAddress() + " status " + status); if (status != BluetoothGatt.GATT_SUCCESS) { Log.w("Fisken", "Disconnect and close"); gatt.disconnect(); } gatt.close(); } } }; BluetoothAdapter mBluetoothAdapter = ((BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter(); BluetoothDevice d = mBluetoothAdapter.getRemoteDevice("FF:55:44:33:22:11"); d.connectGatt(this, false, leGattCallback);

Con este código, si comienzo mi periférico BLE con una dirección aleatoria, todo funciona como se espera. Sin embargo, si intento ejecutarlo con la misma dirección con el conjunto de bits público, logcat dice "Gatt connected", pero eso no es cierto. Y nunca puedo desconectar.

Actualización : hice algunas pruebas más para resolver esto. El evento onConnectionStateChange que recibo es solo el intento de conexión que se agota el tiempo de espera. El estado se establece en 133 (si obtengo STATE_CONNECTED) o 257 (si obtengo un STATE_DISCONNECTED) y he visto ambos. En cualquier caso, debería (y ahora hacerlo en el código de ejemplo) cancelar el intento de conexión y cerrar el cliente.

También descubrí que si hago una exploración primero, para que el dispositivo al que estoy tratando de conectarme haya sido visto recientemente y luego haga una conexión basada únicamente en la dirección mac del dispositivo, entonces puedo conectarme a ambos al azar. y direcciones públicas sin ningún problema.

Así que esto parece ser un error y / o una característica faltante en la API de Android. No le permite conectarse a una dirección pública sin haberlo escaneado primero. Sin embargo, funciona para direcciones aleatorias.


Creo que su original ''necesita 49 bits para distinguir entre direcciones públicas y aleatorias'' es correcto. No puedo encontrar nada en la codificación de una dirección pública IEEE que restrinja a la MSB a ser ''10'' que, de ser cierto, resolvería el problema.

Por lo tanto, lo único que se puede usar es la configuración del bit de ''dirección aleatoria'' en los anuncios del periférico o la configuración del bit equivalente en el paquete de inicio de conexión de la central. Si estos bits no se configuran, entonces la dirección que expone dicho punto final es pública.

Agregaré: De la especificación básica Vol. 6 Parte B, sección 1.3 Direcciones de dispositivos: Llamando a MS = más significativo

Static random address: two MB bits of MS byte are 1 1 such that the MS byte is 11xxxxxx & with 0xC0 Non-resolvable private address: two MB bits of MS byte are 0 0 such that the MS byte is 00xxxxxx & with 0x00 Resolvable private address: two MB bits of MS byte are 0 1 such that the MS byte is 01xxxxxx & with 0x40

No hay forma de distinguir una dirección pública de uno de los tipos de direcciones anteriores sin tener también el indicador de tipo de dirección. Por lo tanto, la necesidad del bit ''49'' (la bandera extra). La sola dirección no lo hace!


Es posible adivinar si la dirección es pública o aleatoria, aunque no funcionará en todos los casos.

Como dice anteriormente, en caso de una dirección aleatoria, ambos MSB son 00xx, 01xx o 11xx ... así que si es 10xx, entonces es una dirección pública (de una compañía cuyo OUI comienza con 8,9, A o SEGUNDO)

Además, el número de OUI registrados es muy limitado en comparación con lo que existe, por lo que al buscar el OUI potencial en la base de datos IEEE, un resultado coincidente probablemente signifique una dirección pública.

Recuento de OUI registrado: ~ 20500, 0.12% de 2 ^ 24 bits y 0.48% de 2 ^ 22 bits.

Sin la base de datos IEEE, es posible confiar en el hecho de que el primer LSB de un OUI siempre es 0, y el segundo LSB casi siempre es 0 (en realidad, debería ser siempre 0 ya que estas direcciones se administran universalmente).

Además, se puede utilizar otro análisis estadístico: por ejemplo, el 60% del OUI comienza con 00. Por otro lado, una dirección privada no resoluble, tiene solo una probabilidad del 1.66% para comenzar con el 00 (con generador aleatorio uniforme).


Puede diferenciar entre direcciones públicas y privadas mirando los 2 bits más significativos. Una dirección tiene una longitud de 48 bits, no 49. Consulte la Especificación Core Bluetooth v4.2, Vol. 6, Parte B, Sección 1.3.


Si la dirección publicitaria es pública o privada, se establece en el encabezado del mensaje publicitario. Establecer el tipo de dirección en la capa de aplicación en público significa que la capa de enlace BLE transmitirá la dirección "MAC" real. Al establecer el tipo de dirección en estático / resoluble privado, indica que la capa de enlace BLE mezclará la dirección con una clave de resolución de identidad (IRK).