question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Android backend does not give each service/characteristic a unique "handle".

See original GitHub issue
  • bleak version: 0.14.3
  • Python version: Python 3.7.13 (Colab)
  • Operating System: Samsung SM-G900F Android 6.0.1, API 23

Description

Hello! I am trying to implement an application on an android mobile. This app needs to connect via low-energy bluetooth BLE to a scale (Mi Smart Scale 2) and take the weight. To create the apk of the application I use Colab. The problem is that when I launch the application it crashes immediately after starting and I cannot read the weight.

What I Did

import asyncio

from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty

from bleak import BleakClient


kv = '''
WindowManager:
    
    MainWindow:
    BluetoothWindow:
    LoginWindow:
    
        
     
    
<LoginWindow>:
    name: "login"

    email: email
    password: password

    FloatLayout:

        Label:
            text:"Email: "
            font_size: (root.width**2 + root.height**2) / 13**4
            pos_hint: {"x":0.1, "top":0.9}
            size_hint: 0.35, 0.15

        TextInput:
            id: email
            font_size: (root.width**2 + root.height**2) / 13**4
            multiline: False
            pos_hint: {"x": 0.45 , "top":0.9}
            size_hint: 0.4, 0.15

        Label:
            text:"Password: "
            font_size: (root.width**2 + root.height**2) / 13**4
            pos_hint: {"x":0.1, "top":0.7}
            size_hint: 0.35, 0.15

        TextInput:
            id: password
            font_size: (root.width**2 + root.height**2) / 13**4
            multiline: False
            password: True
            pos_hint: {"x": 0.45, "top":0.7}
            size_hint: 0.4, 0.15

        Button:
            pos_hint:{"x":0.2,"y":0.05}
            size_hint: 0.6, 0.2
            font_size: (root.width**2 + root.height**2) / 13**4
            text: "Login"
            on_release:
                app.root.current = "main"
                root.manager.transition.direction = "left"

        Button:
            pos_hint:{"x":0.2,"y":0.3}
            size_hint: 0.6, 0.1
            font_size: (root.width**2 + root.height**2) / 17**4
            text: "Non hai un account? Creane uno"  
            on_release:
     
                
     
        
     
<MainWindow>:
    name: "main"
    BoxLayout:
		orientation: "vertical"
		size: root.width, root.height
        
    FloatLayout:
        n: n
        email: email
        created:created

        FloatLayout:
            Label:
                id: n
                pos_hint:{"x": 0.1, "top":0.9}
                size_hint:0.8, 0.2
                text: "Nome account: "

            Label:
                id: email
                pos_hint:{"x": 0.1, "top":0.7}
                size_hint:0.8, 0.2
                text: "Email: "

            Label:
                id: created
                pos_hint:{"x": 0.1, "top":0.5}
                size_hint:0.8, 0.2
                text: "Creato il: "

            Button:
                pos_hint:{"x":0.35, "y": 0.2}
                size_hint:0.3,0.1
                text: "Log Out"
                on_release:
                    app.root.current = "login"
                    root.manager.transition.direction = "right"
                

            Button:
                pos_hint:{"x":0.35, "y": 0.1}
                size_hint:0.3,0.1
                text: "Log In"
                on_release:
                    app.root.current = "ble"
                    root.manager.transition.direction = "left"
                
<BluetoothWindow>:
    name: "ble"
    peso: peso

    
    BoxLayout:
		orientation: "vertical"
		size: root.width, root.height

    FloatLayout:
        Label:
            id: peso
            pos_hint:{"x": 0.1, "top":0.7}
            size_hint:0.8, 0.2
            text: "peso: "
        
        Button:
            pos_hint:{"x":0.2, "y": 0.1}
            size_hint:0.6,0.2
            text: "Log Out"
            on_release:
                app.root.current = "main"
                root.manager.transition.direction = "right"
'''

class LoginWindow(Screen):
    pass

class MainWindow(Screen):
    pass

class BluetoothWindow(Screen):
    peso = ObjectProperty(None)
    
    def on_enter(self):

        self.peso.text = "peso: " + str(data2)


class WindowManager(ScreenManager):
    pass

sm = WindowManager()

screens = [MainWindow(name="main"), 
           BluetoothWindow(name="ble"),
           LoginWindow(name="login")]

for screen in screens:
    sm.add_widget(screen)


sm.current = "main"

class AsyncApp(App):

    other_task = None

    def build(self):
        return Builder.load_string(kv)
    
    def build2(self):
        return sm

    def app_func(self):
        '''This will run both methods asynchronously and then block until they
        are finished
        '''
        self.other_task = asyncio.ensure_future(self.get_the_weight_from_the_mi_smart_scale_2())

        async def run_wrapper():
            # we don't actually need to set asyncio as the lib because it is
            # the default, but it doesn't hurt to be explicit
            await self.async_run(async_lib='asyncio')
            print('App done')
            self.other_task.cancel()

        return asyncio.gather(run_wrapper(), self.other_task)
   
    global notification_handler
    def notification_handler(sender, data):
        """Simple notification handler which prints the data received."""
        data1 = list(data)
        global data2
        data2 = ((data1[1]+data1[2]*256)*0.005)
        print("{0}: {1}".format(sender, data2))

    async def get_the_weight_from_the_mi_smart_scale_2(self):
        #da modificare
        '''This method is also run by the asyncio loop and periodically prints
        something.
        '''
        async with BleakClient("70:87:9e:0f:f8:7d") as client:
            print(f"Connected: {client.is_connected}")
            
            await client.start_notify("00002a9d-0000-1000-8000-00805f9b34fb", notification_handler)
            await asyncio.sleep(30.0)
            await client.stop_notify("00002a9d-0000-1000-8000-00805f9b34fb")   
            print(f"Connected: {client.is_connected}")

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(AsyncApp().app_func())
    loop.close()
### What I read on Android Studio's log######################################
2022-07-13 15:53:26.187 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 3
2022-07-13 15:53:26.187 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 3
2022-07-13 15:53:26.187 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 3
2022-07-13 15:53:26.187 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 3
2022-07-13 15:53:26.187 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 4
2022-07-13 15:53:26.187 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.187 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 3
2022-07-13 15:53:26.187 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 3
2022-07-13 15:53:26.187 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 3
2022-07-13 15:53:26.187 1983-2477/? W/bt_btif: bta_le_client_conn_param_cback, status : 0
2022-07-13 15:53:26.187 1983-2477/? W/bt_btif: bta_le_client_conn_param_cback, clcb found and client_if : 10
2022-07-13 15:53:26.187 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 3
2022-07-13 15:53:26.187 1983-2204/? D/BtGatt.GattService: onClientConnParamsChanged() - clientIf=10 address=70:87:9E:0F:F8:7D, interval=39status=0
2022-07-13 15:53:26.187 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 3
2022-07-13 15:53:26.187 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 4
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 14122-14134/org.test.tesi4 D/BluetoothGatt: onClientConnParamsChanged() - Device=70:87:9E:0F:F8:7D interval=39 status=0
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 5
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 5
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 5
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 5
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.197 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.207 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 5
2022-07-13 15:53:26.207 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.207 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 5
2022-07-13 15:53:26.207 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.207 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 5
2022-07-13 15:53:26.207 1983-2415/? D/BtGatt.GattService: [gattSrvHandler] msg : 2
2022-07-13 15:53:26.207 14122-14134/org.test.tesi4 D/BluetoothGatt: onSearchComplete() = Device=70:87:9E:0F:F8:7D Status=0
2022-07-13 15:53:26.277 1983-2493/? D/bt_upio: ..proc_btwrite_timeout..
2022-07-13 15:53:26.277 1983-2493/? D/bt_upio: upio_set : pio 0 action 1, polarity 1
2022-07-13 15:53:26.357 14122-14150/org.test.tesi4 I/python: Connected: True
2022-07-13 15:53:26.357 14122-14150/org.test.tesi4 D/BluetoothGatt: cancelOpen() - device: 70:87:9E:0F:F8:7D
2022-07-13 15:53:26.367 1983-2015/? D/BtGatt.GattService: clientDisconnect() - address=70:87:9E:0F:F8:7D, connId=10
2022-07-13 15:53:26.367 1983-2477/? E/bt_btm: btm_ble_get_search_if search_if=4
2022-07-13 15:53:26.367 1983-2417/? D/bt_vendor: op for 7
2022-07-13 15:53:26.367 836-2532/? V/AlarmManager:  remove PendingIntent] PendingIntent{ec8bcc: PendingIntentRecord{83cd4dc com.android.bluetooth broadcastIntent}}
2022-07-13 15:53:26.367 1983-2417/? D/bt_upio: upio_set : pio 0 action 2, polarity 1
2022-07-13 15:53:26.367 1983-2477/? W/bt_btif: bta_gattc_conn_cback() - cif=4 connected=0 conn_id=4 reason=0x0016
2022-07-13 15:53:26.367 1983-2417/? D/bt_upio: upio_start_stop_timer : timer_settime success
2022-07-13 15:53:26.367 1983-2477/? W/bt_btif: bta_gattc_conn_cback() - cif=5 connected=0 conn_id=5 reason=0x0016
2022-07-13 15:53:26.367 1983-2477/? W/bt_btif: bta_gattc_conn_cback() - cif=6 connected=0 conn_id=6 reason=0x0016
2022-07-13 15:53:26.367 1983-2477/? W/bt_btif: bta_gattc_conn_cback() - cif=7 connected=0 conn_id=7 reason=0x0016
2022-07-13 15:53:26.367 1983-2477/? W/bt_btif: bta_gattc_conn_cback() - cif=8 connected=0 conn_id=8 reason=0x0016
2022-07-13 15:53:26.367 1983-2477/? W/bt_btif: bta_gattc_conn_cback() - cif=9 connected=0 conn_id=9 reason=0x0016
2022-07-13 15:53:26.367 1983-2417/? D/bt_upio: upio_set: proc btwrite assertion, buffer: 1, timer_armed 1 1
2022-07-13 15:53:26.367 1983-2477/? W/bt_btif: bta_gattc_conn_cback() - cif=10 connected=0 conn_id=10 reason=0x0016
2022-07-13 15:53:26.367 1983-2477/? E/bt_btif: bta_gattc_mark_bg_conn unable to find the bg connection mask for: 70:87:9e:0f:f8:7d
2022-07-13 15:53:26.367 1983-2204/? D/BtGatt.GattService: onDisconnected() - clientIf=10, connId=10, address=70:87:9E:0F:F8:7D
2022-07-13 15:53:26.367 14122-14157/org.test.tesi4 D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=10 device=70:87:9E:0F:F8:7D
2022-07-13 15:53:26.367 14122-14150/org.test.tesi4 D/BluetoothGatt: close()
2022-07-13 15:53:26.367 14122-14150/org.test.tesi4 D/BluetoothGatt: unregisterApp() - mClientIf=10
2022-07-13 15:53:26.377 1983-2505/? D/BtGatt.GattService: unregisterClient() - clientIf=10
2022-07-13 15:53:26.377 14122-14150/org.test.tesi4 I/python:  Traceback (most recent call last):
2022-07-13 15:53:26.377 14122-14150/org.test.tesi4 I/python:    File "/content/.buildozer/android/app/main.py", line 228, in <module>
2022-07-13 15:53:26.377 836-1510/? V/AlarmManager:  remove PendingIntent] PendingIntent{317de15: PendingIntentRecord{83cd4dc com.android.bluetooth broadcastIntent}}
2022-07-13 15:53:26.377 14122-14150/org.test.tesi4 I/python:    File "/content/.buildozer/android/platform/build-armeabi-v7a/build/other_builds/python3/armeabi-v7a__ndk_target_21/python3/Lib/asyncio/base_events.py", line 616, in run_until_complete
2022-07-13 15:53:26.377 14122-14150/org.test.tesi4 I/python:    File "/content/.buildozer/android/app/main.py", line 216, in get_the_weight_from_the_mi_smart_scale_2
2022-07-13 15:53:26.377 14122-14150/org.test.tesi4 I/python:    File "/content/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/tesi4/armeabi-v7a/bleak/backends/p4android/client.py", line 486, in start_notify
2022-07-13 15:53:26.377 14122-14150/org.test.tesi4 I/python:  bleak.exc.BleakError: Characteristic with UUID 00002a9d-0000-1000-8000-00805f9b34fb could not be found!
2022-07-13 15:53:26.377 14122-14150/org.test.tesi4 I/python: Python for android ended.
2022-07-13 15:53:26.387 1983-2477/? I/bt_btm_sec: btm_sec_disconnected clearing pending flag handle:64 reason:22

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:20

github_iconTop GitHub Comments

1reaction
dlechcommented, Jul 18, 2022

The bug in Bleak needs to be fixed. All characteristics in the dictionary are using the same key which writes over the previous key, so only the last discovered characteristic can be used currently.

If Android doesn’t see the characteristic at all, e.g. with the nRF Connect app, then you need to log Bluetooth packets to see what is going on.

1reaction
dlechcommented, Jul 13, 2022

2022-07-13 18:12:41.390 21906-21935/org.test.tesi6 I/python: {0: <bleak.backends.p4android.characteristic.BleakGATTCharacteristicP4Android object at 0x9a2009e8>}

This shows there is only one characteristic with handle 0 which doesn’t seem right. I think we assumed that getInstanceId() returned the handle, but I think that it just returns a number that is unique per characteristics with the same UUID. That is, it returns 0 for most characteristics and 1 for the second instance of a characteristic with the same UUID as an already seen characteristic.

So, to fix this, I think we need to create a mapping between a tuple containing the UUID and instance id to a “handle” integer value to be compatible with other Bleak backends.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Best practices for unique identifiers - Android Developers
There are some key points to bear in mind, however, when you use this ID: Always respect the user's intention in resetting the...
Read more >
Service | Android Developers
A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise...
Read more >
Services overview | Android Developers
A Service is an application component that can perform long-running operations in the background. It does not provide a user interface.
Read more >
Background Work Overview | Android Developers
Likewise, background work in each of these three categories can be either ... work through WorkManager is the best way to handle tasks...
Read more >
Permissions on Android - Android Developers
The Special app access page in system settings contains a set of user-toggleable operations. Many of these operations are implemented as special permissions....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found