簡體   English   中英

在沒有使用 nRF Connect 的解決方法的情況下,無法使用自定義應用程序連接到 BLE 設備

[英]Unable to Connect to BLE Device using Custom App without Workaround using nRF Connect

問題總結及背景

作為大學項目的一部分,我們需要使用自定義應用程序連接到藍牙 LE 模塊 (BL654) 以更新特性。

問題是我無法在沒有先做解決方法的情況下連接到我們的模塊。 我能夠毫無問題地搜索設備,並且我們的模塊顯示在搜索中。 我希望該應用程序不必依賴另一個應用程序才能正常工作。

在手機(Pixel 3XL / Pixel 3 / LG G5)的干凈啟動和干凈的操作系統安裝中,我無法連接到我們的模塊。 但是,我可以連接到其他 BLE 設備,例如 Raspberry Pi 和 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。

關於這個錯誤和可能的解決方案,我已經研究了近一個月,但無法解決。 任何指導將不勝感激。

這是連接嘗試失敗的Logcat 這是使用解決方法后成功連接嘗試的Logcat

下面我將展示相關代碼的片段。 如果需要更多代碼,我很樂意分享。

代碼片段

我在 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) {

        }
    }


感謝您提供的任何幫助:)

啊,可怕的 GATT 133 錯誤。 這通常表明 Android 的 BLE 堆棧存在問題,並且重置藍牙 - 以及舊設備上的 WiFi - 通常會解決。

您的解決方法有效,因為 Android 允許在一個應用程序中連接的藍牙設備在其他應用程序之間共享。 看起來像一個可怕的安全漏洞,但這是預期的行為。

但是,從您的經驗來看,外圍設備完全有可能具有意外的配置。 也許試試RxCentralBle - Uber 的藍牙 LE 集成庫 - 示例應用程序,看看它是否適用於連接到您的設備。 示例應用程序和庫是開源的,因此您可以根據自己的需要進行調整。

全面披露 - 我是 RxCentralBle 的作者和維護者。

嘗試將報告延遲設置為 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
}

我在我的一個應用程序中遇到了這個問題,這似乎是解決方法。

如果向用戶顯示一個列表,這似乎會使列表更新太快,無法通過單擊 go,因此如果出現問題,您可能希望添加自己的延遲更新而不使用setReportDelay

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM