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.
Files changed (77) hide show
  1. bumble/_version.py +2 -2
  2. bumble/a2dp.py +7 -7
  3. bumble/apps/auracast.py +37 -29
  4. bumble/apps/bench.py +9 -7
  5. bumble/apps/console.py +1 -1
  6. bumble/apps/lea_unicast/app.py +6 -2
  7. bumble/apps/pair.py +4 -3
  8. bumble/apps/player/player.py +3 -3
  9. bumble/apps/rfcomm_bridge.py +1 -1
  10. bumble/apps/speaker/speaker.py +4 -2
  11. bumble/att.py +12 -5
  12. bumble/avc.py +5 -5
  13. bumble/avdtp.py +9 -10
  14. bumble/avrcp.py +18 -19
  15. bumble/bridge.py +2 -2
  16. bumble/controller.py +13 -15
  17. bumble/core.py +61 -60
  18. bumble/device.py +193 -162
  19. bumble/drivers/__init__.py +2 -2
  20. bumble/gap.py +1 -1
  21. bumble/gatt.py +16 -0
  22. bumble/gatt_adapters.py +3 -3
  23. bumble/gatt_client.py +27 -21
  24. bumble/gatt_server.py +9 -10
  25. bumble/hci.py +109 -90
  26. bumble/hfp.py +3 -3
  27. bumble/hid.py +4 -3
  28. bumble/host.py +30 -19
  29. bumble/keys.py +3 -3
  30. bumble/l2cap.py +21 -19
  31. bumble/link.py +5 -6
  32. bumble/pairing.py +3 -3
  33. bumble/pandora/__init__.py +5 -5
  34. bumble/pandora/host.py +30 -23
  35. bumble/pandora/l2cap.py +2 -2
  36. bumble/pandora/security.py +17 -19
  37. bumble/pandora/utils.py +2 -2
  38. bumble/profiles/aics.py +6 -6
  39. bumble/profiles/ancs.py +513 -0
  40. bumble/profiles/ascs.py +17 -10
  41. bumble/profiles/asha.py +5 -5
  42. bumble/profiles/bass.py +1 -1
  43. bumble/profiles/csip.py +10 -10
  44. bumble/profiles/gatt_service.py +12 -12
  45. bumble/profiles/hap.py +16 -16
  46. bumble/profiles/mcp.py +26 -24
  47. bumble/profiles/pacs.py +6 -6
  48. bumble/profiles/pbp.py +1 -1
  49. bumble/profiles/vcs.py +6 -4
  50. bumble/profiles/vocs.py +3 -3
  51. bumble/rfcomm.py +8 -8
  52. bumble/sdp.py +1 -1
  53. bumble/smp.py +39 -33
  54. bumble/transport/__init__.py +24 -19
  55. bumble/transport/android_emulator.py +8 -4
  56. bumble/transport/android_netsim.py +8 -5
  57. bumble/transport/common.py +5 -1
  58. bumble/transport/file.py +1 -1
  59. bumble/transport/hci_socket.py +1 -1
  60. bumble/transport/pty.py +1 -1
  61. bumble/transport/pyusb.py +3 -3
  62. bumble/transport/serial.py +1 -1
  63. bumble/transport/tcp_client.py +1 -1
  64. bumble/transport/tcp_server.py +1 -1
  65. bumble/transport/udp.py +1 -1
  66. bumble/transport/unix.py +1 -1
  67. bumble/transport/usb.py +1 -3
  68. bumble/transport/vhci.py +2 -2
  69. bumble/transport/ws_client.py +6 -1
  70. bumble/transport/ws_server.py +1 -1
  71. bumble/utils.py +89 -76
  72. {bumble-0.0.208.dist-info → bumble-0.0.210.dist-info}/METADATA +3 -2
  73. {bumble-0.0.208.dist-info → bumble-0.0.210.dist-info}/RECORD +77 -76
  74. {bumble-0.0.208.dist-info → bumble-0.0.210.dist-info}/WHEEL +1 -1
  75. {bumble-0.0.208.dist-info → bumble-0.0.210.dist-info}/entry_points.txt +0 -0
  76. {bumble-0.0.208.dist-info → bumble-0.0.210.dist-info/licenses}/LICENSE +0 -0
  77. {bumble-0.0.208.dist-info → bumble-0.0.210.dist-info}/top_level.txt +0 -0
@@ -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
@@ -18,7 +18,7 @@
18
18
  import logging
19
19
  import struct
20
20
 
21
- from .gatt import (
21
+ from bumble.gatt import (
22
22
  Service,
23
23
  Characteristic,
24
24
  GATT_GENERIC_ACCESS_SERVICE,
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.utils import ByteSerializable, IntConvertible
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 . import core
73
- from .core import UUID, InvalidStateError
74
- from .gatt import (
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(self, uuids=()) -> list[CharacteristicProxy]:
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(self, uuid: UUID) -> list[CharacteristicProxy]:
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(self, uuid: UUID) -> CharacteristicProxy:
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: CharacteristicProxy = CharacteristicProxy(
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: AttributeProxy = AttributeProxy(
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.utils import AsyncRunner
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