Cómo identificar Eddystone URL y uid?

Quiero detectar Eddystone Ul y uid sin utilizar API de proximidad Beacon o API de mensajes cercanos. Deseo utilizar las bibliotecas androides nativas como BluetoothAdapter o BluetoothGatt o BluetoothGap para analizar los marcos eddystone. ¿Es esto factible? si es así cómo y si no es factible entonces lo que podría ser la alternativa?

La siguiente es la forma más sencilla de obtener información sobre Eddystone AFAIK.

// onLeScan() method of BluetoothAdapter.LeScanCallback interface. public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { // Parse the payload of the advertisement packet // as a list of AD structures. List<ADStructure> structures = ADPayloadParser.getInstance().parse(scanRecord); // For each AD structure contained in the advertisement packet. for (ADStructure structure : structures) { // If the AD structure represents Eddystone UID. if (structure instanceof EddystoneUID) { // Eddystone UID EddystoneUID es = (EddystoneUID)structure; Log.d(TAG, "Tx Power = " + es.getTxPower()); Log.d(TAG, "Namespace ID = " + es.getNamespaceIdAsString()); Log.d(TAG, "Instance ID = " + es.getInstanceIdAsString()); Log.d(TAG, "Beacon ID = " + es.getBeaconIdAsString()); // As byte arrays if you want. byte[] namespaceId = es.getNamespaceId(); byte[] instanceId = es.getInstanceId(); byte[] beaconId = es.getBeaconId(); } // If the AD structure represents Eddystone URL. else if (structure instanceof EddystoneURL) { // Eddystone URL EddystoneURL es = (EddystoneURL)structure; Log.d(TAG, "Tx Power = " + es.getTxPower()); Log.d(TAG, "URL = " + es.getURL()); } // If the AD structure represents Eddystone TLM. else if (structure instanceof EddystoneTLM) { // Eddystone TLM EddystoneTLM es = (EddystoneTLM)structure; Log.d(TAG, "TLM Version = " + es.getTLMVersion()); Log.d(TAG, "Battery Voltage = " + es.getBatteryVoltage()); Log.d(TAG, "Beacon Temperature = " + es.getBeaconTemperature()); Log.d(TAG, "Advertisement Count = " + es.getAdvertisementCount()); Log.d(TAG, "Elapsed Time = " + es.getElapsedTime()); } } } 

Usted no tiene que saber detalles acerca de la especificación de Eddystone si utiliza nv-bluetooth .

Gradle

 dependencies { compile 'com.neovisionaries:nv-bluetooth:1.7' } 

JavaDoc

JavaDoc

Memorándum

Temperatura de baliza en Eddystone TLM se expresa en una notación de punto fijo firmada . Los ejemplos de código en Cómo detectar balizas compatibles con Eddystone (Android Beacon Library) no muestran cómo extraer los datos como un número de punto flotante a partir de esta escritura. Por otro lado, EddystoneTLM clase en nv-bluetooth tiene un método como se muestra a continuación, por lo que no tiene que decodificar la notación de punto fijo.

 public float getBeaconTemperature(); 

Del mismo modo, EddystoneURL clase tiene un método para obtener la URL como URL .

 public URL getURL(); 

Por lo tanto, no tiene que hacer un paso como el siguiente que se requiere cuando utilice Android Beacon Library.

 String url = UrlBeaconUrlCompressor.uncompress(beacon.getId1().toByteArray()); 

nv-bluetooth implementa estructuras de datos relacionadas con Eddystone como un árbol de herencia como se muestra a continuación. Este tipo de árbol de herencia adecuado es difícil de encontrar en otras bibliotecas.

 ADStructure | +-- ServiceData | +-- Eddystone | +-- EddystoneUID | +-- EddystoneURL | +-- EddystoneTLM 

Uno de los beneficios del árbol de herencia adecuado es que los métodos se colocan en las posiciones correctas. Me gusta esto:

 ADStructure | // AD Structure Length - 1 | int getLength(); | | // AD Type | int getType(); | | // AD Data | byte[] getData(); | +-- ServiceData | | // Service UUID | | UUID getServiceUUID(); | | | +-- Eddystone | | // Eddystone Frame Type | | FrameType getFrameType(); | | | +-- EddystoneUID | | // Tx Power | | int getTxPower(); | | | | // Namespace ID (byte[]) | | byte[] getNamespaceId(); | | | | // Instance ID (byte[]) | | byte[] getInstanceId(); | | | | // Beacon ID (byte[]) | | byte[] getBeaconId(); | | | | // Namespace ID (String) | | String getNamespaceIdAsString(); | | | | // Instance ID (String) | | String getInstanceIdAsString(); | | | | // Beacon ID (String) | | String getBeaconIdAsString(); | | | +-- EddystoneURL | | // Tx Power | | int getTxPower(); | | | | // URL | | URL getURL(); | | | +-- EddystoneTLM | // TLM Version | int getTLMVersion(); | | // Battery Voltage | int getBatteryVoltage(); | | // Beacon Temperature | float getBeaconTemperature(); | | // Advertisement Count | long getAdvertisementCount(); | | // Elapsed Time | long getElapsedTime(); | +-- ADManufacturerSpecific | | // Company ID | | int getCompanyId(); | | | +-- IBeacon | | // Major Number | | int getMajor(); | | | | (abbrev) | | | +-- Ucode | | // Ucode | | String getUcode(); | | | | (abbrev) 

Todos los datos de Eddystone están contenidos en el paquete de publicidad Bluetooth 4.0 ("Bajo consumo de energía", "BLE"), por lo que no es necesario BluetoothGatt o BluetoothGap . En su lugar, utilice BluetoothLeScanner . En la onScanResult llamada onScanResult , puede acceder a los datos publicitarios mediante:

 // assuming `result` is the ScanResult passed to the `onScanResult` callback byte[] rawData = result .getScanRecord() .getServiceData(ParcelUuid.fromString("0000FEAA-0000-1000-8000-00805F9B34FB")); 

A continuación, tendrá que analizar los bytes de acuerdo con las especificaciones Eddystone:

UID: https://github.com/google/eddystone/tree/master/eddystone-uid
URL: https://github.com/google/eddystone/tree/master/eddystone-url

También hay un proyecto de ejemplo incluido en el repo Eddystone, por lo que probablemente puede comenzar allí, tal vez reutilizar algún código:

https://github.com/google/eddystone/tree/master/tools/eddystone-validator

Puede detectar balizas Eddystone-UID con la devolución de llamada nativa de Android onLeScan . He publicado código de ejemplo que muestra cómo puede hacer esto en la respuesta aquí:

https://stackoverflow.com/a/32799901/1461050

 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] == 0xaa && scanRecord[startByte+1] == 0xfe && scanRecord[startByte+2] == 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 } } } } 

La clave para hacerlo es entender y analizar el diseño de bytes de cada tipo de baliza. Así es como la biblioteca de código abierto Android Beacon analiza múltiples tipos de balizas como Eddystone definiendo expresiones de diseño para cada baliza para facilitar el análisis. Incluso si quieres rodar tu propio código, puedes ver su código fuente y usarlo para entender cómo funciona. He publicado una descripción de cómo este análisis se produce en la respuesta vinculada anteriormente.

  • Exploración de fondo de iBeacon
  • AltBeacon onBeaconServiceConnect no se llama
  • Android Studio - Estimate SDK - No se pudo encontrar la clase
  • Cómo obtener balizas visibles desde el método RegionBootstrap AltBeacon
  • ¿Cómo agregar más de un faro en una sola región?
  • Android Estimote sdk no es capaz de escanear otros beacons que los estimote
  • ¿Cómo obtener respuestas más rápidas con AltBeacon?
  • Variaciones de rango de ibeacon de Radius Networks
  • Servicio de detector de balizas de estimación en segundo plano
  • Android Bluetooth baja energía - iBeacon
  • ¿Por qué isMultipleAdvertisementSupported () devuelve false, cuando getBluetoothLeAdvertiser devuelve un objeto?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.