weliem / blessed-android-coroutines

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

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ReadCharacteristic returns truncated data

cren90 opened this issue · comments

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.

Hmmm, seems like the 'long read' is not working properly. Odd...

Need to see if I can reproduce this...

I have same problem, after read first part of bytearray (with 20 bytes), don't read remnant.
first part is :
E9 00 13 01 01 00 00 31 13 01 01 00 01 09 00 00 15 5E 5B 5C
and I expect another bytearray with E9 Header, but don't get it

@weliem any updates on this?

I did a quick test with a peripheral to set a long value and read it. Seems to work fine:

D/BluetoothPeripheral: reading characteristic <00002a29-0000-1000-8000-00805f9b34fb>
I/BluetoothHandler$handlePeripheral: Received: This is quite a long text that should result in a long read
D/BluetoothPeripheral: reading characteristic <00002a24-0000-1000-8000-00805f9b34fb>
I/BluetoothHandler$handlePeripheral: Received: Pixel 5

So the central side is working fine which is to be expected because this library doesn't do anything special when reading a long characteristic. It is all handled by Android under the hood.

The problem could be with the peripheral side. But then I don't understand why it would work with nRF Connect...

Can you share some code and logs so I can see what is happening?

Yeah I'll put together a minimal reproduction and link here.

@weliem
Here's the repo: https://github.com/cren90/blessed-long-scan
Log lines when attempting to read the characteristic:

onConnectionUpdated() - Device=565D94_F interval=35 latency=0 timeout=500 status=0
2023-04-10 13:20:20.802  6743-6868  BlePeripheral.read        com...ssed.long_read  D  Characteristic read
2023-04-10 13:20:20.802  6743-6868  BlePeripheral.read        com...ssed.long_read  D  data:{
2023-04-10 13:20:20.802  6743-6868  BlePeripheral.read        com...ssed.long_read  D    "className": "BlePeripheral",
2023-04-10 13:20:20.802  6743-6868  BlePeripheral.read        com...ssed.long_read  D    "Characteristic": {
2023-04-10 13:20:20.802  6743-6868  BlePeripheral.read        com...ssed.long_read  D      "Uuid": "0000e8a2-0000-1000-8000-00805f9b34fb",
2023-04-10 13:20:20.802  6743-6868  BlePeripheral.read        com...ssed.long_read  D      "Value": "{\"uuid\":\"8d302192-ced6"
2023-04-10 13:20:20.802  6743-6868  BlePeripheral.read        com...ssed.long_read  D    },
2023-04-10 13:20:20.802  6743-6868  BlePeripheral.read        com...ssed.long_read  D    "severity": "DEBUG"
2023-04-10 13:20:20.802  6743-6868  BlePeripheral.read        com...ssed.long_read  D  }
2023-04-10 13:20:20.805  6743-6868  BlePeripheral.read        com...ssed.long_read  D  Characteristic read
2023-04-10 13:20:20.806  6743-6868  BlePeripheral.read        com...ssed.long_read  D  data:{
2023-04-10 13:20:20.806  6743-6868  BlePeripheral.read        com...ssed.long_read  D    "className": "BlePeripheral",
2023-04-10 13:20:20.806  6743-6868  BlePeripheral.read        com...ssed.long_read  D    "Characteristic": {
2023-04-10 13:20:20.806  6743-6868  BlePeripheral.read        com...ssed.long_read  D      "Uuid": "0000e8a2-0000-1000-8000-00805f9b34fb",
2023-04-10 13:20:20.806  6743-6868  BlePeripheral.read        com...ssed.long_read  D      "Value": "{\"uuid\":\"8d302192-ced6"
2023-04-10 13:20:20.806  6743-6868  BlePeripheral.read        com...ssed.long_read  D    },
2023-04-10 13:20:20.806  6743-6868  BlePeripheral.read        com...ssed.long_read  D    "severity": "DEBUG"
2023-04-10 13:20:20.806  6743-6868  BlePeripheral.read        com...ssed.long_read  D  }
2023-04-10 13:20:20.811  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E  Failed to parse device info
2023-04-10 13:20:20.811  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E  data:{
2023-04-10 13:20:20.811  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E    "className": "BlePeripheral",
2023-04-10 13:20:20.811  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E    "exception": {
2023-04-10 13:20:20.811  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E      "message": "Unexpected JSON token at offset 8: Expected quotation mark \u0027\"\u0027, but had \u0027\"\u0027 instead at path: $.uuid\nJSON input: {\"uuid\":\"8d302192-ced6",
2023-04-10 13:20:20.811  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E      "stacktrace": "kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 8: Expected quotation mark \u0027\"\u0027, but had \u0027\"\u0027 instead at path: $.uuid\nJSON input: {\"uuid\":\"8d302192-ced6\n\tat kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)\n\tat kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:584)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.fail$default(AbstractJsonLexer.kt:582)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.fail$kotlinx_serialization_json(AbstractJsonLexer.kt:223)\n\tat kotlinx.serialization.json.internal.StringJsonLexer.consumeKeyString(StringJsonLexer.kt:88)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.consumeString(AbstractJsonLexer.kt:369)\n\tat kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeString(StreamingJsonDecoder.kt:342)\n\tat kotlinx.serialization.encoding.AbstractDecoder.decodeStringElement(AbstractDecoder.kt:58)\n\tat com.cren90.blessed.long_read.ble.BleData$$serializer.deserialize(BleData.kt:5)\n\tat com.cren90.blessed.long_read.ble.BleData$$serializer.deserialize(BleData.kt:5)\n\tat kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:70)\n\tat kotlinx.serialization.json.Json.decodeFromString(Json.kt:97)\n\tat com.cren90.blessed.long_read.ble.BlePeripheral.getDeviceInfo(BlePeripheral.kt:85)\n\tat com.cren90.blessed.long_read.ble.BlePeripheral$getDeviceInfo$1.invokeSuspend(Unknown Source:14)\n\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)\n\tat kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)\n\tat kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:54)\n\tat kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:100)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:780)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:684)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:671)\n"
2023-04-10 13:20:20.811  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E    },
2023-04-10 13:20:20.811  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E    "severity": "ERROR"
2023-04-10 13:20:20.811  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E  }
2023-04-10 13:20:20.815  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E  Failed to parse device info
2023-04-10 13:20:20.815  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E  data:{
2023-04-10 13:20:20.815  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E    "className": "BlePeripheral",
2023-04-10 13:20:20.815  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E    "exception": {
2023-04-10 13:20:20.815  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E      "message": "Unexpected JSON token at offset 8: Expected quotation mark \u0027\"\u0027, but had \u0027\"\u0027 instead at path: $.uuid\nJSON input: {\"uuid\":\"8d302192-ced6",
2023-04-10 13:20:20.815  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E      "stacktrace": "kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 8: Expected quotation mark \u0027\"\u0027, but had \u0027\"\u0027 instead at path: $.uuid\nJSON input: {\"uuid\":\"8d302192-ced6\n\tat kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)\n\tat kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:584)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.fail$default(AbstractJsonLexer.kt:582)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.fail$kotlinx_serialization_json(AbstractJsonLexer.kt:223)\n\tat kotlinx.serialization.json.internal.StringJsonLexer.consumeKeyString(StringJsonLexer.kt:88)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.consumeString(AbstractJsonLexer.kt:369)\n\tat kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeString(StreamingJsonDecoder.kt:342)\n\tat kotlinx.serialization.encoding.AbstractDecoder.decodeStringElement(AbstractDecoder.kt:58)\n\tat com.cren90.blessed.long_read.ble.BleData$$serializer.deserialize(BleData.kt:5)\n\tat com.cren90.blessed.long_read.ble.BleData$$serializer.deserialize(BleData.kt:5)\n\tat kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:70)\n\tat kotlinx.serialization.json.Json.decodeFromString(Json.kt:97)\n\tat com.cren90.blessed.long_read.ble.BlePeripheral.getDeviceInfo(BlePeripheral.kt:85)\n\tat com.cren90.blessed.long_read.ble.BlePeripheral$getDeviceInfo$1.invokeSuspend(Unknown Source:14)\n\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)\n\tat kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)\n\tat kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:54)\n\tat kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:100)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:780)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:684)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:671)\n"
2023-04-10 13:20:20.815  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E    },
2023-04-10 13:20:20.815  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E    "severity": "ERROR"
2023-04-10 13:20:20.815  6743-6868  BlePeripher...tDeviceInfo com...ssed.long_read  E  }
2023-04-10 13:20:20.816  6743-6868  BluetoothGatt             com...ssed.long_read  D  cancelOpen() - device: 565D94_F

@weliem Any updates?

I am currently on holidays so I will have a look when I get back. Thanks for preparing the demo app!

I am a bit puzzled.....I tried your app and judging by the logs everything is fine...

Connected to the target VM, address: 'localhost:57300', transport: 'socket'
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/essed.long_read: Late-enabling -Xcheck:jni
I/essed.long_read: Using CollectorTypeCC GC.
D/CompatibilityChangeReporter: Compat change id reported: 171979766; UID 10127; state: ENABLED
W/ActivityThread: Application com.cren90.blessed.long_read is waiting for the debugger on port 8100...
I/System.out: Sending WAIT chunk
I/System.out: Debugger has connected
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: debugger has settled (1409)
W/ziparchive: Unable to open '/data/app/~~6sfQJYpplx1dpUJYmb4zEQ==/com.cren90.blessed.long_read-uPeH6rrYfw6QzfHyOYpCIQ==/base.dm': No such file or directory
W/ziparchive: Unable to open '/data/app/~~6sfQJYpplx1dpUJYmb4zEQ==/com.cren90.blessed.long_read-uPeH6rrYfw6QzfHyOYpCIQ==/base.dm': No such file or directory
D/nativeloader: Configuring classloader-namespace for other apk /data/app/~~6sfQJYpplx1dpUJYmb4zEQ==/com.cren90.blessed.long_read-uPeH6rrYfw6QzfHyOYpCIQ==/base.apk. target_sdk_version=33, uses_libraries=, library_path=/data/app/~~6sfQJYpplx1dpUJYmb4zEQ==/com.cren90.blessed.long_read-uPeH6rrYfw6QzfHyOYpCIQ==/lib/arm64, permitted_path=/data:/mnt/expand:/data/user/0/com.cren90.blessed.long_read
V/GraphicsEnvironment: ANGLE Developer option for 'com.cren90.blessed.long_read' set to: 'default'
V/GraphicsEnvironment: ANGLE GameManagerService for com.cren90.blessed.long_read: false
V/GraphicsEnvironment: Updatable production driver is not supported on the device.
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
W/essed.long_read: Verification of com.cren90.blessed.long_read.ble.BleAdvertiser com.cren90.blessed.long_read.MainActivity.getAdvertiser() took 116.055ms (25.85 bytecodes/s) (1408B approximate peak alloc)
W/essed.long_read: Method java.lang.Object androidx.compose.runtime.snapshots.SnapshotStateMap.mutate(kotlin.jvm.functions.Function1) failed lock verification and will run slower.
Common causes for lock verification issues are non-optimized dex code
and incorrect proguard optimizations.
W/essed.long_read: Method void androidx.compose.runtime.snapshots.SnapshotStateMap.update(kotlin.jvm.functions.Function1) failed lock verification and will run slower.
W/essed.long_read: Method boolean androidx.compose.runtime.snapshots.SnapshotStateMap.removeIf$runtime_release(kotlin.jvm.functions.Function1) failed lock verification and will run slower.
I/AdrenoGLES-0: QUALCOMM build : 4783c89, I46ff5fc46f
Build Date : 11/30/20
OpenGL ES Shader Compiler Version: EV031.31.04.01
Local Branch : QPR2
Remote Branch :
Remote Branch :
Reconstruct Branch :
I/AdrenoGLES-0: Build Config : S P 10.0.4 AArch64
I/AdrenoGLES-0: Driver Path : /vendor/lib64/egl/libGLESv2_adreno.so
I/AdrenoGLES-0: PFP: 0x016dd093, ME: 0x00000000
W/AdrenoUtils: <ReadGpuID_from_sysfs:197>: Failed to open /sys/class/kgsl/kgsl-3d0/gpu_model
W/AdrenoUtils: ReadGpuID:221: Failed to read chip ID from gpu_model. Fallback to use the GSL path
E/OpenGLRenderer: Unable to match the desired swap behavior.
W/Parcel: Expecting binder but got null!
D/ProfileInstaller: Installing profile for com.cren90.blessed.long_read
D/CompatibilityChangeReporter: Compat change id reported: 78294732; UID 10127; state: ENABLED
I/BleAdvertiser.startAdvertising: Starting BLE advertising
I/BleAdvertiser.startAdvertising: data:{
I/BleAdvertiser.startAdvertising: "className": "BleAdvertiser",
I/BleAdvertiser.startAdvertising: "severity": "INFO"
I/BleAdvertiser.startAdvertising: }
I/BleAdvertiser.startAdvertising: Starting BLE advertising
I/BleAdvertiser.startAdvertising: data:{
I/BleAdvertiser.startAdvertising: "className": "BleAdvertiser",
I/BleAdvertiser.startAdvertising: "severity": "INFO"
I/BleAdvertiser.startAdvertising: }
I/BleAdvertiser.startAdvertising: Starting BLE advertising
I/BleAdvertiser.startAdvertising: data:{
I/BleAdvertiser.startAdvertising: "className": "BleAdvertiser",
I/BleAdvertiser.startAdvertising: "severity": "INFO"
I/BleAdvertiser.startAdvertising: }
D/BluetoothGattServer: registerCallback()
D/BluetoothGattServer: registerCallback() - UUID=2bca3549-8140-4558-acc8-c945a75f56bd
D/BluetoothGattServer: onServerRegistered() - status=0 serverIf=6
D/BluetoothGattServer: addService() - service: 0000dec3-0000-1000-8000-00805f9b34fb
D/BluetoothAdapter: isLeEnabled(): ON
D/BluetoothGattServer: onServiceAdded() - handle=134 uuid=0000dec3-0000-1000-8000-00805f9b34fb status=0
D/BluetoothAdapter: isLeEnabled(): ON
I/.onAdvertisingStarted: "onAdvertisingStarted"
I/.onAdvertisingStarted: data:{
I/.onAdvertisingStarted: "className": "BleAdvertiser",
I/.onAdvertisingStarted: "severity": "INFO"
I/.onAdvertisingStarted: }
I/.onAdvertisingStarted: "onAdvertisingStarted"
I/.onAdvertisingStarted: data:{
I/.onAdvertisingStarted: "className": "BleAdvertiser",
I/.onAdvertisingStarted: "severity": "INFO"
I/.onAdvertisingStarted: }
I/.onAdvertisingStarted: "onAdvertisingStarted"
I/.onAdvertisingStarted: data:{
I/.onAdvertisingStarted: "className": "BleAdvertiser",
I/.onAdvertisingStarted: "severity": "INFO"
I/.onAdvertisingStarted: }
I/BleScanner.startScanning: Starting BLE scanning
I/BleScanner.startScanning: data:{
I/BleScanner.startScanning: "className": "BleScanner",
I/BleScanner.startScanning: "severity": "INFO"
I/BleScanner.startScanning: }
I/BleScanner.startScanning: Starting BLE scanning
I/BleScanner.startScanning: data:{
I/BleScanner.startScanning: "className": "BleScanner",
I/BleScanner.startScanning: "severity": "INFO"
I/BleScanner.startScanning: }
I/BleScanner.startScanning: Starting BLE scanning
I/BleScanner.startScanning: data:{
I/BleScanner.startScanning: "className": "BleScanner",
I/BleScanner.startScanning: "severity": "INFO"
I/BleScanner.startScanning: }
D/BluetoothAdapter: isLeEnabled(): ON
D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=4 mScannerId=0
W/essed.long_read: Cleared Reference was only reachable from finalizer (only reported once)
D/BluetoothAdapter: isLeEnabled(): ON
D/BluetoothAdapter: isLeEnabled(): ON
D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=4 mScannerId=0
D/.invoke: BLE device found
D/.invoke: data:{
D/.invoke: "className": "BleScanner",
D/.invoke: "name": "Martijn\u0027s S22",
D/.invoke: "severity": "DEBUG"
D/.invoke: }
D/.invoke: BLE device found
D/.invoke: data:{
D/.invoke: "className": "BleScanner",
D/.invoke: "name": "Martijn\u0027s S22",
D/.invoke: "severity": "DEBUG"
D/.invoke: }
D/.invoke: BLE device found
D/.invoke: data:{
D/.invoke: "className": "BleScanner",
D/.invoke: "name": "Martijn\u0027s S22",
D/.invoke: "severity": "DEBUG"
D/.invoke: }
D/BluetoothGatt: connect() - device: 7E:2A:18:01:75:C8, auto: false
D/BluetoothGatt: registerApp()
D/BluetoothGatt: registerApp() - UUID=63b5296b-1c79-48cc-9aac-e1b62a4d350b
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=7
D/BluetoothGattServer: onServerConnectionState() - status=0 serverIf=6 device=7E:2A:18:01:75:C8
D/BluetoothGattServer: connect() - device: 7E:2A:18:01:75:C8, auto: false
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=7 device=7E:2A:18:01:75:C8
D/BluetoothGatt: onServiceChanged() - Device=7E:2A:18:01:75:C8
D/BluetoothGatt: discoverServices() - device: 7E:2A:18:01:75:C8
D/BluetoothGattServer: onMtuChanged() - device=7E:2A:18:01:75:C8, mtu=517
D/BluetoothGatt: onSearchComplete() = Device=7E:2A:18:01:75:C8 Status=0
D/BluetoothGatt: configureMTU() - device: 7E:2A:18:01:75:C8 mtu: 517
D/BluetoothGatt: onConfigureMTU() - Device=7E:2A:18:01:75:C8 mtu=517 status=0
D/BlePeripheral.read: Characteristic read
D/BlePeripheral.read: data:{
D/BlePeripheral.read: "className": "BlePeripheral",
D/BlePeripheral.read: "Characteristic": {
D/BlePeripheral.read: "Uuid": "0000e8a2-0000-1000-8000-00805f9b34fb",
D/BlePeripheral.read: "Value": "{"uuid":"537faba4-430d-48b1-8679-6a8486f2dbda","seq":1,"priv":1,"name":"Device Name","vers":"BuildConfig.VERSION_NAME","mfg":"samsung","model":"r0s - SM-S901B","os":"Android","osVers":"13"}"
D/BlePeripheral.read: },
D/BlePeripheral.read: "severity": "DEBUG"
D/BlePeripheral.read: }
D/BlePeripheral.read: Characteristic read
D/BlePeripheral.read: data:{
D/BlePeripheral.read: "className": "BlePeripheral",
D/BlePeripheral.read: "Characteristic": {
D/BlePeripheral.read: "Uuid": "0000e8a2-0000-1000-8000-00805f9b34fb",
D/BlePeripheral.read: "Value": "{"uuid":"537faba4-430d-48b1-8679-6a8486f2dbda","seq":1,"priv":1,"name":"Device Name","vers":"BuildConfig.VERSION_NAME","mfg":"samsung","model":"r0s - SM-S901B","os":"Android","osVers":"13"}"
D/BlePeripheral.read: },
D/BlePeripheral.read: "severity": "DEBUG"
D/BlePeripheral.read: }
D/BlePeripheral.read: Characteristic read
D/BlePeripheral.read: data:{
D/BlePeripheral.read: "className": "BlePeripheral",
D/BlePeripheral.read: "Characteristic": {
D/BlePeripheral.read: "Uuid": "0000e8a2-0000-1000-8000-00805f9b34fb",
D/BlePeripheral.read: "Value": "{"uuid":"537faba4-430d-48b1-8679-6a8486f2dbda","seq":1,"priv":1,"name":"Device Name","vers":"BuildConfig.VERSION_NAME","mfg":"samsung","model":"r0s - SM-S901B","os":"Android","osVers":"13"}"
D/BlePeripheral.read: },
D/BlePeripheral.read: "severity": "DEBUG"
D/BlePeripheral.read: }
D/BluetoothGatt: cancelOpen() - device: 7E:2A:18:01:75:C8
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=7 device=7E:2A:18:01:75:C8
D/BluetoothGatt: close()
D/BluetoothGatt: unregisterApp() - mClientIf=7
D/BluetoothGattServer: onServerConnectionState() - status=0 serverIf=6 device=7E:2A:18:01:75:C8
D/BluetoothGattServer: onServerConnectionState() - status=0 serverIf=6 device=7E:2A:18:01:75:C8
D/.invoke: BLE device found
D/.invoke: data:{
D/.invoke: "className": "BleScanner",
D/.invoke: "name": "Martijn\u0027s S22",
D/.invoke: "severity": "DEBUG"
D/.invoke: }
D/.invoke: BLE device found
D/.invoke: data:{
D/.invoke: "className": "BleScanner",
D/.invoke: "name": "Martijn\u0027s S22",
D/.invoke: "severity": "DEBUG"
D/.invoke: }
D/.invoke: BLE device found
D/.invoke: data:{
D/.invoke: "className": "BleScanner",
D/.invoke: "name": "Martijn\u0027s S22",
D/.invoke: "severity": "DEBUG"
D/.invoke: }
D/BluetoothGatt: connect() - device: 7E:2A:18:01:75:C8, auto: false
D/BluetoothGatt: registerApp()
D/BluetoothGatt: registerApp() - UUID=8f23757c-b860-498c-bc81-1bb0c1cdc50f
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=7
D/BluetoothGattServer: onServerConnectionState() - status=0 serverIf=6 device=7E:2A:18:01:75:C8
D/BluetoothGattServer: connect() - device: 7E:2A:18:01:75:C8, auto: false
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=7 device=7E:2A:18:01:75:C8
D/BluetoothGatt: discoverServices() - device: 7E:2A:18:01:75:C8
D/BluetoothGatt: onSearchComplete() = Device=7E:2A:18:01:75:C8 Status=0
D/BluetoothGatt: configureMTU() - device: 7E:2A:18:01:75:C8 mtu: 517
D/BluetoothGattServer: onMtuChanged() - device=7E:2A:18:01:75:C8, mtu=517
D/BluetoothGatt: onConfigureMTU() - Device=7E:2A:18:01:75:C8 mtu=517 status=0
D/BlePeripheral.read: Characteristic read
D/BlePeripheral.read: data:{
D/BlePeripheral.read: "className": "BlePeripheral",
D/BlePeripheral.read: "Characteristic": {
D/BlePeripheral.read: "Uuid": "0000e8a2-0000-1000-8000-00805f9b34fb",
D/BlePeripheral.read: "Value": "{"uuid":"3468b32a-458b-4640-9543-6a77c335d780","seq":1,"priv":1,"name":"Device Name","vers":"BuildConfig.VERSION_NAME","mfg":"samsung","model":"r0s - SM-S901B","os":"Android","osVers":"13"}"
D/BlePeripheral.read: },
D/BlePeripheral.read: "severity": "DEBUG"
D/BlePeripheral.read: }
D/BlePeripheral.read: Characteristic read
D/BlePeripheral.read: data:{
D/BlePeripheral.read: "className": "BlePeripheral",
D/BlePeripheral.read: "Characteristic": {
D/BlePeripheral.read: "Uuid": "0000e8a2-0000-1000-8000-00805f9b34fb",
D/BlePeripheral.read: "Value": "{"uuid":"3468b32a-458b-4640-9543-6a77c335d780","seq":1,"priv":1,"name":"Device Name","vers":"BuildConfig.VERSION_NAME","mfg":"samsung","model":"r0s - SM-S901B","os":"Android","osVers":"13"}"
D/BlePeripheral.read: },
D/BlePeripheral.read: "severity": "DEBUG"
D/BlePeripheral.read: }
D/BlePeripheral.read: Characteristic read
D/BlePeripheral.read: data:{
D/BlePeripheral.read: "className": "BlePeripheral",
D/BlePeripheral.read: "Characteristic": {
D/BlePeripheral.read: "Uuid": "0000e8a2-0000-1000-8000-00805f9b34fb",
D/BlePeripheral.read: "Value": "{"uuid":"3468b32a-458b-4640-9543-6a77c335d780","seq":1,"priv":1,"name":"Device Name","vers":"BuildConfig.VERSION_NAME","mfg":"samsung","model":"r0s - SM-S901B","os":"Android","osVers":"13"}"
D/BlePeripheral.read: },
D/BlePeripheral.read: "severity": "DEBUG"
D/BlePeripheral.read: }
D/BluetoothGatt: cancelOpen() - device: 7E:2A:18:01:75:C8
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=7 device=7E:2A:18:01:75:C8
D/BluetoothGatt: close()
D/BluetoothGatt: unregisterApp() - mClientIf=7
D/BluetoothGattServer: onServerConnectionState() - status=0 serverIf=6 device=7E:2A:18:01:75:C8
D/BluetoothGattServer: onServerConnectionState() - status=0 serverIf=6 device=7E:2A:18:01:75:C8
D/BluetoothAdapter: isLeEnabled(): ON
Disconnected from the target VM, address: 'localhost:57300', transport: 'socket'

Is there a specific way to trigger the issue?

Perhaps it is phone related or Android version related....what are you testing on? I used a Samsung S22 and a Pixel 5 both running Android 13

I've been testing between my Galaxy S9+ running Android 10 and my Note 20 Ultra running Android 13. Others at my company are seeing the same behavior between multiple Pixel 6 devices running Android 13

Looks like it was the translation from byte[] to string that was causing the issue. When I used either ByteArray.asString() or ByteArray.toString() I got a 20 char string, switching to ByteArray.decodeToString() resolved. I'm going to mark as closed.
@SaeedBahari this might resolve for you as well.