Android 4.3: BLE: Comportamiento de filtrado de startLeScan ()

Estoy trabajando en un dispositivo de sensor BluetoothLE, para el cual necesito formar una transmisión de uno a muchos de datos. Según la especificación, los periféricos pueden tener solamente un solo amo, y debido a las limitaciones del pedacito y de la pila que estoy diseñando encendido, un amo puede tener solamente tres esclavos. Por lo que entiendo, Android no puede convertirse en un esclavo BLE de todos modos, por lo que tener mi dispositivo como un maestro no es una opción.

Tanto la especificación de BT4 como la documentación del fabricante hablan de otro modo de operación, denominado modo de difusión. En el modo de difusión, nunca se realiza una conexión y los datos de la aplicación se transmiten como parte del paquete publicitario. Esto se ajustará exactamente a mis necesidades, ya que muchos teléfonos Android / iOS pueden analizar simultáneamente cada paquete. Un paquete de publicidad se transmite varias veces en ráfagas, por lo que sospecho que la recepción de datos para ser en su mayoría fiable. Si un paquete se pierde aquí y allá, puede ser tolerado.

Donde esto se pone interesante, es que quiero que estos paquetes para llevar a cabo los datos del sensor en vivo, que se actualiza a una tasa de 10-20Hz. De los ejemplos que he encontrado en la web, BLE en este modo se utiliza principalmente para las implementaciones de tipo "iBeacon", donde están transmitiendo datos estáticos. No puedo encontrar ninguna información sobre cómo se filtran los paquetes de publicidad en la pila de Android. Podría ser que devuelvan un resultado por dirección de hardware de Bluetooth, o podría ser la combinación única de dirección y datos. La segunda opción funcionaría para esta aplicación. Si iniciar y detener la exploración restablece el filtro, puedo hacer que algo funcione también.

La documentación de Android no menciona nada sobre cómo funciona el filtrado de dispositivos en el método de análisis. He podido encontrar un poste en la red que intenta solucionar este mismo problema, que tiene una respuesta sin resolver: BLE: Múltiple descubrimiento del mismo periférico durante exploración . En iOS, mi colega me informa que hay un parámetro que se puede pasar a la función de exploración que hace esto posible.

He intentado rastrear el código de regreso de la llamada startLeScan () en la fuente de Android, pero el código es bastante complejo, y el uso de la abstracción ha hecho difícil identificar la implementación del objeto que lo contiene. El más lejano que he conseguido es a un objeto de IBluetoothGatt devuelto del método de la clase de BluetoothManagerService getBluetoothGatt (). Este objeto recibe la solicitud para iniciar el escaneado. Se está instanciando alrededor de la línea 790 de BluetoothManagerService.java en la revisión actual en vivo en github. El objeto se está emitiendo desde el resultado de un mensaje, por lo que sospecho que tal vez el resultado es específico de teléfono / controlador. Es más allá de mi experiencia para poder rastrear más lejos.

Otra pregunta que me gustaría resolver es la rapidez con la que el escaneo se puede encender y apagar. La exploración es una operación intensiva de energía, sin embargo, la transmisión de datos ocurrirá periódicamente en un tiempo bastante preciso, temporizador en tiempo real. Como resultado, sería una gran optimización si el escaneo se puede encender y apagar, de modo que la difusión y la exploración se sincronicen, con el escáner cerrado el otro 90% + del tiempo. Probablemente será necesario probarlo experimentalmente.

Todavía estoy haciendo la investigación de factibilidad para ver si esto es posible para nuestro accesorio para Android. Mi teléfono actual todavía no puede ejecutar la versión 4.3, así que no tengo forma de probar / hackear esto experimentalmente.

Con Android 4.3 y 4.4 hasta ahora, parece ser un lío: Algunos dispositivos de llamada onLeScan (dispositivo BluetoothDevice, int rssi, byte [] scanRecord) varias veces para un dispositivo en una exploración, otros no. No hay forma de configurar el filtrado como en iOS (ver respuesta de Arkadiusz Konior). Así pues, ahora comienzo una lista, porque no puedo preguntar a mis usuarios tal pregunta sobre su dispositivo.

Sin embargo, reiniciar la exploración tampoco es un problema en los dispositivos que no filtran. Por lo tanto, reiniciar la exploración en cada dispositivo ahora.

No filtrar (Continuamente llamando a OnSec ())

  • Samsung Galaxy S4 con 4.2.2 usando Samsung BLE sdk (yo era dueño de ese dispositivo)
  • Nexus 5 con 4.4 (agregado por [vegarwe]. El dispositivo dará continuamente registros de exploración para dispositivos cercanos mientras escanea)
  • Samsung Galaxy S3 con 4.3 (JSS15J.I9300XXUGMK6, estaba probando en ese dispositivo)
  • Samsung Galaxy S4 con 4.3 y 4.4.2 con Android SDK (añadido por arnaud.b , sin compilación)
  • HTC One con 4.4.2 (añadido por arnaud.b , sin número de compilación proporcionado)

Dispositivos de filtración (se aplica al estándar)

  • Nexus 4 con 4.3, 4.4 (yo poseo ese dispositivo)
  • Nexus 7 2013 4G con 4.4.2 (KOT49H, estaba probando en ese dispositivo)
  • Samsung Galaxy S4 mini con 4.2.2 (estaba probando en este dispositivo)
  • Motorola Moto X (añadido por user1603602 , no se proporciona información sobre la versión android)
  • Motorola Moto G con 4.3 (falcon_umts, Mi dispositivo de prueba)
  • Sony Xperia Tablet Z Wi-Fi con Android 4.3 (Build 10.4.B.0.577, Modelo SGP311, mi dispositivo de prueba)
  • OnePlus One con 5.0.1 y 5.1.1 (Cyanogen 12.1)

Comportamiento de filtrado desconocido (ayuda para asociar el dispositivo a un grupo determinado)

  • Nexus 7 2013 (Se ha reportado un comportamiento diferente como aquí, pero he leído más informes de que pertenece al primer grupo).
  • Otros dispositivos SAMSUNG, HTC, Motorola, …,

El texto en las páginas 2535-2536 en la especificación Bluetooth (Core_v4.1.pdf) acerca de los informes publicitarios duplicados es algo poco claro. Sin embargo, el texto de la página 1258 es claro. Especifica un parámetro Filter_Duplicates en el comando HCI_LE_Set_Scan_Enable. En Android versión 4.4 (Kitkat) este parámetro es 0x00 (Duplicar filtrado deshabilitado).

Hay una manera simple de averiguar si cualquier filtrado se hace en el chip Bluetooth de Android versiones 4.4 (Kitkat). Haga que el teléfono sea un teléfono para programador, entre en las opciones de desarrollador y marque "Habilitar registro de Bluetooth HCI snoop". A continuación, apague y encienda Bluetooth una vez para hacer que los ajustes muerden. A partir de ahora, todos los paquetes HCI entre el procesador de la aplicación y el chip Bluetooth serán almacenados en el teléfono en un archivo que es extraído por adb pull storage / emulated / legacy / btsnoop_hci.log. Esto no es un archivo de texto y necesita un programa de http://www.fte.com/products/default.aspx o wireshark para ver btsnoop_hci.log. Para wireshark necesitas una versión bastante reciente, porque las versiones anteriores no soportan BLE. Mi experiencia es que nunca hay filtrado en el chip Bluetooth, es decir, el evento HCI "LE Advertising Report Event" se envía para cada ADV_IND y ADV_NONCONN_IND que recibe el chip Bluetooth. Esto se aplica a los teléfonos con chips Bluetooth Qualcomm / Atheros WCN 3680 y Broadcom BCM 4339.

Corrección: la ruta de acceso a btsnoop_hci.log puede ser diferente dependiendo del fabricante del teléfono. Usted puede encontrar el camino correcto por el gato de la cáscara del adb etc / bluetooth / bt_stack.conf | Grep BtSnoopFileName

Estoy desarrollando la aplicación para Android 4.3 (Nexus 4 y 7) utilizando BLE y de mis observaciones el escaneado devuelve el mismo dispositivo varias veces si no se ha enviado ningún SCAN REQUEST al periférico.

El dispositivo puede anunciarse de 2 maneras: pasivo y activo. En modo pasivo, el dispositivo periférico sólo anuncia todos sus datos y no escucha después de enviar paquetes periódicos. Es sólo enviar, dormir, enviar, dormir … En el modo activo, el sensor también anuncia, pero el mensaje es lo más corto posible. Después de enviarlo, cambia a escuchar durante un tiempo muy corto. Cuando se escanea detecta el mensaje corto, envía inmediatamente el comando SCAN REQUEST al periférico y obtiene respuesta con más detalles. Por lo que puedo ver, Android no envía SCAN REQUEST varias veces durante una exploración.

Supongamos que tenemos 2 dispositivos en el rango. Uno de ellos es el sensor nRF Temp de Nordic (publicidad pasiva) y otro dispositivo conectable. He recibido la siguiente respuesta de análisis:

11-10 21:32:54.281: D/BluetoothAdapter(13468): startLeScan(): null 11-10 21:32:54.281: D/BluetoothAdapter(13468): onClientRegistered() - status=0 clientIf=4 11-10 21:32:54.321: D/BluetoothAdapter(13468): onScanResult() - Device=CD:61:1A:A8:BC:BE RSSI=-94 11-10 21:32:55.122: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-61 11-10 21:32:56.414: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-62 11-10 21:32:57.715: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-61 11-10 21:32:59.016: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63 11-10 21:33:01.609: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63 11-10 21:33:02.901: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63 11-10 21:33:04.212: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-62 11-10 21:33:04.282: D/BluetoothAdapter(13468): stopLeScan() 

Como se puede ver el dispositivo conectable apareció sólo una vez, mientras que el otro 7 veces.

Otra pregunta que me gustaría resolver es la rapidez con la que el escaneo se puede encender y apagar. La exploración es una operación intensiva de energía, sin embargo, la transmisión de datos ocurrirá periódicamente en un tiempo bastante preciso, temporizador en tiempo real. Como resultado, sería una gran optimización si el escaneo se puede encender y apagar, de modo que la difusión y la exploración se sincronicen, con el escáner cerrado el otro 90% + del tiempo. Probablemente será necesario probarlo experimentalmente.

La frecuencia de escaneado depende del dispositivo. Además la publicidad se hace generalmente en 3 canales: 37, 38 y 39 para aumentar la probabilidad de ser encontrado. Sin embargo, esto podría ser bastante buena idea para obtener paquetes publicitarios de dispositivos "activos" varias veces.

La especificación bluetooth real dice:

No se requiere que los informes de publicidad duplicados se envíen al host. Un informe de publicidad duplicado es un informe de publicidad para la misma dirección de dispositivo mientras que la capa de enlace permanece en el estado de escaneado. Los datos publicitarios pueden cambiar; Los datos de publicidad o los datos de respuesta de escaneo no se consideran significativos al determinar los informes publicitarios duplicados.

Según la especificación esto se aplica durante un período de exploración, lo que sugiere que la forma correcta de evitar esto es detener y reiniciar el escaneado cada vez que reciba un anuncio.

Basado en mi experiencia con BLE, parece que enviar datos variables en los anuncios no es una buena idea. Casi todo asume que los datos de anuncios no cambian. Si desea enviar datos variables (por ejemplo, lecturas de termómetro), entonces es mucho mejor conectarse realmente al dispositivo y hacerlo a través de una característica. Es más confiable y usa mucho menos energía. La desventaja es que sólo se puede conectar a 8 dispositivos a la vez.

Los anuncios están destinados a detectar la presencia de dispositivos e identificarlos.

En iOS, este indicador se denomina CBCentralManagerScanOptionAllowDuplicatesKey . Pasarla a la función de análisis hace que la notificación de cada paquete de publicidad. No pude encontrar una bandera similar en Android.

  • Android 4.3 Bluetooth Baja energía inestable
  • Análisis pasivo de Android BLE
  • UUID y MACAddress para Bluetooth BLE
  • Android BLE ACTION_ACL_CONNECTED no se llama para dispositivos emparejados
  • Problema de BLE de Android: transporte no admitido para la conexión de fondo
  • Análisis BLE de Android en el servicio de fondo
  • Android: Envío de datos> 20 bytes by BLE
  • Android Bluetooth Scan para dispositivos clásicos y BTLE
  • Navegación en interiores y seguimiento de personas usando BLE
  • APIs en android para Bluetooth Servicio de alerta inmediata en Find me profile
  • Init conexión sin sincronización utilizando Bluetooth Low Energy en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.