Android 应用程序中未从蓝牙温度计接收温度数据

问题描述 投票:0回答:1

我正在开发一个与低功耗蓝牙 (BLE) 温度计设备交互的 Android 应用程序。我的目标是从温度计读取温度数据并将其显示在我的应用程序中。然而,尽管正确设置了 BLE 通信,我在接收预期温度数据时仍面临问题。

这是我的测试项目

这是我的主要活动

package com.example.bluetoothdevice

import android.Manifest
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothGattDescriptor
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import java.util.UUID


class MainActivity: AppCompatActivity() {

    lateinit var bluetoothDevice : BluetoothDevice
    lateinit var gatt: BluetoothGatt

    var gattCallback: BluetoothGattCallback = object : BluetoothGattCallback() {

        override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
            super.onConnectionStateChange(gatt, status, newState)

            if(newState == BluetoothGatt.STATE_CONNECTED){
                Log.i("callback","Device connected")

                gatt.discoverServices()
            }
        }

        override fun onDescriptorWrite(
            gatt: BluetoothGatt?,
            descriptor: BluetoothGattDescriptor?,
            status: Int
        ) {
            super.onDescriptorWrite(gatt, descriptor, status)
            if(status == BluetoothGatt.GATT_SUCCESS){
                Log.i("callback","write descriptor done ")
                gatt?.readCharacteristic(descriptor?.characteristic)

            }

        }



        override fun onCharacteristicChanged(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            value: ByteArray
        ) {

            Log.i("callback","indication value "+value.toString())
        }

        @RequiresApi(Build.VERSION_CODES.TIRAMISU)
        override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {

            super.onServicesDiscovered(gatt, status)

            Log.i("callback","services discovered "+gatt.services.size)

            val bluetoothGattService = gatt?.getService(UUID.fromString("00001809-0000-1000-8000-00805f9b34fb"))

            if(bluetoothGattService != null){

                Log.i("callback","temperature service found "+bluetoothGattService.toString())

                var mReadCharacteristic: BluetoothGattCharacteristic =
                    bluetoothGattService.getCharacteristic(
                        UUID.fromString("00002a1c-0000-1000-8000-00805f9b34fb")
                    )



                if (mReadCharacteristic != null) {
                    Log.i(
                        "Callback",
                        "temperature characteristic found "
                    )


                    gatt?.setCharacteristicNotification(mReadCharacteristic, true)

                    val descriptor = mReadCharacteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"))

                    descriptor.value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE

                    gatt?.writeDescriptor(descriptor)
                    

                }
            }
        }

        override fun onCharacteristicRead(
            gatt: BluetoothGatt,
            characteristic: BluetoothGattCharacteristic,
            status: Int
        ) {
            super.onCharacteristicRead(gatt, characteristic, status)

            Log.i("callback","On characteristic Read "+ characteristic.value.decodeToString())

            val receivedData = characteristic.value // Your received data byte array

            val temperature = ((receivedData[1].toInt() and 0xFF) shl 8) or (receivedData[0].toInt() and 0xFF)

            val celsiusTemperature = temperature / 10.0

            Log.i("callback",celsiusTemperature.toString())

        }
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()

        checkPermissions()

        for (device in bluetoothAdapter.bondedDevices) {

            if (device.name[0] == 'F') {
                 bluetoothDevice = bluetoothAdapter.getRemoteDevice(device.address)

                toast(device.name.toString())

                gatt = device.connectGatt(this, false, gattCallback)

            }
        }

    }


    private fun checkPermissions() {
        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf<String>(Manifest.permission.ACCESS_FINE_LOCATION),
                100
            )
            return
        }
        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.BLUETOOTH_CONNECT
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.BLUETOOTH_CONNECT),
                100
            )
            return
        }
        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.BLUETOOTH_SCAN
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.BLUETOOTH_SCAN),
                100
            )
            return
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        gatt.close()
        gatt.disconnect()
    }

}

这是清单文件

Im trying to fetch temperature data from FORA IR42. The temperature data is Indicatable data. I can get other data like manufacturer name, serial number ext. But I couldn't get temperature data as Indicatable. The onCharacteristicChanged function is not triggering after data change. Please give me a solution for read the temperature data from the bluetooth thermometer. <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.BluetoothDevice"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

我正在尝试从 FORA IR42 获取温度数据。温度数据是可指示数据。我可以获得其他数据,例如制造商名称、序列号分机号。但我无法获得可指示的温度数据。数据更改后不会触发 onCharacteristicChanged 函数。请给我一个从蓝牙温度计读取温度数据的解决方案。

bluetooth-lowenergy android-bluetooth bluetooth-gatt
1个回答
0
投票
  1. 当您启用指示/通知时,会触发 onCharacteristicChanged 回调,而不是 onCharacteristicRead。

  2. 您不应该一次性完成所有 GATT 操作,而应按顺序进行。 即读取序列号,一旦触发onCharacteristicRead就进行下一步操作

  3. 获取像nRF Connect这样的BLE android工具,确保您的特征类型是指示,如果是通知类型尝试使用

    val cccDescriptor = characteristic?.getDescriptor(CCC_DESCRIPTOR_UUID)

    val value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE

    gatt?.writeDescriptor(cccDescriptor, value)

© www.soinside.com 2019 - 2024. All rights reserved.