11import logging
2+ import asyncio
23from typing import Optional , Any
4+ from uuid import UUID
5+
36from typing_extensions import override
47
58from _bleio import set_adapter
1518logger = logging .getLogger (__name__ )
1619logger .setLevel (logging .DEBUG )
1720
21+
1822class BleakClientCircuitPython (BaseBleakClient ):
1923 def __init__ (
2024 self ,
@@ -26,6 +30,7 @@ def __init__(
2630 _adapter = kwargs .get ("adapter" )
2731 if _adapter is not None :
2832 set_adapter (_adapter )
33+ self ._timeout = 10
2934
3035 self ._radio : Optional [BLERadio ] = None
3136 self ._advertisement : Optional [Advertisement ] = None
@@ -40,22 +45,13 @@ def __init__(
4045
4146 @override
4247 async def connect (self , pair , dangerous_use_bleak_cache = False , ** kwargs ):
43- logger .debug ("Attempting to connect BLE device @ {}" .format (self .address ))
44-
45- if self .is_connected :
46- raise BleakError ("Client is already connected" )
4748
4849 if not self ._advertisement .connectable :
4950 raise BleakError ("Device is not connectable" )
5051
51- if pair :
52- raise NotImplementedError ("Not yet implemented" )
53-
5452 timeout = kwargs .get ("timeout" , self ._timeout )
5553
5654 if self ._advertisement is None :
57- logger .debug ("Attempting to find BLE device @ {}" .format (self .address ))
58-
5955 device = await BleakScanner .find_device_by_address (
6056 self .address , timeout = timeout , backend = BleakScannerCircuitPython
6157 )
@@ -69,21 +65,21 @@ async def connect(self, pair, dangerous_use_bleak_cache=False, **kwargs):
6965 if self ._radio is None :
7066 self ._radio = BLERadio ()
7167
72- # TODO: disconnect_callback ?
73-
7468 logger .debug ("Connecting to BLE device @ {}" .format (self .address ))
7569
76- # TODO: wrap async
77- self ._connection = self ._radio .connect (self ._advertisement .address , timeout = timeout )
70+ self ._connection = await asyncio .create_task (self ._connect_task ())
71+ if not self .is_connected :
72+ raise BleakError ("Device is not connected" )
73+
7874 logger .debug ("Connected to BLE device @ {}" .format (self .address ))
7975
8076 logger .debug ("Retrieving services from BLE device @ {}" .format (self .address ))
8177
82- # TODO: get services
83-
78+ # TODO: отримати сервіси, обгорнувши синхронний виклик у asyncio.to_thread
79+ discovered_services_tuple = await asyncio .create_task (self ._discover_services_task ())
80+ print (discovered_services_tuple )
8481 logger .debug ("Services retrieved from BLE device @ {}" .format (self .address ))
8582
86-
8783 async def disconnect (self ) -> None :
8884 """Disconnect from the peripheral device"""
8985 logger .debug ("Disconnecting from BLE device @ {}" .format (self .address ))
@@ -95,10 +91,31 @@ async def disconnect(self) -> None:
9591 logger .debug ("Device is not connected @ {}" .format (self .address ))
9692 return
9793
98- # TODO: wrap async
99- self ._connection .disconnect ()
94+ await asyncio .create_task (self ._disconnect_task ())
95+ self ._connection = None
96+
10097 logger .debug ("Device disconnected @ {}" .format (self .address ))
10198
99+ async def _connect_task (self ):
100+ return self ._radio .connect (self ._advertisement .address )
101+
102+ async def _disconnect_task (self ):
103+ """Helper to run the blocking disconnect call."""
104+ if self .is_connected :
105+ self ._connection .disconnect ()
106+
107+ async def _discover_services_task (self ):
108+ if hasattr (self ._connection , "_bleio_connection" ):
109+ bleio_conn = self ._connection ._bleio_connection
110+ if hasattr (bleio_conn , "discover_remote_services" ):
111+ await asyncio .sleep (1.0 )
112+ try :
113+ await asyncio .sleep (1 )
114+ return bleio_conn .discover_remote_services ()
115+ except Exception as e :
116+ raise BleakError (f"Failed to discover remote services: { e } " )
117+ raise BleakError ("Discover remote services not available" )
118+
102119 @property
103120 @override
104121 def is_connected (self ) -> bool :
0 commit comments