bleak: Android backend does not give each service/characteristic a unique "handle".
- 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
About this issue
- Original URL
- State: open
- Created 2 years ago
- Comments: 22
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.
This shows there is only one characteristic with handle
0which doesn’t seem right. I think we assumed thatgetInstanceId()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.