bumble 0.0.208__py3-none-any.whl → 0.0.210__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bumble/_version.py +2 -2
- bumble/a2dp.py +7 -7
- bumble/apps/auracast.py +37 -29
- bumble/apps/bench.py +9 -7
- bumble/apps/console.py +1 -1
- bumble/apps/lea_unicast/app.py +6 -2
- bumble/apps/pair.py +4 -3
- bumble/apps/player/player.py +3 -3
- bumble/apps/rfcomm_bridge.py +1 -1
- bumble/apps/speaker/speaker.py +4 -2
- bumble/att.py +12 -5
- bumble/avc.py +5 -5
- bumble/avdtp.py +9 -10
- bumble/avrcp.py +18 -19
- bumble/bridge.py +2 -2
- bumble/controller.py +13 -15
- bumble/core.py +61 -60
- bumble/device.py +193 -162
- bumble/drivers/__init__.py +2 -2
- bumble/gap.py +1 -1
- bumble/gatt.py +16 -0
- bumble/gatt_adapters.py +3 -3
- bumble/gatt_client.py +27 -21
- bumble/gatt_server.py +9 -10
- bumble/hci.py +109 -90
- bumble/hfp.py +3 -3
- bumble/hid.py +4 -3
- bumble/host.py +30 -19
- bumble/keys.py +3 -3
- bumble/l2cap.py +21 -19
- bumble/link.py +5 -6
- bumble/pairing.py +3 -3
- bumble/pandora/__init__.py +5 -5
- bumble/pandora/host.py +30 -23
- bumble/pandora/l2cap.py +2 -2
- bumble/pandora/security.py +17 -19
- bumble/pandora/utils.py +2 -2
- bumble/profiles/aics.py +6 -6
- bumble/profiles/ancs.py +513 -0
- bumble/profiles/ascs.py +17 -10
- bumble/profiles/asha.py +5 -5
- bumble/profiles/bass.py +1 -1
- bumble/profiles/csip.py +10 -10
- bumble/profiles/gatt_service.py +12 -12
- bumble/profiles/hap.py +16 -16
- bumble/profiles/mcp.py +26 -24
- bumble/profiles/pacs.py +6 -6
- bumble/profiles/pbp.py +1 -1
- bumble/profiles/vcs.py +6 -4
- bumble/profiles/vocs.py +3 -3
- bumble/rfcomm.py +8 -8
- bumble/sdp.py +1 -1
- bumble/smp.py +39 -33
- bumble/transport/__init__.py +24 -19
- bumble/transport/android_emulator.py +8 -4
- bumble/transport/android_netsim.py +8 -5
- bumble/transport/common.py +5 -1
- bumble/transport/file.py +1 -1
- bumble/transport/hci_socket.py +1 -1
- bumble/transport/pty.py +1 -1
- bumble/transport/pyusb.py +3 -3
- bumble/transport/serial.py +1 -1
- bumble/transport/tcp_client.py +1 -1
- bumble/transport/tcp_server.py +1 -1
- bumble/transport/udp.py +1 -1
- bumble/transport/unix.py +1 -1
- bumble/transport/usb.py +1 -3
- bumble/transport/vhci.py +2 -2
- bumble/transport/ws_client.py +6 -1
- bumble/transport/ws_server.py +1 -1
- bumble/utils.py +89 -76
- {bumble-0.0.208.dist-info → bumble-0.0.210.dist-info}/METADATA +3 -2
- {bumble-0.0.208.dist-info → bumble-0.0.210.dist-info}/RECORD +77 -76
- {bumble-0.0.208.dist-info → bumble-0.0.210.dist-info}/WHEEL +1 -1
- {bumble-0.0.208.dist-info → bumble-0.0.210.dist-info}/entry_points.txt +0 -0
- {bumble-0.0.208.dist-info → bumble-0.0.210.dist-info/licenses}/LICENSE +0 -0
- {bumble-0.0.208.dist-info → bumble-0.0.210.dist-info}/top_level.txt +0 -0
bumble/drivers/__init__.py
CHANGED
|
@@ -25,8 +25,8 @@ import pathlib
|
|
|
25
25
|
import platform
|
|
26
26
|
from typing import Dict, Iterable, Optional, Type, TYPE_CHECKING
|
|
27
27
|
|
|
28
|
-
from . import rtk, intel
|
|
29
|
-
from .common import Driver
|
|
28
|
+
from bumble.drivers import rtk, intel
|
|
29
|
+
from bumble.drivers.common import Driver
|
|
30
30
|
|
|
31
31
|
if TYPE_CHECKING:
|
|
32
32
|
from bumble.host import Host
|
bumble/gap.py
CHANGED
bumble/gatt.py
CHANGED
|
@@ -286,6 +286,22 @@ GATT_ASHA_AUDIO_STATUS_CHARACTERISTIC = UUID('38663f1a-e711-4cac-b641-32
|
|
|
286
286
|
GATT_ASHA_VOLUME_CHARACTERISTIC = UUID('00e4ca9e-ab14-41e4-8823-f9e70c7e91df', 'Volume')
|
|
287
287
|
GATT_ASHA_LE_PSM_OUT_CHARACTERISTIC = UUID('2d410339-82b6-42aa-b34e-e2e01df8cc1a', 'LE_PSM_OUT')
|
|
288
288
|
|
|
289
|
+
# Apple Notification Center Service
|
|
290
|
+
GATT_ANCS_SERVICE = UUID('7905F431-B5CE-4E99-A40F-4B1E122D00D0', 'Apple Notification Center')
|
|
291
|
+
GATT_ANCS_NOTIFICATION_SOURCE_CHARACTERISTIC = UUID('9FBF120D-6301-42D9-8C58-25E699A21DBD', 'Notification Source')
|
|
292
|
+
GATT_ANCS_CONTROL_POINT_CHARACTERISTIC = UUID('69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9', 'Control Point')
|
|
293
|
+
GATT_ANCS_DATA_SOURCE_CHARACTERISTIC = UUID('22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB', 'Data Source')
|
|
294
|
+
|
|
295
|
+
# Apple Media Service
|
|
296
|
+
GATT_AMS_SERVICE = UUID('89D3502B-0F36-433A-8EF4-C502AD55F8DC', 'Apple Media')
|
|
297
|
+
GATT_AMS_REMOTE_COMMAND_CHARACTERISTIC = UUID('9B3C81D8-57B1-4A8A-B8DF-0E56F7CA51C2', 'Remote Command')
|
|
298
|
+
GATT_AMS_ENTITY_UPDATE_CHARACTERISTIC = UUID('2F7CABCE-808D-411F-9A0C-BB92BA96C102', 'Entity Update')
|
|
299
|
+
GATT_AMS_ENTITY_ATTRIBUTE_CHARACTERISTIC = UUID('C6B2F38C-23AB-46D8-A6AB-A3A870BBD5D7', 'Entity Attribute')
|
|
300
|
+
|
|
301
|
+
# Misc Apple Services
|
|
302
|
+
GATT_APPLE_CONTINUITY_SERVICE = UUID('D0611E78-BBB4-4591-A5F8-487910AE4366', 'Apple Continuity')
|
|
303
|
+
GATT_APPLE_NEARBY_SERVICE = UUID('9FA480E0-4967-4542-9390-D343DC5D04AE', 'Apple Nearby')
|
|
304
|
+
|
|
289
305
|
# Misc
|
|
290
306
|
GATT_DEVICE_NAME_CHARACTERISTIC = UUID.from_16_bits(0x2A00, 'Device Name')
|
|
291
307
|
GATT_APPEARANCE_CHARACTERISTIC = UUID.from_16_bits(0x2A01, 'Appearance')
|
bumble/gatt_adapters.py
CHANGED
|
@@ -35,15 +35,15 @@ from typing import (
|
|
|
35
35
|
from bumble.core import InvalidOperationError
|
|
36
36
|
from bumble.gatt import Characteristic
|
|
37
37
|
from bumble.gatt_client import CharacteristicProxy
|
|
38
|
-
from bumble
|
|
38
|
+
from bumble import utils
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
# -----------------------------------------------------------------------------
|
|
42
42
|
# Typing
|
|
43
43
|
# -----------------------------------------------------------------------------
|
|
44
44
|
_T = TypeVar('_T')
|
|
45
|
-
_T2 = TypeVar('_T2', bound=ByteSerializable)
|
|
46
|
-
_T3 = TypeVar('_T3', bound=IntConvertible)
|
|
45
|
+
_T2 = TypeVar('_T2', bound=utils.ByteSerializable)
|
|
46
|
+
_T3 = TypeVar('_T3', bound=utils.IntConvertible)
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
# -----------------------------------------------------------------------------
|
bumble/gatt_client.py
CHANGED
|
@@ -44,11 +44,10 @@ from typing import (
|
|
|
44
44
|
TYPE_CHECKING,
|
|
45
45
|
)
|
|
46
46
|
|
|
47
|
-
from pyee import EventEmitter
|
|
48
47
|
|
|
49
|
-
from .colors import color
|
|
50
|
-
from .hci import HCI_Constant
|
|
51
|
-
from .att import (
|
|
48
|
+
from bumble.colors import color
|
|
49
|
+
from bumble.hci import HCI_Constant
|
|
50
|
+
from bumble.att import (
|
|
52
51
|
ATT_ATTRIBUTE_NOT_FOUND_ERROR,
|
|
53
52
|
ATT_ATTRIBUTE_NOT_LONG_ERROR,
|
|
54
53
|
ATT_CID,
|
|
@@ -69,9 +68,10 @@ from .att import (
|
|
|
69
68
|
ATT_Write_Request,
|
|
70
69
|
ATT_Error,
|
|
71
70
|
)
|
|
72
|
-
from
|
|
73
|
-
from
|
|
74
|
-
from .
|
|
71
|
+
from bumble import utils
|
|
72
|
+
from bumble import core
|
|
73
|
+
from bumble.core import UUID, InvalidStateError
|
|
74
|
+
from bumble.gatt import (
|
|
75
75
|
GATT_CHARACTERISTIC_ATTRIBUTE_TYPE,
|
|
76
76
|
GATT_CLIENT_CHARACTERISTIC_CONFIGURATION_DESCRIPTOR,
|
|
77
77
|
GATT_PRIMARY_SERVICE_ATTRIBUTE_TYPE,
|
|
@@ -117,11 +117,11 @@ def show_services(services: Iterable[ServiceProxy]) -> None:
|
|
|
117
117
|
# -----------------------------------------------------------------------------
|
|
118
118
|
# Proxies
|
|
119
119
|
# -----------------------------------------------------------------------------
|
|
120
|
-
class AttributeProxy(EventEmitter, Generic[_T]):
|
|
120
|
+
class AttributeProxy(utils.EventEmitter, Generic[_T]):
|
|
121
121
|
def __init__(
|
|
122
122
|
self, client: Client, handle: int, end_group_handle: int, attribute_type: UUID
|
|
123
123
|
) -> None:
|
|
124
|
-
EventEmitter.__init__(self)
|
|
124
|
+
utils.EventEmitter.__init__(self)
|
|
125
125
|
self.client = client
|
|
126
126
|
self.handle = handle
|
|
127
127
|
self.end_group_handle = end_group_handle
|
|
@@ -149,7 +149,7 @@ class AttributeProxy(EventEmitter, Generic[_T]):
|
|
|
149
149
|
|
|
150
150
|
class ServiceProxy(AttributeProxy):
|
|
151
151
|
uuid: UUID
|
|
152
|
-
characteristics: List[CharacteristicProxy]
|
|
152
|
+
characteristics: List[CharacteristicProxy[bytes]]
|
|
153
153
|
included_services: List[ServiceProxy]
|
|
154
154
|
|
|
155
155
|
@staticmethod
|
|
@@ -170,14 +170,20 @@ class ServiceProxy(AttributeProxy):
|
|
|
170
170
|
self.uuid = uuid
|
|
171
171
|
self.characteristics = []
|
|
172
172
|
|
|
173
|
-
async def discover_characteristics(
|
|
173
|
+
async def discover_characteristics(
|
|
174
|
+
self, uuids=()
|
|
175
|
+
) -> list[CharacteristicProxy[bytes]]:
|
|
174
176
|
return await self.client.discover_characteristics(uuids, self)
|
|
175
177
|
|
|
176
|
-
def get_characteristics_by_uuid(
|
|
178
|
+
def get_characteristics_by_uuid(
|
|
179
|
+
self, uuid: UUID
|
|
180
|
+
) -> list[CharacteristicProxy[bytes]]:
|
|
177
181
|
"""Get all the characteristics with a specified UUID."""
|
|
178
182
|
return self.client.get_characteristics_by_uuid(uuid, self)
|
|
179
183
|
|
|
180
|
-
def get_required_characteristic_by_uuid(
|
|
184
|
+
def get_required_characteristic_by_uuid(
|
|
185
|
+
self, uuid: UUID
|
|
186
|
+
) -> CharacteristicProxy[bytes]:
|
|
181
187
|
"""
|
|
182
188
|
Get the first characteristic with a specified UUID.
|
|
183
189
|
|
|
@@ -256,7 +262,7 @@ class CharacteristicProxy(AttributeProxy[_T]):
|
|
|
256
262
|
)
|
|
257
263
|
|
|
258
264
|
|
|
259
|
-
class DescriptorProxy(AttributeProxy):
|
|
265
|
+
class DescriptorProxy(AttributeProxy[bytes]):
|
|
260
266
|
def __init__(self, client: Client, handle: int, descriptor_type: UUID) -> None:
|
|
261
267
|
super().__init__(client, handle, 0, descriptor_type)
|
|
262
268
|
|
|
@@ -376,7 +382,7 @@ class Client:
|
|
|
376
382
|
|
|
377
383
|
def get_characteristics_by_uuid(
|
|
378
384
|
self, uuid: UUID, service: Optional[ServiceProxy] = None
|
|
379
|
-
) -> List[CharacteristicProxy]:
|
|
385
|
+
) -> List[CharacteristicProxy[bytes]]:
|
|
380
386
|
services = [service] if service else self.services
|
|
381
387
|
return [
|
|
382
388
|
c
|
|
@@ -628,7 +634,7 @@ class Client:
|
|
|
628
634
|
|
|
629
635
|
async def discover_characteristics(
|
|
630
636
|
self, uuids, service: Optional[ServiceProxy]
|
|
631
|
-
) -> List[CharacteristicProxy]:
|
|
637
|
+
) -> List[CharacteristicProxy[bytes]]:
|
|
632
638
|
'''
|
|
633
639
|
See Vol 3, Part G - 4.6.1 Discover All Characteristics of a Service and 4.6.2
|
|
634
640
|
Discover Characteristics by UUID
|
|
@@ -641,12 +647,12 @@ class Client:
|
|
|
641
647
|
services = [service] if service else self.services
|
|
642
648
|
|
|
643
649
|
# Perform characteristic discovery for each service
|
|
644
|
-
discovered_characteristics: List[CharacteristicProxy] = []
|
|
650
|
+
discovered_characteristics: List[CharacteristicProxy[bytes]] = []
|
|
645
651
|
for service in services:
|
|
646
652
|
starting_handle = service.handle
|
|
647
653
|
ending_handle = service.end_group_handle
|
|
648
654
|
|
|
649
|
-
characteristics: List[CharacteristicProxy] = []
|
|
655
|
+
characteristics: List[CharacteristicProxy[bytes]] = []
|
|
650
656
|
while starting_handle <= ending_handle:
|
|
651
657
|
response = await self.send_request(
|
|
652
658
|
ATT_Read_By_Type_Request(
|
|
@@ -686,7 +692,7 @@ class Client:
|
|
|
686
692
|
|
|
687
693
|
properties, handle = struct.unpack_from('<BH', attribute_value)
|
|
688
694
|
characteristic_uuid = UUID.from_bytes(attribute_value[3:])
|
|
689
|
-
characteristic
|
|
695
|
+
characteristic = CharacteristicProxy[bytes](
|
|
690
696
|
self, handle, 0, characteristic_uuid, properties
|
|
691
697
|
)
|
|
692
698
|
|
|
@@ -779,7 +785,7 @@ class Client:
|
|
|
779
785
|
|
|
780
786
|
return descriptors
|
|
781
787
|
|
|
782
|
-
async def discover_attributes(self) -> List[AttributeProxy]:
|
|
788
|
+
async def discover_attributes(self) -> List[AttributeProxy[bytes]]:
|
|
783
789
|
'''
|
|
784
790
|
Discover all attributes, regardless of type
|
|
785
791
|
'''
|
|
@@ -812,7 +818,7 @@ class Client:
|
|
|
812
818
|
logger.warning(f'bogus handle value: {attribute_handle}')
|
|
813
819
|
return []
|
|
814
820
|
|
|
815
|
-
attribute
|
|
821
|
+
attribute = AttributeProxy[bytes](
|
|
816
822
|
self, attribute_handle, 0, UUID.from_bytes(attribute_uuid)
|
|
817
823
|
)
|
|
818
824
|
attributes.append(attribute)
|
bumble/gatt_server.py
CHANGED
|
@@ -38,7 +38,6 @@ from typing import (
|
|
|
38
38
|
Type,
|
|
39
39
|
TYPE_CHECKING,
|
|
40
40
|
)
|
|
41
|
-
from pyee import EventEmitter
|
|
42
41
|
|
|
43
42
|
from bumble.colors import color
|
|
44
43
|
from bumble.core import UUID
|
|
@@ -83,7 +82,7 @@ from bumble.gatt import (
|
|
|
83
82
|
Descriptor,
|
|
84
83
|
Service,
|
|
85
84
|
)
|
|
86
|
-
from bumble
|
|
85
|
+
from bumble import utils
|
|
87
86
|
|
|
88
87
|
if TYPE_CHECKING:
|
|
89
88
|
from bumble.device import Device, Connection
|
|
@@ -103,7 +102,7 @@ GATT_SERVER_DEFAULT_MAX_MTU = 517
|
|
|
103
102
|
# -----------------------------------------------------------------------------
|
|
104
103
|
# GATT Server
|
|
105
104
|
# -----------------------------------------------------------------------------
|
|
106
|
-
class Server(EventEmitter):
|
|
105
|
+
class Server(utils.EventEmitter):
|
|
107
106
|
attributes: List[Attribute]
|
|
108
107
|
services: List[Service]
|
|
109
108
|
attributes_by_handle: Dict[int, Attribute]
|
|
@@ -662,7 +661,7 @@ class Server(EventEmitter):
|
|
|
662
661
|
|
|
663
662
|
self.send_response(connection, response)
|
|
664
663
|
|
|
665
|
-
@AsyncRunner.run_in_task()
|
|
664
|
+
@utils.AsyncRunner.run_in_task()
|
|
666
665
|
async def on_att_find_by_type_value_request(self, connection, request):
|
|
667
666
|
'''
|
|
668
667
|
See Bluetooth spec Vol 3, Part F - 3.4.3.3 Find By Type Value Request
|
|
@@ -715,7 +714,7 @@ class Server(EventEmitter):
|
|
|
715
714
|
|
|
716
715
|
self.send_response(connection, response)
|
|
717
716
|
|
|
718
|
-
@AsyncRunner.run_in_task()
|
|
717
|
+
@utils.AsyncRunner.run_in_task()
|
|
719
718
|
async def on_att_read_by_type_request(self, connection, request):
|
|
720
719
|
'''
|
|
721
720
|
See Bluetooth spec Vol 3, Part F - 3.4.4.1 Read By Type Request
|
|
@@ -781,7 +780,7 @@ class Server(EventEmitter):
|
|
|
781
780
|
|
|
782
781
|
self.send_response(connection, response)
|
|
783
782
|
|
|
784
|
-
@AsyncRunner.run_in_task()
|
|
783
|
+
@utils.AsyncRunner.run_in_task()
|
|
785
784
|
async def on_att_read_request(self, connection, request):
|
|
786
785
|
'''
|
|
787
786
|
See Bluetooth spec Vol 3, Part F - 3.4.4.3 Read Request
|
|
@@ -807,7 +806,7 @@ class Server(EventEmitter):
|
|
|
807
806
|
)
|
|
808
807
|
self.send_response(connection, response)
|
|
809
808
|
|
|
810
|
-
@AsyncRunner.run_in_task()
|
|
809
|
+
@utils.AsyncRunner.run_in_task()
|
|
811
810
|
async def on_att_read_blob_request(self, connection, request):
|
|
812
811
|
'''
|
|
813
812
|
See Bluetooth spec Vol 3, Part F - 3.4.4.5 Read Blob Request
|
|
@@ -852,7 +851,7 @@ class Server(EventEmitter):
|
|
|
852
851
|
)
|
|
853
852
|
self.send_response(connection, response)
|
|
854
853
|
|
|
855
|
-
@AsyncRunner.run_in_task()
|
|
854
|
+
@utils.AsyncRunner.run_in_task()
|
|
856
855
|
async def on_att_read_by_group_type_request(self, connection, request):
|
|
857
856
|
'''
|
|
858
857
|
See Bluetooth spec Vol 3, Part F - 3.4.4.9 Read by Group Type Request
|
|
@@ -920,7 +919,7 @@ class Server(EventEmitter):
|
|
|
920
919
|
|
|
921
920
|
self.send_response(connection, response)
|
|
922
921
|
|
|
923
|
-
@AsyncRunner.run_in_task()
|
|
922
|
+
@utils.AsyncRunner.run_in_task()
|
|
924
923
|
async def on_att_write_request(self, connection, request):
|
|
925
924
|
'''
|
|
926
925
|
See Bluetooth spec Vol 3, Part F - 3.4.5.1 Write Request
|
|
@@ -967,7 +966,7 @@ class Server(EventEmitter):
|
|
|
967
966
|
response = ATT_Write_Response()
|
|
968
967
|
self.send_response(connection, response)
|
|
969
968
|
|
|
970
|
-
@AsyncRunner.run_in_task()
|
|
969
|
+
@utils.AsyncRunner.run_in_task()
|
|
971
970
|
async def on_att_write_command(self, connection, request):
|
|
972
971
|
'''
|
|
973
972
|
See Bluetooth spec Vol 3, Part F - 3.4.5.3 Write Command
|