如果没有使用nRF Connect的解决方案,无法使用自定义应用程序连接到BLE设备



问题摘要和背景

作为大学项目的一部分,我们需要连接到带有自定义应用程序的蓝牙LE模块(BL654(来更新特性

问题是,如果不先解决问题,我无法连接到我们的模块。我可以搜索没有问题的设备,我们的模块显示在搜索中。我希望这个应用程序不必依赖另一个应用程序才能正常工作。

在干净的启动和干净的操作系统安装手机(Pixel 3XL/Pixel 3/LG G5(时,我无法连接到我们的模块。然而,我可以连接到其他BLE设备,如树莓派和HTV Vive基站。

我在Android Studio Logcat中收到的错误是:

D/BluetoothGatt: onClientConnectionState() - status=133 clientIf=7 device=C2:A1:E0:B3:69:54

然后使用nRF Connect连接到不同的设备后,我就可以连接到nRF Connect中的模块,然后连接到我的应用程序中的模块。Nordic生产在板上运行的固件和nRF Connect。这让我相信两人之间正在发生一些特别的事情?

我正在使用标准的Android库进行连接,并尝试使用RxAndroidBle

我已经研究了将近一个月关于这个错误和可能的解决方案,但无法解决。任何指导都将不胜感激

这是一个失败连接尝试的日志。以下是使用解决方法后成功连接尝试的日志

下面我将展示相关代码的片段。如果需要更多的代码,我很乐意与大家分享

代码段

我在Kotlin Class文件和MainActivity.kt之间进行了代码分割,据我所知,我正在这两个文件之间传递所有正确的参数。我是Kotlin的初学者,所以试着对我放松;(

查找蓝牙设备(mBluetoothLEAdapter.kt内部(:

fun findBluetoothDevices(mBluetoothAdapter: BluetoothAdapter?){
// Get and instance of the Bluetooth Low Energy Scanner
scanner = mBluetoothAdapter?.bluetoothLeScanner
// Create search settings object
val mSettings = ScanSettings.Builder().
setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).
setReportDelay(reportDelay).
build()
// Create a scanning filter
val mFilter = ScanFilter.Builder().setDeviceName("AEsir ADC Test").build()
val scannerFilter = arrayListOf<ScanFilter>()
scannerFilter.add(mFilter)
// Stop previous scan if there was one
stopScanningBluetoothDevices()
//Start new scanner
tools.showToast("Scanning...")
scanner?.startScan(null, mSettings, mCallback)
}


扫描回调(mBluetoothLEAdapter.kt内部(:

inner class MCallBack: ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult?) {
super.onScanResult(callbackType, result)
stopScanningBluetoothDevices()
tools.showToast("Single Result Found!")
}
override fun onScanFailed(errorCode: Int) {
super.onScanFailed(errorCode)
stopScanningBluetoothDevices()
tools.showToast("Error on Scan!")
tools.showToast(errorCode.toString())
}
override fun onBatchScanResults(results: MutableList<ScanResult>?) {
super.onBatchScanResults(results)
stopScanningBluetoothDevices()
tools.showToast("Batch Results Found!")
scanResults = results
val mAdapter = DeviceListAdapter(activity, scanResults)
val deviceList = activity.findViewById<ListView>(R.id.device_list)
deviceList.adapter = mAdapter
}
}


连接到设备(内部MainActivity.kt(:

// Runs when an item in the Device List is pressed.
// This initiates a GATT connection to the selected device.
override fun onListPressed(): AdapterView.OnItemClickListener? {
return AdapterView.OnItemClickListener { parent, _, position, _ ->
if (bluetoothGatt != null) {
bluetoothGatt?.disconnect()
bluetoothGatt?.close()
}
val clickedItem = parent.getItemAtPosition(position) as ScanResult
//val device = clickedItem.device
val address = clickedItem.device.address
tools.showToast("Connecting to: $address")
// CONNECTION NOT WORKING. HAVE TO USE nRF Connect to make it work
bluetoothGatt = clickedItem.device.connectGatt(applicationContext, false, mGattCallback, BluetoothDevice.TRANSPORT_LE)
}
}


GattCallback(内部MainActivity.kt(:

inner class GattCallback : BluetoothGattCallback() {
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
super.onConnectionStateChange(gatt, status, newState)
//If we connected to the GATT server find services on device
if (status == BluetoothGatt.GATT_SUCCESS) {
gatt.discoverServices()
}
else if (status == BluetoothGatt.STATE_CONNECTING) {
tools.showToast("Connecting I am")
}
else if (status == BluetoothGatt.STATE_DISCONNECTED) {
bluetoothGatt?.close()
bluetoothGatt = null
tools.showToast("I got here and closed the connection")
}
}
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
super.onServicesDiscovered(gatt, status)
bluetoothServices = gatt?.services
}
override fun onCharacteristicChanged(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic) {
//"Notification"
}
override fun onCharacteristicWrite(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
super.onCharacteristicWrite(gatt, characteristic, status)
//Confirm that the characteristic was actually changed
tools.showToast("Characteristic was written!")
}
override fun onCharacteristicRead(gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int) {
}
override fun onDescriptorRead(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
}
}


感谢您提供的任何帮助:(

尝试将报告延迟设置为0。

你的设置现在应该像这个

val mSettings = ScanSettings.Builder().
setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).
setReportDelay(0).
build()

您还需要开始使用单个结果回调,而不是onBatchScanResults,这将需要将结果列表存储在其他地方。

override fun onScanResult(callbackType: Int, result: ScanResult?) {
//add to the list
//adapter.notifyDataSetChanged() if needed
}

我的一个应用程序出现了这个问题,似乎已经解决了。

如果向用户显示列表,这似乎会使列表更新过快,无法点击,因此如果出现问题,您可能希望添加自己的延迟更新,而不使用setReportDelay

啊,可怕的GATT133错误。这通常表明安卓的BLE堆栈有问题,重置蓝牙和旧设备上的WiFi通常会解决问题。

你的解决方法之所以有效,是因为Android允许在一个应用程序中连接的蓝牙设备在其他应用程序中共享。看起来是一个可怕的安全漏洞,但这是意料之中的行为。

然而,从你的经验来看,外设完全有可能有一个意想不到的配置。也许可以试试RxCentralBle——优步的蓝牙LE集成库——示例应用程序,看看它是否适用于连接到你的设备。示例应用程序和库是开源的,因此您可以根据自己的意愿进行调整。

全面披露-我是RxCentralBle的作者和维护者。

最新更新