Giter Site home page Giter Site logo

weliem / blessed-android-coroutines Goto Github PK

View Code? Open in Web Editor NEW
119.0 4.0 31.0 568 KB

BLESSED Coroutines, a Bluetooth Low Energy (BLE) library for Android using Kotlin Coroutines

License: MIT License

Kotlin 100.00%
bluetooth-low-energy bluetooth-le kotlin coroutines android-library

blessed-android-coroutines's People

Contributors

bbilger avatar cren90 avatar nisrulz avatar weliem avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

blessed-android-coroutines's Issues

Get all records at once

Currently the setupGLXnotifications listens and returns all the records one by one, how can I retrieve all the records at once, or find the total records available in the device so i know which is the last one.

I tried returning the last record like that and then checking while it's observing when the last record appears. But on the device I am using it returns the results descending, so the last record appears as the first one.
val command = byteArrayOf(OP_CODE_REPORT_STORED_RECORDS, OPERATOR_LAST_RECORD)

I also tried with "first record" with Byte = 5 but it doesn't get returned. It returns the "Last record" again. I guess these are device specific issues because i have encountered similar behaviours on different devices. So I'm not sure what will be the correct way to handle that.

I would appreciate some pointers to how I can achieve that. How to know when all of the records have been returned so I don't miss any recording.

Send an array of bytes

Hi once again, Im again using your library and I was thinking on a way of, for example I have a device lets say is TD4289 in this example and I want to send an array of bytes such as [0x51, 0x26, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x1A] and read the information that comes with it, should be some data. Could I possibly do that? Send that exact array and await/read the data from the device?

As I dont fully understand bluetooth and BLE yet if you could teach me how to achieve what I just said I would be really glad.

Much thanks.

IllegalStateException BT Adapter is not turned ON

OS version: Android 13, 14
Device: Pixel 5, Pixel 6, Pixel 7 Pro
Background: Yes
Rooted: No
Blessed-android-coroutines: 0.4.0

Fatal Exception: java.lang.IllegalStateException: BT Adapter is not turned ON
       at android.bluetooth.le.BluetoothLeUtils.checkAdapterStateOn(BluetoothLeUtils.java:160)
       at android.bluetooth.le.BluetoothLeScanner.stopScan(BluetoothLeScanner.java:310)
       at com.welie.blessed.BluetoothCentralManager.stopScan(BluetoothCentralManager.kt:415)
       at com.welie.blessed.BluetoothCentralManager.setScanTimer$lambda-8(BluetoothCentralManager.kt:700)
       at com.welie.blessed.BluetoothCentralManager.$r8$lambda$nxpJqov4C8B70Ry3ZyS3UMxi7p0()
       at com.welie.blessed.BluetoothCentralManager$$ExternalSyntheticLambda2.run(:2)
       at android.os.Handler.handleCallback(Handler.java:959)
       at android.os.Handler.dispatchMessage(Handler.java:100)
       at android.os.Looper.loopOnce(Looper.java:232)
       at android.os.Looper.loop(Looper.java:317)
       at android.app.ActivityThread.main(ActivityThread.java:8532)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
       at com.android.internal.os.ExecInit.main(ExecInit.java:50)
       at com.android.internal.os.RuntimeInit.nativeFinishInit(RuntimeInit.java)
       at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:359)

I see this issue occur in blessed-android with same problem is weliem/blessed-android#169
and have fixed in weliem/blessed-android#171. Do you have plan update this issue to blessed-android-coroutines

Write success after 2nd connect

Hello!

I am encountering a problem and am somewhat at odds as to how to solve it.

Scenario:
We have a bluetooth device that has been tried and tested. This year I wrote a new android app to connect to the device. Since we were often plagued with 133 errors I decided to give this library a try.

My problem:
If the Bluetoothdevice does a fresh boot and I try to write a characteristic then it does nothing. But it does not even throw an error. Even android's own BluetoothGatt write call returns status=0 ( whatever that is worth with writetype=NO_RESPONSE)...

Once I disconnect, rescan, reconnect to the device I can write without any problems until the bluetooth device gets bootet again.

I used the BluetoothHandler class from the examples. And since it is a singleton I really don't understand why it only works the second time around.

I tested this by added a writeCharacteristic to the handlePeripheral() method so that after a connection is made we can send some data and directly know if the device gets the data. And like I said, after the second connection the data always gets transmitted.

Anyone have a clue as to what is going on here? Or how I could try to further debug this situation?

Running this on a Samsung A20e phone

Greetings

Receiving UInt8 as ByteArray

The question is as follows:

I have devices, that send a uint8_t array as bytes to an Android device. In embedded C uint8_t and byte as the same and range from 0 to 255. However, this library uses ByteArrays, which are signed and accept values ranging from -127 to 127. So that happens if I connect to these devices and how can I make sure to receive the correct data?

Not detecting Heart Rate Sensor (0x180D)-> When when scanning with Service

I am trying to find my device using the following code
var deviceMap = HashMap<String, BluetoothPeripheral>()
val HEART_RATE_NOTIFY_SERVICE_UUID = UUID.fromString("0000180d-0000-1000-8000-00805f9b34fb")
val WEIGHT_SCALE_SERVICE = UUID.fromString("0000181d-0000-1000-8000-00805f9b34fb")
var list = arrayOf(
WEIGHT_SCALE_SERVICE,
HEART_RATE_NOTIFY_SERVICE_UUID
)
centralManager.scanForPeripheralsWithServices(list, { peripheral, scanResult ->
Log.d("Device", peripheral.address)
deviceMap.put(peripheral.address, peripheral)
}, { error ->
})

It is able to detect weight scale but not detecting heart rate.

"IllegalStateException: Already resumed" on disconnected internal callback

Hi

Using 0.3.0, we sometime have this exception

Fatal Exception: java.lang.IllegalStateException: Already resumed
       at kotlin.coroutines.SafeContinuation.resumeWith(SafeContinuationJvm.kt:44)
       at com.welie.blessed.BluetoothCentralManager$cancelConnection$2$1.onDisconnectedPeripheral(BluetoothCentralManager.kt:538)
       at com.welie.blessed.BluetoothCentralManager$internalCallback$1$disconnected$1.invokeSuspend(BluetoothCentralManager.kt:209)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
       at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:39)
       at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
       at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

There is no way to catch it outise of the lib because the exception raise in an internal callback here :
https://github.com/weliem/blessed-android-coroutines/blob/0.3.0/blessed/src/main/java/com/welie/blessed/BluetoothCentralManager.kt#L209

compose ui

Has Blessed been tested on Compose UI?

ReadCharacteristic returns truncated data

I'm using the library both for advertising from device1 and scanning from device2.

When attempting to read a characteristic on device1, I get the callback in device1 for BluetoothPeripheralManagerCallback.onCharacteristicRead and then perform characteristic.setValue(data) which is ~200 characters. I get the first 22 chars returned to device2 peripheral.readCharacteristic(uuid, uuid).

If I scan using the nRF app, on device2 I see the full data payload.
I've also tried requestMtu(MAX_MTU) and that hasn't helped.

It appears as though the suspendCoroutine in BluetoothPeripheral.readCharacteristic line 790 is resuming early on the first value being read.

Release name is wrong

I think it is supposed to be v0.1.3, unless there is a missing tag of 0.1.4 and the tag 0.1.3 got overwritten or something.

Screenshot 2021-11-29 at 13 02 54

Screenshot 2021-11-29 at 13 03 21

ScanRecord not available in BluetoothPeripheral

Hi,

I'm using your library and everything is fine but currently we have a request to check for advertising flags once we get scanning results. Currently method :
private fun sendScanResult(result: ScanResult) { scope.launch { if (isScanning) { val peripheral = getPeripheral(result.device.address) peripheral.setDevice(result.device) currentResultCallback?.invoke(peripheral, result) } } }

assigns only device (BluetoothDevice) but there is no support for ScanRecord.
Is this something that is in planned to be supported by the lib, or is there some workaround?
Are you ok to create a PR to support this?

Best regards,
Nemanja

Trying to get 16 byte from Characteristic but ouputs only zeros

I can can read from this characteristics in the NRF app as well as using the flutter_blue library, which we used for an older app before.

I'm using this code to read from a characteristic.

peripheral.getCharacteristic(SERVICE_UUID, NOTIFICATION_UUID)?.let {
   val test = peripheral.readCharacteristic(it)
   Timber.d("${test.size}")
   Timber.d("${test.asList()}")
}

As output, I only get zeros

/BluetoothPeripheral: reading characteristic <0000ff01-0000-1000-8000-00805f9b34fb>
D/BluetoothHandler: 16
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

That am I missing? I tried it on Android 11 and on an old Android 9 phone with the same result both times

minSdk 26

Hello Weliem,
first of all, congrats on your SDK. My problem is that I'd like to import it into my app but since I need to support devices with at least Oreo on board (Api Level 24) it looks like I cannot because your SDK's minSdk is 26. Is there a reason for that? Thanks

Mark location permissions with maxSdkVersion=30

Location permissions are only required for API 30 and below. Marking those to be only for maxSdkVersion=30 should be part of the lib.

<uses-permission
        android:name="android.permission.ACCESS_FINE_LOCATION"
        android:maxSdkVersion="30" />
    <uses-permission
        android:name="android.permission.ACCESS_COARSE_LOCATION"
        android:maxSdkVersion="30" />

I already have a branch with the changes, but wanted to open an issue to discuss if there are any blockers or questions.

BluetoothBytesParser array index out of bounds

E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-9
Process: com.welie.blessedexample, PID: 22490
java.lang.ArrayIndexOutOfBoundsException: length=7; index=7
at com.welie.blessed.BluetoothBytesParser.setCurrentTime(BluetoothBytesParser.kt:559)
at com.welie.blessedexample.BluetoothHandler$handlePeripheral$1.invokeSuspend(BluetoothHandler.kt:54)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:39)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

value size is reset to 7 in call to setDateTime() after being set to 10 in setCurrentTime()

fun setCurrentTime(calendar: Calendar): Boolean {
    value = ByteArray(10)
    setDateTime(calendar)
    value[7] = ((calendar[Calendar.DAY_OF_WEEK] + 5) % 7 + 1).toByte()
    value[8] = (calendar[Calendar.MILLISECOND] * 256 / 1000).toByte()
    value[9] = 1
    return true
}

/**
 * Sets the byte array to represent the current date in CurrentTime format
 *
 * @param calendar the calendar object representing the current date
 * @return flase if the calendar object was null, otherwise true
 */
fun setDateTime(calendar: Calendar): Boolean {
    value = ByteArray(7)
    value[0] = calendar[Calendar.YEAR].toByte()
    value[1] = (calendar[Calendar.YEAR] shr 8).toByte()
    value[2] = (calendar[Calendar.MONTH] + 1).toByte()
    value[3] = calendar[Calendar.DATE].toByte()
    value[4] = calendar[Calendar.HOUR_OF_DAY].toByte()
    value[5] = calendar[Calendar.MINUTE].toByte()
    value[6] = calendar[Calendar.SECOND].toByte()
    return true
}

Wrong implementation of bytesToFloat

Hello, I receive wrong values when trying to read a FORMAT_FLOAT as shown by this test

package com.welie.blessed

import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import java.nio.ByteBuffer
import java.nio.ByteOrder

class BluetoothBytesParserTest {

    @Test
    fun getFloatValueLE() {
        val byteParser = BluetoothBytesParser(
            ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putFloat(1.1f).array(),
            ByteOrder.LITTLE_ENDIAN
        )
        assertEquals(byteParser.getFloatValue(BluetoothBytesParser.FORMAT_FLOAT), 1.1f)
    }

    @Test
    fun getFloatValueBE() {
        val byteParser = BluetoothBytesParser(
            ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putFloat(1.1f).array(),
            ByteOrder.BIG_ENDIAN
        )
        assertEquals(byteParser.getFloatValue(BluetoothBytesParser.FORMAT_FLOAT), 1.1f)
    }

    @Test
    fun setFloatValueLE() {
        val byteParser = BluetoothBytesParser(ByteArray(4), ByteOrder.LITTLE_ENDIAN)
        val floatValue = byteParser.setFloatValue(1.1f, BluetoothBytesParser.FORMAT_FLOAT)
        assertTrue(floatValue)
        assertEquals(ByteBuffer.wrap(byteParser.value).order(ByteOrder.LITTLE_ENDIAN).float, 1.1f)
    }

    @Test
    fun setFloatValueBE() {
        val byteParser = BluetoothBytesParser(ByteArray(4), ByteOrder.BIG_ENDIAN)
        val floatValue = byteParser.setFloatValue(1.1f, BluetoothBytesParser.FORMAT_FLOAT)
        assertTrue(floatValue)
        assertEquals(ByteBuffer.wrap(byteParser.value).order(ByteOrder.BIG_ENDIAN).float, 1.1f)
    }
}

Unreliable notifications

Hi
I have a device using a nRF52 chip that sends a notification immediately after the notification is enabled to initially populate some fields in my Android app. I noted that this is not reliable and could narrow it down to something happening on Android, as I control the nRF52 and could verify that the notification is indeed sent. There is no log entry, it just does not happen. I have 4 characteristics, but get notifications for any number between 0 and 4 when I initially connect. Later, the notifications do work.

What I tried so far:

  • Delaying the observe() call all together or individually spaced for up to 2 seconds in between calls
  • Delaying the response from the nRF52 in the same manner

My code to set up notifications look like that:
private suspend fun setupAmountNotification(peripheral: BluetoothPeripheral) { peripheral.getCharacteristic( UUID.fromString(SERVICE_UUID), UUID.fromString(CHAR_AMOUNT_UUID) )?.let { peripheral.observe(it) {value -> Log.i(TAG, "Notification for amount") val parser = BluetoothBytesParser(value, ByteOrder.LITTLE_ENDIAN) runOnUiThread{ onAmountNotification(parser.getIntValue(FORMAT_UINT32)) } } } }

In turn, I get this log (the other observe functions are analogous):
D/MainActivity: Peripheral eo-4095 has CONNECTED D/BluetoothGatt: setCharacteristicNotification() - uuid: e44e1403-14b3-457c-xxxx-34bf34932966 enable: true D/BluetoothGatt: setCharacteristicNotification() - uuid: e44e1402-14b3-457c-xxxx-34bf34932966 enable: true D/BluetoothGatt: setCharacteristicNotification() - uuid: e44e1401-14b3-457c-xxxx-34bf34932966 enable: true D/BluetoothGatt: setCharacteristicNotification() - uuid: e44e1404-14b3-457c-xxxx-34bf34932966 enable: true I/MainActivity: Notification for reservoir I/MainActivity: Notification for status

How to stop observing connection state

I am observing connection during onResume and I can't figure out way to stopObserving this. Is there any way to do so?

centralManager.observeConnectionState { peripheral, state ->
Log.d("Connected Device",peripheral.address)
}

use library on android wear 3 -> bonding failed

so this is a special one ... i'm trying to use your library on an android wear 3 watch (samsung galaxy watch 4).

on my phone your demo-app is asking me if i want to bond with my omron evolv and after pressing yes everything works.
on my watch this popup is not shown and it immediately logs "bonding failed"

i don't think that you tried your library on a watch and especially not on wear os 3 but maybe you have an idea.

log from my watch:

2022-08-04 15:48:54.924 15479-15479/com.example.bt_wear_spielwiese D/BluetoothPeripheral: starting bonding with 'BLESmart_0000021FEC21E500D0D6' (EC:21:E5:00:D0:D6)
2022-08-04 15:48:54.928 15479-16079/com.example.bt_wear_spielwiese I/BluetoothHandler$connectPeripheral: Bond state is BONDING
2022-08-04 15:48:54.938 15479-15479/com.example.bt_wear_spielwiese D/BluetoothPeripheral: pairing request received: PAIRING_VARIANT_CONSENT (3)
2022-08-04 15:48:55.028 15479-15479/com.example.bt_wear_spielwiese E/BluetoothPeripheral: bonding failed for 'BLESmart_0000021FEC21E500D0D6', disconnecting device
2022-08-04 15:48:55.031 15479-16055/com.example.bt_wear_spielwiese D/BluetoothGatt: cancelOpen() - device: EC:21:E5:00:D0:D6
2022-08-04 15:48:55.031 15479-16079/com.example.bt_wear_spielwiese I/BluetoothHandler$connectPeripheral: Bond state is BONDING_FAILED
2022-08-04 15:48:55.060 15479-16038/com.example.bt_wear_spielwiese D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=7 device=EC:21:E5:00:D0:D6
2022-08-04 15:48:55.083 15479-16038/com.example.bt_wear_spielwiese D/BluetoothPeripheral: disconnected 'BLESmart_0000021FEC21E500D0D6' on request
2022-08-04 15:48:55.085 15479-16038/com.example.bt_wear_spielwiese D/BluetoothGatt: close()
2022-08-04 15:48:55.097 15479-16038/com.example.bt_wear_spielwiese D/BluetoothGatt: unregisterApp() - mClientIf=7
2022-08-04 15:48:55.123 15479-16060/com.example.bt_wear_spielwiese E/BluetoothHandler: Peripheral BLESmart_0000021FEC21E500D0D6 has DISCONNECTED

Advertise Fails DATA_TOO_LARGE

I'm following the guide at Server.MD to POC an android app as a heart rate monitor. I get a DATA_TOO_LARGE error on attempting to advertise. Here are the pertinent pieces of the POC:

private val hrmService = UUID.fromString("0000180D-0000-1000-8000-00805f9b34fb")
private val hrmCharacteristic = UUID.fromString("00002A37-0000-1000-8000-00805f9b34fb")
private val service = BluetoothGattService(hrmService, BluetoothGattService.SERVICE_TYPE_PRIMARY)
private val characteristic = BluetoothGattCharacteristic(hrmCharacteristic, PROPERTY_READ or PROPERTY_INDICATE, PERMISSION_READ_ENCRYPTED_MITM)
private val peripheralManager by lazy { BluetoothPeripheralManager(this, getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager, callback) }

fun setupAdvertising() {
        CoroutineScope(Dispatchers.IO).launch {
            hrFlow.collect {
                it?.let {
                    val bytes = ByteBuffer.allocate(Int.SIZE_BYTES).apply {
                        putShort(it)
                    }.array()
                    peripheralManager.notifyCharacteristicChanged(bytes, characteristic)
                }
            }
        }

        service.addCharacteristic(characteristic)
        peripheralManager.add(service)

        val advertiseSettings = AdvertiseSettings.Builder()
            .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
            .setConnectable(true)
            .setTimeout(0)
            .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
            .build()

        val advertiseData = AdvertiseData.Builder()
            .setIncludeTxPowerLevel(true)
            .addServiceUuid(ParcelUuid(hrmService))
            .build()

        val scanResponse = AdvertiseData.Builder()
            .setIncludeDeviceName(true)
            .build()

        peripheralManager.startAdvertising(advertiseSettings, scanResponse, advertiseData)
    }

observeConnectionState - 5 second delay

Hi, First off, Thank you for writing this library. It has made dealing with BLE a much better experience.

My question is, is there a faster way to get feedback from observeConnectionState?
I have a total of 6 BLE devices that I am connected to and my requirement is to stop all of the connections if any of the devices gets disconnected.

The callback works great and I am able to disconnect all of the devices if 1 becomes disconnected but there's about a 5 second delay from when I pull the battery off 1 device until the time the callback gets called?

Notify Listeners when Scan Fails

Currently, the BluetoothCentralManager gets the failure status and logs it, but doesn't send it to listeners:

    private fun sendScanFailed(scanFailure: ScanFailure) {
        currentCallback = null
        currentFilters = null
        scope.launch {
            Logger.e(TAG, "scan failed with error code %d (%s)", scanFailure.value, scanFailure)
         //   bluetoothCentralManagerCallback.onScanFailed(scanFailure)
        }
    }

Looks like it's just a matter of uncommenting line 124.

Not showing temp or anything in the screen

Hello, I found out this by coincidence while studying Bluetooth and coroutines on android studio kotlin and I found out your library in java which is amazing and works amazingly, I found out this one too just now and wanted to run a test if it worked as smooth as the java one but the text when you measure temperature is not showing, didn't test anything else but that for now but I don't know if you are going to look into this, in the logcat it all works wonderful.

BluetoothPeripheral GATT error NO_RESOURCES

E/BluetoothPeripheral: writing to characteristic <00002a2b-0000-1000-8000-00805f9b34fb> failed, status 'NO_RESOURCES'
E/BluetoothHandler$handlePeripheral: com.welie.blessed.GattException: GATT error NO_RESOURCES (128)
at com.welie.blessed.BluetoothPeripheral$writeCharacteristic$4$result$1.onCharacteristicWrite(BluetoothPeripheral.kt:861)
at com.welie.blessed.BluetoothPeripheral$bluetoothGattCallback$1$onCharacteristicWrite$1.invokeSuspend(BluetoothPeripheral.kt:201)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:920)

I am using Omron BP5450. Running the example program. The java version of the library works fine. Phone is Samsung Galaxy A52 5G.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.