bumble 0.0.207__py3-none-any.whl → 0.0.209__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 (47) hide show
  1. bumble/_version.py +9 -4
  2. bumble/apps/auracast.py +29 -35
  3. bumble/apps/bench.py +13 -10
  4. bumble/apps/console.py +19 -12
  5. bumble/apps/gg_bridge.py +1 -1
  6. bumble/att.py +61 -39
  7. bumble/controller.py +7 -8
  8. bumble/core.py +306 -159
  9. bumble/device.py +127 -82
  10. bumble/gatt.py +25 -228
  11. bumble/gatt_adapters.py +374 -0
  12. bumble/gatt_client.py +38 -31
  13. bumble/gatt_server.py +5 -5
  14. bumble/hci.py +76 -71
  15. bumble/host.py +19 -8
  16. bumble/l2cap.py +2 -2
  17. bumble/link.py +2 -2
  18. bumble/pairing.py +5 -5
  19. bumble/pandora/host.py +19 -23
  20. bumble/pandora/security.py +2 -3
  21. bumble/pandora/utils.py +2 -2
  22. bumble/profiles/aics.py +33 -23
  23. bumble/profiles/ancs.py +514 -0
  24. bumble/profiles/ascs.py +2 -1
  25. bumble/profiles/asha.py +11 -9
  26. bumble/profiles/bass.py +8 -5
  27. bumble/profiles/battery_service.py +13 -3
  28. bumble/profiles/device_information_service.py +16 -14
  29. bumble/profiles/gap.py +12 -8
  30. bumble/profiles/gatt_service.py +1 -0
  31. bumble/profiles/gmap.py +16 -11
  32. bumble/profiles/hap.py +8 -6
  33. bumble/profiles/heart_rate_service.py +20 -4
  34. bumble/profiles/mcp.py +11 -9
  35. bumble/profiles/pacs.py +37 -24
  36. bumble/profiles/tmap.py +6 -4
  37. bumble/profiles/vcs.py +6 -5
  38. bumble/profiles/vocs.py +49 -41
  39. bumble/smp.py +3 -3
  40. bumble/transport/usb.py +1 -3
  41. bumble/utils.py +10 -0
  42. {bumble-0.0.207.dist-info → bumble-0.0.209.dist-info}/METADATA +3 -3
  43. {bumble-0.0.207.dist-info → bumble-0.0.209.dist-info}/RECORD +47 -45
  44. {bumble-0.0.207.dist-info → bumble-0.0.209.dist-info}/WHEEL +1 -1
  45. {bumble-0.0.207.dist-info → bumble-0.0.209.dist-info}/LICENSE +0 -0
  46. {bumble-0.0.207.dist-info → bumble-0.0.209.dist-info}/entry_points.txt +0 -0
  47. {bumble-0.0.207.dist-info → bumble-0.0.209.dist-info}/top_level.txt +0 -0
bumble/device.py CHANGED
@@ -53,14 +53,12 @@ from pyee import EventEmitter
53
53
 
54
54
  from .colors import color
55
55
  from .att import ATT_CID, ATT_DEFAULT_MTU, ATT_PDU
56
- from .gatt import Characteristic, Descriptor, Service
56
+ from .gatt import Attribute, Characteristic, Descriptor, Service
57
57
  from .host import DataPacketQueue, Host
58
58
  from .profiles.gap import GenericAccessService
59
59
  from .core import (
60
60
  BT_BR_EDR_TRANSPORT,
61
- BT_CENTRAL_ROLE,
62
61
  BT_LE_TRANSPORT,
63
- BT_PERIPHERAL_ROLE,
64
62
  AdvertisingData,
65
63
  BaseBumbleError,
66
64
  ConnectionParameterUpdateError,
@@ -1555,13 +1553,13 @@ class IsoPacketStream:
1555
1553
  class Connection(CompositeEventEmitter):
1556
1554
  device: Device
1557
1555
  handle: int
1558
- transport: int
1556
+ transport: core.PhysicalTransport
1559
1557
  self_address: hci.Address
1560
1558
  self_resolvable_address: Optional[hci.Address]
1561
1559
  peer_address: hci.Address
1562
1560
  peer_resolvable_address: Optional[hci.Address]
1563
1561
  peer_le_features: Optional[hci.LeFeatureMask]
1564
- role: int
1562
+ role: hci.Role
1565
1563
  encryption: int
1566
1564
  authenticated: bool
1567
1565
  sc: bool
@@ -1569,8 +1567,8 @@ class Connection(CompositeEventEmitter):
1569
1567
  gatt_client: gatt_client.Client
1570
1568
  pairing_peer_io_capability: Optional[int]
1571
1569
  pairing_peer_authentication_requirements: Optional[int]
1572
- cs_configs: dict[int, ChannelSoundingConfig] = {} # Config ID to Configuration
1573
- cs_procedures: dict[int, ChannelSoundingProcedure] = {} # Config ID to Procedures
1570
+ cs_configs: dict[int, ChannelSoundingConfig] # Config ID to Configuration
1571
+ cs_procedures: dict[int, ChannelSoundingProcedure] # Config ID to Procedures
1574
1572
 
1575
1573
  @composite_listener
1576
1574
  class Listener:
@@ -1586,7 +1584,7 @@ class Connection(CompositeEventEmitter):
1586
1584
  def on_connection_data_length_change(self):
1587
1585
  pass
1588
1586
 
1589
- def on_connection_phy_update(self):
1587
+ def on_connection_phy_update(self, phy):
1590
1588
  pass
1591
1589
 
1592
1590
  def on_connection_phy_update_failure(self, error):
@@ -1612,7 +1610,6 @@ class Connection(CompositeEventEmitter):
1612
1610
  peer_resolvable_address,
1613
1611
  role,
1614
1612
  parameters,
1615
- phy,
1616
1613
  ):
1617
1614
  super().__init__()
1618
1615
  self.device = device
@@ -1629,7 +1626,6 @@ class Connection(CompositeEventEmitter):
1629
1626
  self.authenticated = False
1630
1627
  self.sc = False
1631
1628
  self.link_key_type = None
1632
- self.phy = phy
1633
1629
  self.att_mtu = ATT_DEFAULT_MTU
1634
1630
  self.data_length = DEVICE_DEFAULT_DATA_LENGTH
1635
1631
  self.gatt_client = None # Per-connection client
@@ -1639,6 +1635,8 @@ class Connection(CompositeEventEmitter):
1639
1635
  self.pairing_peer_io_capability = None
1640
1636
  self.pairing_peer_authentication_requirements = None
1641
1637
  self.peer_le_features = None
1638
+ self.cs_configs = {}
1639
+ self.cs_procedures = {}
1642
1640
 
1643
1641
  # [Classic only]
1644
1642
  @classmethod
@@ -1658,7 +1656,6 @@ class Connection(CompositeEventEmitter):
1658
1656
  None,
1659
1657
  role,
1660
1658
  None,
1661
- None,
1662
1659
  )
1663
1660
 
1664
1661
  # [Classic only]
@@ -1675,9 +1672,9 @@ class Connection(CompositeEventEmitter):
1675
1672
  def role_name(self):
1676
1673
  if self.role is None:
1677
1674
  return 'NOT-SET'
1678
- if self.role == BT_CENTRAL_ROLE:
1675
+ if self.role == hci.Role.CENTRAL:
1679
1676
  return 'CENTRAL'
1680
- if self.role == BT_PERIPHERAL_ROLE:
1677
+ if self.role == hci.Role.PERIPHERAL:
1681
1678
  return 'PERIPHERAL'
1682
1679
  return f'UNKNOWN[{self.role}]'
1683
1680
 
@@ -1735,7 +1732,7 @@ class Connection(CompositeEventEmitter):
1735
1732
  async def encrypt(self, enable: bool = True) -> None:
1736
1733
  return await self.device.encrypt(self, enable)
1737
1734
 
1738
- async def switch_role(self, role: int) -> None:
1735
+ async def switch_role(self, role: hci.Role) -> None:
1739
1736
  return await self.device.switch_role(self, role)
1740
1737
 
1741
1738
  async def sustain(self, timeout: Optional[float] = None) -> None:
@@ -1774,12 +1771,12 @@ class Connection(CompositeEventEmitter):
1774
1771
  async def set_phy(self, tx_phys=None, rx_phys=None, phy_options=None):
1775
1772
  return await self.device.set_connection_phy(self, tx_phys, rx_phys, phy_options)
1776
1773
 
1774
+ async def get_phy(self) -> ConnectionPHY:
1775
+ return await self.device.get_connection_phy(self)
1776
+
1777
1777
  async def get_rssi(self):
1778
1778
  return await self.device.get_connection_rssi(self)
1779
1779
 
1780
- async def get_phy(self):
1781
- return await self.device.get_connection_phy(self)
1782
-
1783
1780
  async def transfer_periodic_sync(
1784
1781
  self, sync_handle: int, service_data: int = 0
1785
1782
  ) -> None:
@@ -2049,9 +2046,9 @@ class Device(CompositeEventEmitter):
2049
2046
  legacy_advertiser: Optional[LegacyAdvertiser]
2050
2047
  sco_links: Dict[int, ScoLink]
2051
2048
  cis_links: Dict[int, CisLink]
2052
- bigs = dict[int, Big]()
2053
- bis_links = dict[int, BisLink]()
2054
- big_syncs = dict[int, BigSync]()
2049
+ bigs: dict[int, Big]
2050
+ bis_links: dict[int, BisLink]
2051
+ big_syncs: dict[int, BigSync]
2055
2052
  _pending_cis: Dict[int, tuple[int, int]]
2056
2053
  gatt_service: gatt_service.GenericAttributeProfileService | None = None
2057
2054
 
@@ -2144,6 +2141,9 @@ class Device(CompositeEventEmitter):
2144
2141
  self.sco_links = {} # ScoLinks, by connection handle (BR/EDR only)
2145
2142
  self.cis_links = {} # CisLinks, by connection handle (LE only)
2146
2143
  self._pending_cis = {} # (CIS_ID, CIG_ID), by CIS_handle
2144
+ self.bigs = {}
2145
+ self.bis_links = {}
2146
+ self.big_syncs = {}
2147
2147
  self.classic_enabled = False
2148
2148
  self.inquiry_response = None
2149
2149
  self.address_resolver = None
@@ -2221,7 +2221,7 @@ class Device(CompositeEventEmitter):
2221
2221
  permissions=descriptor["permissions"],
2222
2222
  )
2223
2223
  descriptors.append(new_descriptor)
2224
- new_characteristic = Characteristic(
2224
+ new_characteristic: Characteristic[bytes] = Characteristic(
2225
2225
  uuid=characteristic["uuid"],
2226
2226
  properties=Characteristic.Properties.from_string(
2227
2227
  characteristic["properties"]
@@ -2711,7 +2711,7 @@ class Device(CompositeEventEmitter):
2711
2711
  if phy == hci.HCI_LE_1M_PHY:
2712
2712
  return True
2713
2713
 
2714
- feature_map = {
2714
+ feature_map: dict[int, hci.LeFeatureMask] = {
2715
2715
  hci.HCI_LE_2M_PHY: hci.LeFeatureMask.LE_2M_PHY,
2716
2716
  hci.HCI_LE_CODED_PHY: hci.LeFeatureMask.LE_CODED_PHY,
2717
2717
  }
@@ -2732,7 +2732,7 @@ class Device(CompositeEventEmitter):
2732
2732
  self,
2733
2733
  advertising_type: AdvertisingType = AdvertisingType.UNDIRECTED_CONNECTABLE_SCANNABLE,
2734
2734
  target: Optional[hci.Address] = None,
2735
- own_address_type: int = hci.OwnAddressType.RANDOM,
2735
+ own_address_type: hci.OwnAddressType = hci.OwnAddressType.RANDOM,
2736
2736
  auto_restart: bool = False,
2737
2737
  advertising_data: Optional[bytes] = None,
2738
2738
  scan_response_data: Optional[bytes] = None,
@@ -3013,7 +3013,7 @@ class Device(CompositeEventEmitter):
3013
3013
  active: bool = True,
3014
3014
  scan_interval: float = DEVICE_DEFAULT_SCAN_INTERVAL, # Scan interval in ms
3015
3015
  scan_window: float = DEVICE_DEFAULT_SCAN_WINDOW, # Scan window in ms
3016
- own_address_type: int = hci.OwnAddressType.RANDOM,
3016
+ own_address_type: hci.OwnAddressType = hci.OwnAddressType.RANDOM,
3017
3017
  filter_duplicates: bool = False,
3018
3018
  scanning_phys: Sequence[int] = (hci.HCI_LE_1M_PHY, hci.HCI_LE_CODED_PHY),
3019
3019
  ) -> None:
@@ -3089,7 +3089,7 @@ class Device(CompositeEventEmitter):
3089
3089
  # pylint: disable=line-too-long
3090
3090
  hci.HCI_LE_Set_Scan_Parameters_Command(
3091
3091
  le_scan_type=scan_type,
3092
- le_scan_interval=int(scan_window / 0.625),
3092
+ le_scan_interval=int(scan_interval / 0.625),
3093
3093
  le_scan_window=int(scan_window / 0.625),
3094
3094
  own_address_type=own_address_type,
3095
3095
  scanning_filter_policy=hci.HCI_LE_Set_Scan_Parameters_Command.BASIC_UNFILTERED_POLICY,
@@ -3379,11 +3379,11 @@ class Device(CompositeEventEmitter):
3379
3379
  async def connect(
3380
3380
  self,
3381
3381
  peer_address: Union[hci.Address, str],
3382
- transport: int = BT_LE_TRANSPORT,
3382
+ transport: core.PhysicalTransport = BT_LE_TRANSPORT,
3383
3383
  connection_parameters_preferences: Optional[
3384
- Dict[int, ConnectionParametersPreferences]
3384
+ dict[hci.Phy, ConnectionParametersPreferences]
3385
3385
  ] = None,
3386
- own_address_type: int = hci.OwnAddressType.RANDOM,
3386
+ own_address_type: hci.OwnAddressType = hci.OwnAddressType.RANDOM,
3387
3387
  timeout: Optional[float] = DEVICE_DEFAULT_CONNECT_TIMEOUT,
3388
3388
  always_resolve: bool = False,
3389
3389
  ) -> Connection:
@@ -3431,6 +3431,7 @@ class Device(CompositeEventEmitter):
3431
3431
  # Check parameters
3432
3432
  if transport not in (BT_LE_TRANSPORT, BT_BR_EDR_TRANSPORT):
3433
3433
  raise InvalidArgumentError('invalid transport')
3434
+ transport = core.PhysicalTransport(transport)
3434
3435
 
3435
3436
  # Adjust the transport automatically if we need to
3436
3437
  if transport == BT_LE_TRANSPORT and not self.le_enabled:
@@ -3626,7 +3627,7 @@ class Device(CompositeEventEmitter):
3626
3627
  else:
3627
3628
  # Save pending connection
3628
3629
  self.pending_connections[peer_address] = Connection.incomplete(
3629
- self, peer_address, BT_CENTRAL_ROLE
3630
+ self, peer_address, hci.Role.CENTRAL
3630
3631
  )
3631
3632
 
3632
3633
  # TODO: allow passing other settings
@@ -3681,7 +3682,7 @@ class Device(CompositeEventEmitter):
3681
3682
  async def accept(
3682
3683
  self,
3683
3684
  peer_address: Union[hci.Address, str] = hci.Address.ANY,
3684
- role: int = BT_PERIPHERAL_ROLE,
3685
+ role: hci.Role = hci.Role.PERIPHERAL,
3685
3686
  timeout: Optional[float] = DEVICE_DEFAULT_CONNECT_TIMEOUT,
3686
3687
  ) -> Connection:
3687
3688
  '''
@@ -3767,12 +3768,12 @@ class Device(CompositeEventEmitter):
3767
3768
  self.on('connection', on_connection)
3768
3769
  self.on('connection_failure', on_connection_failure)
3769
3770
 
3770
- # Save pending connection, with the Peripheral role.
3771
+ # Save pending connection, with the Peripheral hci.role.
3771
3772
  # Even if we requested a role switch in the hci.HCI_Accept_Connection_Request
3772
3773
  # command, this connection is still considered Peripheral until an eventual
3773
3774
  # role change event.
3774
3775
  self.pending_connections[peer_address] = Connection.incomplete(
3775
- self, peer_address, BT_PERIPHERAL_ROLE
3776
+ self, peer_address, hci.Role.PERIPHERAL
3776
3777
  )
3777
3778
 
3778
3779
  try:
@@ -3901,7 +3902,7 @@ class Device(CompositeEventEmitter):
3901
3902
  '''
3902
3903
 
3903
3904
  if use_l2cap:
3904
- if connection.role != BT_PERIPHERAL_ROLE:
3905
+ if connection.role != hci.Role.PERIPHERAL:
3905
3906
  raise InvalidStateError(
3906
3907
  'only peripheral can update connection parameters with l2cap'
3907
3908
  )
@@ -3937,12 +3938,14 @@ class Device(CompositeEventEmitter):
3937
3938
  )
3938
3939
  return result.return_parameters.rssi
3939
3940
 
3940
- async def get_connection_phy(self, connection):
3941
+ async def get_connection_phy(self, connection: Connection) -> ConnectionPHY:
3941
3942
  result = await self.send_command(
3942
3943
  hci.HCI_LE_Read_PHY_Command(connection_handle=connection.handle),
3943
3944
  check_result=True,
3944
3945
  )
3945
- return (result.return_parameters.tx_phy, result.return_parameters.rx_phy)
3946
+ return ConnectionPHY(
3947
+ result.return_parameters.tx_phy, result.return_parameters.rx_phy
3948
+ )
3946
3949
 
3947
3950
  async def set_connection_phy(
3948
3951
  self, connection, tx_phys=None, rx_phys=None, phy_options=None
@@ -4006,13 +4009,12 @@ class Device(CompositeEventEmitter):
4006
4009
  # Create a future to wait for an address to be found
4007
4010
  peer_address = asyncio.get_running_loop().create_future()
4008
4011
 
4009
- def on_peer_found(address, ad_data):
4010
- local_name = ad_data.get(AdvertisingData.COMPLETE_LOCAL_NAME, raw=True)
4011
- if local_name is None:
4012
- local_name = ad_data.get(AdvertisingData.SHORTENED_LOCAL_NAME, raw=True)
4013
- if local_name is not None:
4014
- if local_name.decode('utf-8') == name:
4015
- peer_address.set_result(address)
4012
+ def on_peer_found(address: hci.Address, ad_data: AdvertisingData) -> None:
4013
+ local_name = ad_data.get(
4014
+ AdvertisingData.Type.COMPLETE_LOCAL_NAME
4015
+ ) or ad_data.get(AdvertisingData.Type.SHORTENED_LOCAL_NAME)
4016
+ if local_name == name:
4017
+ peer_address.set_result(address)
4016
4018
 
4017
4019
  listener = None
4018
4020
  was_scanning = self.scanning
@@ -4145,10 +4147,10 @@ class Device(CompositeEventEmitter):
4145
4147
  if keys.ltk:
4146
4148
  return keys.ltk.value
4147
4149
 
4148
- if connection.role == BT_CENTRAL_ROLE and keys.ltk_central:
4150
+ if connection.role == hci.Role.CENTRAL and keys.ltk_central:
4149
4151
  return keys.ltk_central.value
4150
4152
 
4151
- if connection.role == BT_PERIPHERAL_ROLE and keys.ltk_peripheral:
4153
+ if connection.role == hci.Role.PERIPHERAL and keys.ltk_peripheral:
4152
4154
  return keys.ltk_peripheral.value
4153
4155
  return None
4154
4156
 
@@ -4300,7 +4302,7 @@ class Device(CompositeEventEmitter):
4300
4302
  self.emit('key_store_update')
4301
4303
 
4302
4304
  # [Classic only]
4303
- async def switch_role(self, connection: Connection, role: int):
4305
+ async def switch_role(self, connection: Connection, role: hci.Role):
4304
4306
  pending_role_change = asyncio.get_running_loop().create_future()
4305
4307
 
4306
4308
  def on_role_change(new_role):
@@ -4920,16 +4922,84 @@ class Device(CompositeEventEmitter):
4920
4922
  self.gatt_service = gatt_service.GenericAttributeProfileService()
4921
4923
  self.gatt_server.add_service(self.gatt_service)
4922
4924
 
4923
- async def notify_subscriber(self, connection, attribute, value=None, force=False):
4925
+ async def notify_subscriber(
4926
+ self,
4927
+ connection: Connection,
4928
+ attribute: Attribute,
4929
+ value: Optional[Any] = None,
4930
+ force: bool = False,
4931
+ ) -> None:
4932
+ """
4933
+ Send a notification to an attribute subscriber.
4934
+
4935
+ Args:
4936
+ connection:
4937
+ The connection of the subscriber.
4938
+ attribute:
4939
+ The attribute whose value is notified.
4940
+ value:
4941
+ The value of the attribute (if None, the value is read from the attribute)
4942
+ force:
4943
+ If True, send a notification even if there is no subscriber.
4944
+ """
4924
4945
  await self.gatt_server.notify_subscriber(connection, attribute, value, force)
4925
4946
 
4926
- async def notify_subscribers(self, attribute, value=None, force=False):
4947
+ async def notify_subscribers(
4948
+ self, attribute: Attribute, value=None, force=False
4949
+ ) -> None:
4950
+ """
4951
+ Send a notification to all the subscribers of an attribute.
4952
+
4953
+ Args:
4954
+ attribute:
4955
+ The attribute whose value is notified.
4956
+ value:
4957
+ The value of the attribute (if None, the value is read from the attribute)
4958
+ force:
4959
+ If True, send a notification for every connection even if there is no
4960
+ subscriber.
4961
+ """
4927
4962
  await self.gatt_server.notify_subscribers(attribute, value, force)
4928
4963
 
4929
- async def indicate_subscriber(self, connection, attribute, value=None, force=False):
4964
+ async def indicate_subscriber(
4965
+ self,
4966
+ connection: Connection,
4967
+ attribute: Attribute,
4968
+ value: Optional[Any] = None,
4969
+ force: bool = False,
4970
+ ):
4971
+ """
4972
+ Send an indication to an attribute subscriber.
4973
+
4974
+ This method returns when the response to the indication has been received.
4975
+
4976
+ Args:
4977
+ connection:
4978
+ The connection of the subscriber.
4979
+ attribute:
4980
+ The attribute whose value is indicated.
4981
+ value:
4982
+ The value of the attribute (if None, the value is read from the attribute)
4983
+ force:
4984
+ If True, send an indication even if there is no subscriber.
4985
+ """
4930
4986
  await self.gatt_server.indicate_subscriber(connection, attribute, value, force)
4931
4987
 
4932
- async def indicate_subscribers(self, attribute, value=None, force=False):
4988
+ async def indicate_subscribers(
4989
+ self, attribute: Attribute, value: Optional[Any] = None, force: bool = False
4990
+ ):
4991
+ """
4992
+ Send an indication to all the subscribers of an attribute.
4993
+
4994
+ Args:
4995
+ attribute:
4996
+ The attribute whose value is notified.
4997
+ value:
4998
+ The value of the attribute (if None, the value is read from the attribute)
4999
+ force:
5000
+ If True, send an indication for every connection even if there is no
5001
+ subscriber.
5002
+ """
4933
5003
  await self.gatt_server.indicate_subscribers(attribute, value, force)
4934
5004
 
4935
5005
  @host_event_handler
@@ -5101,40 +5171,17 @@ class Device(CompositeEventEmitter):
5101
5171
  lambda _: self.abort_on('flush', advertising_set.start()),
5102
5172
  )
5103
5173
 
5104
- self._emit_le_connection(connection)
5105
-
5106
- def _emit_le_connection(self, connection: Connection) -> None:
5107
- # If supported, read which PHY we're connected with before
5108
- # notifying listeners of the new connection.
5109
- if self.host.supports_command(hci.HCI_LE_READ_PHY_COMMAND):
5110
-
5111
- async def read_phy():
5112
- result = await self.send_command(
5113
- hci.HCI_LE_Read_PHY_Command(connection_handle=connection.handle),
5114
- check_result=True,
5115
- )
5116
- connection.phy = ConnectionPHY(
5117
- result.return_parameters.tx_phy, result.return_parameters.rx_phy
5118
- )
5119
- # Emit an event to notify listeners of the new connection
5120
- self.emit('connection', connection)
5121
-
5122
- # Do so asynchronously to not block the current event handler
5123
- connection.abort_on('disconnection', read_phy())
5124
-
5125
- return
5126
-
5127
5174
  self.emit('connection', connection)
5128
5175
 
5129
5176
  @host_event_handler
5130
5177
  def on_connection(
5131
5178
  self,
5132
5179
  connection_handle: int,
5133
- transport: int,
5180
+ transport: core.PhysicalTransport,
5134
5181
  peer_address: hci.Address,
5135
5182
  self_resolvable_address: Optional[hci.Address],
5136
5183
  peer_resolvable_address: Optional[hci.Address],
5137
- role: int,
5184
+ role: hci.Role,
5138
5185
  connection_parameters: ConnectionParameters,
5139
5186
  ) -> None:
5140
5187
  # Convert all-zeros addresses into None.
@@ -5177,7 +5224,7 @@ class Device(CompositeEventEmitter):
5177
5224
  peer_address = resolved_address
5178
5225
 
5179
5226
  self_address = None
5180
- own_address_type: Optional[int] = None
5227
+ own_address_type: Optional[hci.OwnAddressType] = None
5181
5228
  if role == hci.HCI_CENTRAL_ROLE:
5182
5229
  own_address_type = self.connect_own_address_type
5183
5230
  assert own_address_type is not None
@@ -5222,7 +5269,6 @@ class Device(CompositeEventEmitter):
5222
5269
  peer_resolvable_address,
5223
5270
  role,
5224
5271
  connection_parameters,
5225
- ConnectionPHY(hci.HCI_LE_1M_PHY, hci.HCI_LE_1M_PHY),
5226
5272
  )
5227
5273
  self.connections[connection_handle] = connection
5228
5274
 
@@ -5238,7 +5284,7 @@ class Device(CompositeEventEmitter):
5238
5284
 
5239
5285
  if role == hci.HCI_CENTRAL_ROLE or not self.supports_le_extended_advertising:
5240
5286
  # We can emit now, we have all the info we need
5241
- self._emit_le_connection(connection)
5287
+ self.emit('connection', connection)
5242
5288
  return
5243
5289
 
5244
5290
  if role == hci.HCI_PERIPHERAL_ROLE and self.supports_le_extended_advertising:
@@ -5306,7 +5352,7 @@ class Device(CompositeEventEmitter):
5306
5352
  elif self.classic_accept_any:
5307
5353
  # Save pending connection
5308
5354
  self.pending_connections[bd_addr] = Connection.incomplete(
5309
- self, bd_addr, BT_PERIPHERAL_ROLE
5355
+ self, bd_addr, hci.Role.PERIPHERAL
5310
5356
  )
5311
5357
 
5312
5358
  self.host.send_command_sync(
@@ -5792,14 +5838,13 @@ class Device(CompositeEventEmitter):
5792
5838
 
5793
5839
  @host_event_handler
5794
5840
  @with_connection_from_handle
5795
- def on_connection_phy_update(self, connection, connection_phy):
5841
+ def on_connection_phy_update(self, connection, phy):
5796
5842
  logger.debug(
5797
5843
  f'*** Connection PHY Update: [0x{connection.handle:04X}] '
5798
5844
  f'{connection.peer_address} as {connection.role_name}, '
5799
- f'{connection_phy}'
5845
+ f'{phy}'
5800
5846
  )
5801
- connection.phy = connection_phy
5802
- connection.emit('connection_phy_update')
5847
+ connection.emit('connection_phy_update', phy)
5803
5848
 
5804
5849
  @host_event_handler
5805
5850
  @with_connection_from_handle