Android 如何通过scanRecord识别涡流管

Android 如何通过scanRecord识别涡流管,android,bluetooth,gatt,Android,Bluetooth,Gatt,我正在开发一个Android应用程序,它正在扫描可移动设备。每次我找到设备时,我都会收到: byte[]扫描记录,蓝牙设备,int-rssifrom BluetoothAdapter.startedscan() 然后,我将字节数组转换为ScanRecord对象: ScanRecord.parseFromBytes() 现在,我从Eddystone(从toString()方法)中获得了以下信息 有人能告诉我,如何用这些信息将设备识别为Eddystone吗?也许是服务UUID?我并不总是知道设备的名

我正在开发一个Android应用程序,它正在扫描可移动设备。每次我找到设备时,我都会收到:
byte[]扫描记录,蓝牙设备,int-rssi
from
BluetoothAdapter.startedscan()

然后,我将字节数组转换为ScanRecord对象:
ScanRecord.parseFromBytes()

现在,我从Eddystone(从
toString()
方法)中获得了以下信息


有人能告诉我,如何用这些信息将设备识别为Eddystone吗?也许是服务UUID?我并不总是知道设备的名称或地址。

android.bluetooth.le.ScanRecord
是android中最糟糕的API之一

如果您已经有
扫描记录
(字节数组),我建议提取Eddystone数据。下面的代码片段显示了nv bluetooth的用法

//解析广告包的有效负载。
列表结构=
ADPayloadParser.getInstance().parse(scanRecord);
//对于有效负载中包含的每个AD结构。
for(ADStructure结构:结构)
{
if(EddystoneUID的结构实例)
{
//埃迪斯通液体
EddystoneUID es=(EddystoneUID)结构;
//(1)0米处的校准发射功率。
int power=es.getTxPower();
//(2)10字节名称空间ID
字节[]namespaceId=es.getNamespaceId();
字符串namespaceIdAsString=es.getNamespaceIdAsString();
//(3)6字节实例ID
字节[]instanceId=es.getInstanceId();
字符串instanceIdAsString=es.getInstanceIdAsString();
//(4)16字节信标ID
字节[]beaconId=es.getBeaconId();
字符串beaconIdAsString=es.getBeaconIdAsString();
}
else if(EddystoneURL的结构实例)
{
//Eddystone URL
EddystoneURL es=(EddystoneURL)结构;
//(1)0米处的校准发射功率。
int power=es.getTxPower();
//(2)网址
URL=es.getURL();
}
else if(Eddysonelm的结构实例)
{
//埃迪斯通TLM
Eddysonelm es=(Eddysonelm)结构;
//(1)TLM版本
int version=es.getTLMVersion();
//(2)蓄电池电压
int电压=es.getBatteryVoltage();
//(3)信标温度
浮动温度=es.getBeaconTemperature();
//(4)开机或重新启动后的播发计数。
long count=es.getAdvertisementCount();
//(5)自通电或重新启动以来经过的时间(毫秒)。
长时间运行=es.getElapsedTime();
}
else if(IBeacon的结构实例)
{
//伊贝肯
IBeacon IBeacon=(IBeacon)结构;
//(1)接近UUID
UUID UUID=iBeacon.getUUID();
//(2)主要数字
int major=iBeacon.getMajor();
//(3)未成年人
int minor=iBeacon.getMinor();
//(4)发射功率
int power=iBeacon.getPower();
}
}
上面的代码意味着扫描记录应该被解析为广告结构列表。但是,
android.bluetooth.le.ScanRecord
parseFromBytes
没有以正确的方式解析扫描记录

ScanRecord
有以下方法(以及其他一些方法):

  • getAdvertiseFlags()
  • getDeviceName()
  • getManufacturersSpecificATA()
  • getServiceData()
  • getTxPowerLevel()
  • 这些方法对应于一些AD结构。此API设计与下面显示的
    AnimalRecord
    类的结构相同

    公共类动物记录
    {
    公共Cat getCat(){…}
    公共狗getDog(){…}
    公共鹰getEagle(){…}
    ...
    }
    
    标志、本地名称、制造商特定数据、服务数据和Tx功率级别也应解析为AD结构,如下所示

    ADStructure
      |
      +-- ServiceData
            |
            +-- Eddystone
                  |
                  +-- EddystoneUID
                  +-- EddystoneURL
                  +-- EddystoneTLM
    
    //解析广告包的有效负载。
    列表结构=
    ADPayloadParser.getInstance().parse(scanRecord);
    //对于有效负载中包含的每个AD结构。
    for(ADStructure结构:结构)
    {
    if(结构实例f标志)
    {
    //旗帜
    Flags Flags=(Flags)结构;
    }
    else if(LocalName的结构实例)
    {
    //本地名称
    LocalName=(LocalName)结构;
    }
    else if(AdManufacturer特定的结构实例)
    {
    //制造商特定数据
    //请注意,iBeacon是一种特定于制造商的数据
    AdManufacturersSpecific ms=(AdManufacturersSpecific)结构;
    }
    else if(ServiceData的结构实例)
    {
    //服务数据
    //请注意,Eddystone是一种服务数据。
    ServiceData sd=(ServiceData)结构;
    }
    else if(TxPowerLevel的结构实例)
    {
    //TxPowerLevel
    TxPowerLevel level=(TxPowerLevel)结构;
    }
    }
    
    正如上面代码中所述,Eddystone是一种服务数据。因此,Eddystone UID、Eddystone URL和Eddystone TLM应该具有如下所示的继承树

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

    我希望那些非常了解BLE规范并具有良好设计技能的人能够从头开始重写Android的BLE API。

    对于那些想了解其实际工作原理的人:

    mServiceData={
      0000feaa-0000-1000-8000-00805f9b34fb=[
        16, -36, 2, 107, 110, 116, 107, 46, 105, 111, 47, 101, 100, 100, 121, 115, 116, 111, 110, 101
      ], 
      0000d00d-0000-1000-8000-00805f9b34fb=[
        67, 77, 103, 52, 50, 57, 100
      ]
    }
    
    第一个服务数据包可通过“0000feaa-0000-1000-8000-00805f9b34fb”的前32位识别为EddyStone数据。转换时,0000feAA是可在中找到的16位EddyStone服务UUID

    服务始终发出“????????-0000-1000-8000-00805f9b34fb”,此UUID的前32位由服务及其别名替换。在本例中,“feaa”是指EddyStone服务数据(由谷歌创建/指定)

    因此,由于识别了密钥,我们现在知道该值是一个EddyStone数据视图。这些值需要根据需要进行映射/解释
    16-bit UUID for Members => 0xFEAA => Google
    
    FrameType = 16; => 0x10 => EddyStone URL
    
    TX Power = -36; => -36
    
    107 => k
    110 => n
    116 => t
    107 => k
     46 => .
    105 => i
    111 => o
     47 => /
    101 => e
    100 => d
    100 => d
    121 => y
    115 => s
    116 => t
    111 => o
    110 => n
    101 => e
    
    So the URL is: 'kntk.io/eddystone'