polarofficial / polar-ble-sdk

Repository includes SDK and code examples. More info https://polar.com/en/developers
Other
447 stars 147 forks source link

Trouble streaming HR (RR interval) data #407

Open adojnov opened 8 months ago

adojnov commented 8 months ago

Platform your question concerns:

Device:

I am currently trying to stream HR activity (specifically R R intervals). I have confirmed that bluetooth is enabled and that the device is paired and connected. I keep getting an error where the HR stream does not work. Below is the relevant portion of the code. I am fairly new to this so I may have missed a small step. If anyone could help me figure out the issue, I'd be very grateful.

class BreathingPracticeActivity : AppCompatActivity() { companion object { private const val TAG = "RRinterval" private const val PERMISSION_REQUEST_CODE = 1 }

private val polarBleApi: PolarBleApi by lazy {
    // Configure Polar Ble API features
    PolarBleApiDefaultImpl.defaultImplementation(
        applicationContext,
        setOf(
            PolarBleApi.PolarBleSdkFeature.FEATURE_HR,
            PolarBleApi.PolarBleSdkFeature.FEATURE_POLAR_SDK_MODE,
            PolarBleApi.PolarBleSdkFeature.FEATURE_BATTERY_INFO,
            PolarBleApi.PolarBleSdkFeature.FEATURE_POLAR_H10_EXERCISE_RECORDING,
            PolarBleApi.PolarBleSdkFeature.FEATURE_POLAR_OFFLINE_RECORDING,
            PolarBleApi.PolarBleSdkFeature.FEATURE_POLAR_ONLINE_STREAMING,
            PolarBleApi.PolarBleSdkFeature.FEATURE_POLAR_DEVICE_TIME_SETUP,
            PolarBleApi.PolarBleSdkFeature.FEATURE_DEVICE_INFO,
            PolarBleApi.PolarBleSdkFeature.FEATURE_POLAR_LED_ANIMATION
        )
    )
}

// Initialize the Disposable property at the class level
private var hrDisposable: Disposable? = null

private var deviceId = "B2EAB422" //"FD:9C:E1:C0:2B:E8"
private val rrDataEntries = mutableListOf<Entry>()

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

    val startHrButton = findViewById<Button>(R.id.start_hr_button)
    val stopHrButton = findViewById<Button>(R.id.stop_hr_button)
    val rrIntervalChart = findViewById<LineChart>(R.id.rrIntervalChart)

    startHrButton.setOnClickListener {
        // Check if Bluetooth permissions are granted and the specific device is connected
        if (areBluetoothPermissionsGranted()) {
            Log.d(TAG, "Bluetooth permissions granted. Starting HR stream...")

            hrDisposable = polarBleApi.startHrStreaming(deviceId)
                .subscribe(
                    { hrData: PolarHrData ->
                        for (sample in hrData.samples) {
                            if (sample.rrAvailable) {
                                Log.d(TAG, "RR interval data available")
                                val rrValues = sample.rrsMs

                                for (rrValue in rrValues) {
                                    val rrValueFloat = rrValue.toFloat()
                                    rrDataEntries.add(Entry(rrDataEntries.size.toFloat(), rrValueFloat))
                                }

                                // Update the LineChart with the RR interval data
                                updateRRIntervalChart(rrIntervalChart, rrDataEntries)
                            }
                        }
                    },
                    { error: Throwable ->
                        Log.e(TAG, "HR stream failed: ${error.message}")
                    },
                    { Log.d(TAG, "HR stream complete") }
                )
        } else {
            Log.e(TAG, "Bluetooth permissions not granted or the specific device is not connected. HR stream cannot be started.")
        }
    }

    stopHrButton.setOnClickListener {
        // Stop the heart rate data streaming when the button is clicked
        hrDisposable?.dispose()
    }
}

// Function to check if Bluetooth permissions are granted
private fun areBluetoothPermissionsGranted(): Boolean {
    val bluetoothPermissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            arrayOf(Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT)
        } else {
            arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
        }
    } else {
        arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION)
    }

    for (permission in bluetoothPermissions) {
        if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
            return false
        }
    }
    return true
}

private fun updateRRIntervalChart(chart: LineChart, entries: List<Entry>) {
    val dataSet = LineDataSet(entries, "RR Interval")
    dataSet.setDrawValues(false)

    val lineData = LineData(dataSet)

    chart.data = lineData
    chart.description.isEnabled = false
    chart.invalidate()
}

}

Thank you kindly, AD