Programáticamente, ¿Cómo identificar si un faro pertenece a Eddystone o iBeacon?

He creado una aplicación androide para escanear BLE usando Bluetooth LEscanner. Ahora que necesito mi aplicación para identificar si un faro pertenece a iBeacon o Eddystone. Hasta ahora, tengo éxito en la determinación de UUID, MajorId, MinorId de ibeacon al analizar el marco AD.

Es relativamente fácil leer los bytes de los anuncios si conoce los desplazamientos de bytes de todos los campos. Dos fragmentos de código a continuación muestran cómo se pueden analizar estos. El primero muestra cómo puede hacer esto en su propia onLeScan llamada onLeScan usando la Biblioteca de Android Beacon , y el segundo muestra cómo puede rodar su propio desde cero.

Para explicar cómo funcionan los diseños, mire el código de abajo. Utiliza la clase BeaconParser Beacon Libray de BeaconParser que maneja todo el análisis para un diseño configurable. (Incluso si quieres rodar el tuyo como se muestra en el segundo fragmento de código, vale la pena mirar las expresiones de diseño para que sepas cómo funcionan.Las expresiones siguientes muestran los detalles de AltBeacon que es muy similar a iBeacon. Porque no existen restricciones de propiedad intelectual para discutir su implementación, tanto AltBeacon como Eddystone son estándares de código abierto.)

La primera expresión de disposición muestra que AltBeacon (de nuevo muy similar a iBeacon) tiene tres identificadores (expresiones "i"). El primero (conocido como UUID en iBeacon) es de 16 bytes que va desde el desplazamiento de bytes 4-19. El segundo (conocido como mayor en iBeacon) es de 2 bytes que va desde el desplazamiento de bytes 20-21. El tercero (conocido como menor en iBeacon) es de 2 bytes que va desde el desplazamiento de bytes 22-23.

La segunda expresión de disposición muestra que Eddystone-UID es un anuncio de servicio que tiene un UUID de servicio de 16 bits de 0xfeaa seguido de un código de byte coincidente de 0x00. Tiene dos identificadores, el primero conocido como "identificador de espacio de nombres" de los desplazamientos de bytes 4-13. El segundo identificador se conoce como el "identificador de instancia" de los desplazamientos de bytes 14-19.

  public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { ArrayList<BeaconParser> beaconParsers = new ArrayList<BeaconParser>(); final String ALTBEACON_LAYOUT = "m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"; final String EDDYSTONE_UID_LAYOUT = "s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19"; beaconParsers.add(new BeaconParser().setBeaconLayout(EDDYSTONE_UID_LAYOUT)); beaconParsers.add(new BeaconParser().setBeaconLayout(ALTBEACON_LAYOUT)); Beacon beacon = null; for (BeaconParser parser : beaconParsers) { beacon = parser.fromScanData(scanRecord, rssi, device); if (beacon != null) { if (beacon.getServiceUuid() == 0xfeaa) { // This is Eddystone, which uses a service Uuid of 0xfeaa Identifier eddystoneNamespaceId = beacon.getId1(); Identifier eddystoneInstanceId = beacon.getId2(); } else { // This is another type of beacon like AltBeacon or iBeacon Identifier uuid = beacon.getId1(); Identifier major = beacon.getId2(); Identifier minor = beacon.getId3(); } } } 

La biblioteca de código abierto Android Beacon maneja todos los detalles sobre las PDU de longitud variable que pueden alterar ligeramente los desplazamientos de bytes dentro de la respuesta de análisis. Puede ver el código fuente de cómo funciona su BeaconParser aquí.

Si quieres rodar tu propio completamente desde cero, la manera más fácil es simplemente hacer un bucle a través de los bytes que buscan el patrón que quieres encontrar, luego analizar los bytes de interés basados ​​en los desplazamientos. (La Biblioteca Beacon de Android utiliza un método más robusto y sofisticado de analizar realmente PDU individuales). Pero la técnica de bucle sigue funcionando.

  public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { for (int startByte = 0; startByte < scanRecord.length; startByte++) { if (scanRecord.length-startByte > 19) { // need at least 19 bytes for Eddystone-UID // Check that this has the right pattern needed for this to be Eddystone-UID if (scanRecord[startByte+0] == (byte)0xaa && scanRecord[startByte+1] == (byte)0xfe && scanRecord[startByte+2] == (byte)0x00) { // This is an Eddystone-UID beacon. byte[] namespaceIdentifierBytes = Arrays.copyOfRange(scanRecord, startByte+4, startByte+13); byte[] instanceIdentifierBytes = Arrays.copyOfRange(scanRecord, startByte+14, startByte+19); // TODO: do something with the above identifiers here } } if (scanRecord.length-startByte > 24) { // need at least 24 bytes for AltBeacon // Check that this has the right pattern needed for this to be AltBeacon // iBeacon has a slightly different layout. Do a Google search to find it. if (scanRecord[startByte+2] == (byte)0xbe && scanRecord[startByte+3] == (byte)0xac) { // This is an AltBeacon byte[] uuidBytes = Arrays.copyOfRange(scanRecord, startByte+4, startByte+19); byte[] majorBytes = Arrays.copyOfRange(scanRecord, startByte+20, startByte+21); byte[] minorBytes = Arrays.copyOfRange(scanRecord, startByte+22, startByte+23); // TODO: do something with the above identifiers here } } } } 

Una vez más, el código anterior muestra cómo analizar los AltBeacons de código abierto (por razones de propiedad intelectual). Para analizar iBeacons, necesitará realizar una búsqueda en Google para su BeaconLayout y realizar pequeños ajustes en el código anterior.

Las balizas pueden anunciar iBeacon y Eddystone . De hecho, un proyecto en el que estoy involucrado está utilizando tales faros.

Es fácil extraer iBeacon y Eddystone de paquetes si usa la biblioteca nv-bluetooth . Me gusta esto:

 // onLeScan() method of BluetoothAdapter.LeScanCallback interface. public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { // Parse the payload of the advertisement packet. List<ADStructure> structures = ADPayloadParser.getInstance().parse(scanRecord); // For each AD structure contained in the advertising packet. for (ADStructure structure : structures) { // If the ADStructure instance can be cast to IBeacon. if (structure instanceof IBeacon) { // An iBeacon was found. IBeacon iBeacon = (IBeacon)structure; ...... } // If the ADStructure instance can be cast to Eddystone. else if (structure instanceof Eddystone) { if (structure instanceof EddystoneUID) { // Eddystone UID EddystoneUID es = (EddystoneUID)structure; ...... } else if (structure instanceof EddystoneURL) { // Eddystone URL EddystoneURL es = (EddystoneURL)structure; ...... } else if (structure instanceof EddystoneTLM) { // Eddystone TLM EddystoneTLM es = (EddystoneTLM)structure; ...... } } ...... } ...... } 

Tenga en cuenta que android.bluetooth.le.ScanRecord es una de las peores API en Android, por lo que es mejor analizar paquetes manualmente que utilizar ScanRecord .

Por favor, lea la documentación sobre ScanRecord https://developer.android.com/reference/android/bluetooth/le/ScanRecord.html . El método getManufacturerSpecificData() puede ser algo que está buscando.

  • Estimar la detección de regiones de beacons de un servicio en segundo plano
  • Podemos usar iBeacon para transferir datos a través de bluetooth en iOS - android?
  • ¿Cómo encontrar los eventos de entrada y salida?
  • ¿Android Beacon Library realmente admite la exploración en segundo plano?
  • UUID y MACAddress para Bluetooth BLE
  • ¿Cómo detectar Region Enter / Exit para múltiples balizas usando AltBeacon android-beacon-library?
  • ¿Cómo detectar múltiples balizas usando la biblioteca de Altbeacon android?
  • ¿Puede un dispositivo Android actuar como iBeacon?
  • No se muestran todas las balizas en Android mediante la biblioteca de altBeacon
  • ¿Cómo mejorar la medición de la distancia Bluetooth mediante RSSI?
  • AltBeacon onBeaconServiceConnect no se llama
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.