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