如何识别Eddystone URL和uid?

时间:2015-09-29 06:03:12

标签: android bluetooth-lowenergy android-bluetooth ibeacon-android eddystone

我希望在不使用Proximity Beacon API或Nearby Messages API的情况下检测Eddystone Ul和uid。我希望使用像BluetoothAdapter或BluetoothGatt或BluetoothGap这样的原生android库来解析eddystone帧。这可行吗?如果是这样,如果它不可行那么什么可以替代呢?

3 个答案:

答案 0 :(得分:4)

以下获取有关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());
        }
    }
}

如果您使用 Eddystone specification ,则无需了解nv-bluetooth的详细信息。

摇篮

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

的JavaDoc

JavaDoc

备注

Eddystone TLM中的信标温度以带符号的定点符号表示。 How to detect Eddystone-Compatible Beacons(Android信标库)中的代码示例未显示在撰写本文时如何将数据提取为浮点数。另一方面,nv-bluetooth中的EddystoneTLM类有如下所示的方法,因此您不必解码定点表示法。

public float getBeaconTemperature();

同样,EddystoneURL类有一种方法可以将网址设为URL

public URL getURL();

因此,当您使用Android Beacon Library时,您不必执行以下步骤。

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

nv-bluetooth将与Eddystone相关的数据结构实现为继承树,如下所示。在其他库中很难找到这种正确的继承树。

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

正确的继承树的一个好处是方法放在正确的位置。像这样:

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)

答案 1 :(得分:3)

所有Eddystone数据都包含在蓝牙4.0(&#34;低能耗,&#34;&#34; BLE&#34;)广告包中,因此无需BluetoothGatt或{{1 }}。请改用BluetoothGap。在BluetoothLeScanner回调中,您可以通过以下方式访问广告数据:

onScanResult

然后,您需要根据Eddystone规范解析字节:

// assuming `result` is the ScanResult passed to the `onScanResult` callback byte[] rawData = result .getScanRecord() .getServiceData(ParcelUuid.fromString("0000FEAA-0000-1000-8000-00805F9B34FB")); https://github.com/google/eddystone/tree/master/eddystone-uid
UID: https://github.com/google/eddystone/tree/master/eddystone-url

还有Eddystone回购中包含的示例项目,所以你可以从那里开始,也许重用一些代码:

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

答案 2 :(得分:1)

您可以使用原生Android <?php header("pragma : no-cache"); header("Expires: Thu, 19 Nov 1981 08:52:00 GMT"); header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); header("Content-Description: File Transfer"); header("Content-Type: video/mp4"); header("Content-Location: videos/testvid.mp4"); header("Content-Transfer-Encoding: binary"); header("Content-Length: ".filesize("videos/testvid.mp4")); readfile("videos/testvid.mp4"); ?> 回调检测Eddystone-UID信标。我已经发布了示例代码,显示了如何在答案中执行此操作:

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

onLeScan

这样做的关键是理解和解析每个信标类型的字节布局。这就是开源Android Beacon Library通过为每个信标定义布局表达式以帮助解析来解析多个信标类型(如Eddystone)的方式。即使您想要自己编写代码,也可以查看其源代码并使用它来了解它的工作原理。我已经在上面链接的答案中发布了解析如何发生的描述。