问题描述
我正在尝试为 BLE Eddystone UID 数据包编写解析器,但不知道具体该怎么做。 我正在使用 Beacon Simulator App 广播 Eddystone UID 数据包,当我使用与扫描仪相同的应用程序在不同的手机上进行测试时,我可以看到第一台设备广播的 Eddystone UID 数据包。
我想编写一个示例应用程序来扫描 Eddystone UID 数据包。
我知道我必须使用 BluetoothLeScanner
,并且在 onScanResult
的 ScanCallback
中,我可以获得与 BLE(低功耗蓝牙)兼容的所有蓝牙设备。
但问题是我能够从 ScanResult
中提取设备 mac、设备名称,并且可以验证我是否能够听到我的蓝牙耳机和扬声器的声音,但我不确定我将如何获得 {{1 }} 和 namespace
的 Eddystone UID,我无法在 instance
中看到任何此类变量,这对我有帮助。
任何人都可以向我指出有关如何执行此操作的任何片段或任何代码。我不想使用任何第三方库进行扫描,在 Kotlin 或 Java 中简单明了。 Kotlin 是首选,但 java 也不错,我知道这两种语言。
解决方法
Eddystone UID:具有 10 字节命名空间组件和 6 字节实例组件的唯一静态 ID。
在 onScanResult
中,您可以提取如下所示的 Eddystone uid 数据包
override fun onScanResult(callbackType: Int,result: ScanResult) {
val scanRecord = result.scanRecord
if (scanRecord != null) {
val serviceUuids = scanRecord.serviceUuids
if (serviceUuids != null && serviceUuids.size > 0 && serviceUuids.contains(
eddystoneServiceId
)
) {
val serviceData = scanRecord.getServiceData(eddystoneServiceId)
if (serviceData != null && serviceData.size > 18) {
val eddystoneUUID =
Utils.toHexString(Arrays.copyOfRange(serviceData,2,18))
val namespace = String(eddystoneUUID.toCharArray().sliceArray(0..19))
val instance = String(
eddystoneUUID.toCharArray()
.sliceArray(20 until eddystoneUUID.toCharArray().size)
)
Log.e("DINKAR","Namespace:$namespace Instance:$instance")
}
}
}
}
scanRecord:广告和扫描响应的组合
serviceUuids:广告中用于识别蓝牙 GATT 服务的服务 UUID 列表。
eddystoneServiceId : Eddystone UID 的服务 UUID,即“0000FEAA-0000–1000–8000–00805F9B34FB”
serviceData:与 serviceUuid 关联的服务数据字节数组,在我们的例子中是 eddystoneServiceId
eddystoneUID 数据包信息在 serviceData 中从索引 2 到 18,我们需要使用实用方法将此字节数组转换为十六进制字符串。
namespace 是 10 个字节,从 eddystoneUID 的 20 个字符开始
instanceId 为 6 个字节,即 eddystoneUID 的其余 12 个字符
向您展示如何将字节数组转换为十六进制字符串的示例
private val HEX = "0123456789ABCDEF".toCharArray()
fun toHexString(bytes: ByteArray): String {
if (bytes.isEmpty()) {
return ""
}
val hexChars = CharArray(bytes.size * 2)
for (j in bytes.indices) {
val v = (bytes[j].toInt() and 0xFF)
hexChars[j * 2] = HEX[v ushr 4]
hexChars[j * 2 + 1] = HEX[v and 0x0F]
}
return String(hexChars)
}
我写了一篇关于解析 Eddystone UID 和 iBeacon 的博客,你可以参考here
此外,您可以参考完整的工作示例应用程序来扫描 Eddystone UID、iBeacon 和普通蓝牙外围设备 here