bumble 0.0.215__py3-none-any.whl → 0.0.216__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 CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.0.215'
32
- __version_tuple__ = version_tuple = (0, 0, 215)
31
+ __version__ = version = '0.0.216'
32
+ __version_tuple__ = version_tuple = (0, 0, 216)
33
33
 
34
34
  __commit_id__ = commit_id = None
bumble/device.py CHANGED
@@ -2169,10 +2169,12 @@ def with_connection_from_handle(function):
2169
2169
  # Decorator that converts the first argument from a bluetooth address to a connection
2170
2170
  def with_connection_from_address(function):
2171
2171
  @functools.wraps(function)
2172
- def wrapper(self, address: hci.Address, *args, **kwargs):
2173
- for connection in self.connections.values():
2172
+ def wrapper(device: Device, address: hci.Address, *args, **kwargs):
2173
+ if connection := device.pending_connections.get(address):
2174
+ return function(device, connection, address, *args, **kwargs)
2175
+ for connection in device.connections.values():
2174
2176
  if connection.peer_address == address:
2175
- return function(self, connection, *args, **kwargs)
2177
+ return function(device, connection, *args, **kwargs)
2176
2178
  raise ObjectLookupError('no connection for address')
2177
2179
 
2178
2180
  return wrapper
@@ -2182,11 +2184,13 @@ def with_connection_from_address(function):
2182
2184
  # connection
2183
2185
  def try_with_connection_from_address(function):
2184
2186
  @functools.wraps(function)
2185
- def wrapper(self, address, *args, **kwargs):
2186
- for connection in self.connections.values():
2187
+ def wrapper(device: Device, address: hci.Address, *args, **kwargs):
2188
+ if connection := device.pending_connections.get(address):
2189
+ return function(device, connection, address, *args, **kwargs)
2190
+ for connection in device.connections.values():
2187
2191
  if connection.peer_address == address:
2188
- return function(self, connection, address, *args, **kwargs)
2189
- return function(self, None, address, *args, **kwargs)
2192
+ return function(device, connection, address, *args, **kwargs)
2193
+ return function(device, None, address, *args, **kwargs)
2190
2194
 
2191
2195
  return wrapper
2192
2196
 
@@ -2234,7 +2238,7 @@ class Device(utils.CompositeEventEmitter):
2234
2238
  scan_response_data: bytes
2235
2239
  cs_capabilities: ChannelSoundingCapabilities | None = None
2236
2240
  connections: dict[int, Connection]
2237
- connection_roles: dict[hci.Address, hci.Role]
2241
+ pending_connections: dict[hci.Address, Connection]
2238
2242
  classic_pending_accepts: dict[
2239
2243
  hci.Address,
2240
2244
  list[asyncio.Future[Union[Connection, tuple[hci.Address, int, int]]]],
@@ -2356,9 +2360,9 @@ class Device(utils.CompositeEventEmitter):
2356
2360
  self.le_connecting = False
2357
2361
  self.disconnecting = False
2358
2362
  self.connections = {} # Connections, by connection handle
2359
- self.connection_roles = (
2363
+ self.pending_connections = (
2360
2364
  {}
2361
- ) # Local connection roles, by BD address (BR/EDR only)
2365
+ ) # Pending connections, by BD address (BR/EDR only)
2362
2366
  self.sco_links = {} # ScoLinks, by connection handle (BR/EDR only)
2363
2367
  self.cis_links = {} # CisLinks, by connection handle (LE only)
2364
2368
  self._pending_cis = {} # (CIS_ID, CIG_ID), by CIS_handle
@@ -3827,7 +3831,17 @@ class Device(utils.CompositeEventEmitter):
3827
3831
  )
3828
3832
  else:
3829
3833
  # Save pending connection
3830
- self.connection_roles[peer_address] = hci.Role.CENTRAL
3834
+ self.pending_connections[peer_address] = Connection(
3835
+ device=self,
3836
+ handle=0,
3837
+ transport=core.PhysicalTransport.BR_EDR,
3838
+ self_address=self.public_address,
3839
+ self_resolvable_address=None,
3840
+ peer_address=peer_address,
3841
+ peer_resolvable_address=None,
3842
+ role=hci.Role.CENTRAL,
3843
+ parameters=Connection.Parameters(0, 0, 0),
3844
+ )
3831
3845
 
3832
3846
  # TODO: allow passing other settings
3833
3847
  result = await self.send_command(
@@ -3880,7 +3894,7 @@ class Device(utils.CompositeEventEmitter):
3880
3894
  self.le_connecting = False
3881
3895
  self.connect_own_address_type = None
3882
3896
  else:
3883
- self.connection_roles.pop(peer_address, None)
3897
+ self.pending_connections.pop(peer_address, None)
3884
3898
 
3885
3899
  async def accept(
3886
3900
  self,
@@ -3978,7 +3992,17 @@ class Device(utils.CompositeEventEmitter):
3978
3992
  # Even if we requested a role switch in the hci.HCI_Accept_Connection_Request
3979
3993
  # command, this connection is still considered Peripheral until an eventual
3980
3994
  # role change event.
3981
- self.connection_roles[peer_address] = hci.Role.PERIPHERAL
3995
+ self.pending_connections[peer_address] = Connection(
3996
+ device=self,
3997
+ handle=0,
3998
+ transport=core.PhysicalTransport.BR_EDR,
3999
+ self_address=self.public_address,
4000
+ self_resolvable_address=None,
4001
+ peer_address=peer_address,
4002
+ peer_resolvable_address=None,
4003
+ role=hci.Role.PERIPHERAL,
4004
+ parameters=Connection.Parameters(0, 0, 0),
4005
+ )
3982
4006
 
3983
4007
  try:
3984
4008
  # Accept connection request
@@ -3996,7 +4020,7 @@ class Device(utils.CompositeEventEmitter):
3996
4020
  finally:
3997
4021
  self.remove_listener(self.EVENT_CONNECTION, on_connection)
3998
4022
  self.remove_listener(self.EVENT_CONNECTION_FAILURE, on_connection_failure)
3999
- self.connection_roles.pop(peer_address, None)
4023
+ self.pending_connections.pop(peer_address, None)
4000
4024
 
4001
4025
  @asynccontextmanager
4002
4026
  async def connect_as_gatt(self, peer_address: Union[hci.Address, str]):
@@ -5441,29 +5465,27 @@ class Device(utils.CompositeEventEmitter):
5441
5465
  connection_handle: int,
5442
5466
  peer_address: hci.Address,
5443
5467
  ) -> None:
5444
- connection_role = self.connection_roles.pop(peer_address, hci.Role.PERIPHERAL)
5468
+ if connection := self.pending_connections.pop(peer_address, None):
5469
+ connection.handle = connection_handle
5470
+ else:
5471
+ # Create a new connection
5472
+ connection = Connection(
5473
+ device=self,
5474
+ handle=connection_handle,
5475
+ transport=PhysicalTransport.BR_EDR,
5476
+ self_address=self.public_address,
5477
+ self_resolvable_address=None,
5478
+ peer_address=peer_address,
5479
+ peer_resolvable_address=None,
5480
+ role=hci.Role.PERIPHERAL,
5481
+ parameters=Connection.Parameters(0.0, 0, 0.0),
5482
+ )
5445
5483
 
5446
- logger.debug(
5447
- f'*** Connection: [0x{connection_handle:04X}] '
5448
- f'{peer_address} {hci.HCI_Constant.role_name(connection_role)}'
5449
- )
5484
+ logger.debug('*** %s', connection)
5450
5485
  if connection_handle in self.connections:
5451
5486
  logger.warning(
5452
5487
  'new connection reuses the same handle as a previous connection'
5453
5488
  )
5454
-
5455
- # Create a new connection
5456
- connection = Connection(
5457
- device=self,
5458
- handle=connection_handle,
5459
- transport=PhysicalTransport.BR_EDR,
5460
- self_address=self.public_address,
5461
- self_resolvable_address=None,
5462
- peer_address=peer_address,
5463
- peer_resolvable_address=None,
5464
- role=connection_role,
5465
- parameters=Connection.Parameters(0.0, 0, 0.0),
5466
- )
5467
5489
  self.connections[connection_handle] = connection
5468
5490
 
5469
5491
  self.emit(self.EVENT_CONNECTION, connection)
@@ -5618,7 +5640,9 @@ class Device(utils.CompositeEventEmitter):
5618
5640
 
5619
5641
  # FIXME: Explore a delegate-model for BR/EDR wait connection #56.
5620
5642
  @host_event_handler
5621
- def on_connection_request(self, bd_addr, class_of_device, link_type):
5643
+ def on_connection_request(
5644
+ self, bd_addr: hci.Address, class_of_device: int, link_type: int
5645
+ ):
5622
5646
  logger.debug(f'*** Connection request: {bd_addr}')
5623
5647
 
5624
5648
  # Handle SCO request.
@@ -5647,7 +5671,17 @@ class Device(utils.CompositeEventEmitter):
5647
5671
  # device configuration is set to accept any incoming connection
5648
5672
  elif self.classic_accept_any:
5649
5673
  # Save pending connection
5650
- self.connection_roles[bd_addr] = hci.Role.PERIPHERAL
5674
+ self.pending_connections[bd_addr] = Connection(
5675
+ device=self,
5676
+ handle=0,
5677
+ transport=core.PhysicalTransport.BR_EDR,
5678
+ self_address=self.public_address,
5679
+ self_resolvable_address=None,
5680
+ peer_address=bd_addr,
5681
+ peer_resolvable_address=None,
5682
+ role=hci.Role.PERIPHERAL,
5683
+ parameters=Connection.Parameters(0, 0, 0),
5684
+ )
5651
5685
 
5652
5686
  self.host.send_command_sync(
5653
5687
  hci.HCI_Accept_Connection_Request_Command(
@@ -5958,7 +5992,7 @@ class Device(utils.CompositeEventEmitter):
5958
5992
  @host_event_handler
5959
5993
  @try_with_connection_from_address
5960
5994
  def on_remote_name(
5961
- self, connection: Connection, address: hci.Address, remote_name: bytes
5995
+ self, connection: Optional[Connection], address: hci.Address, remote_name: bytes
5962
5996
  ):
5963
5997
  # Try to decode the name
5964
5998
  try:
@@ -5977,7 +6011,7 @@ class Device(utils.CompositeEventEmitter):
5977
6011
  @host_event_handler
5978
6012
  @try_with_connection_from_address
5979
6013
  def on_remote_name_failure(
5980
- self, connection: Connection, address: hci.Address, error: int
6014
+ self, connection: Optional[Connection], address: hci.Address, error: int
5981
6015
  ):
5982
6016
  if connection:
5983
6017
  connection.emit(connection.EVENT_REMOTE_NAME_FAILURE, error)
@@ -6411,19 +6445,22 @@ class Device(utils.CompositeEventEmitter):
6411
6445
  @host_event_handler
6412
6446
  @try_with_connection_from_address
6413
6447
  def on_role_change(
6414
- self, connection: Connection, peer_address: hci.Address, new_role: hci.Role
6448
+ self,
6449
+ connection: Optional[Connection],
6450
+ peer_address: hci.Address,
6451
+ new_role: hci.Role,
6415
6452
  ):
6416
6453
  if connection:
6417
6454
  connection.role = new_role
6418
6455
  connection.emit(connection.EVENT_ROLE_CHANGE, new_role)
6419
6456
  else:
6420
- self.connection_roles[peer_address] = new_role
6457
+ logger.warning("Role change to unknown connection %s", peer_address)
6421
6458
 
6422
6459
  # [Classic only]
6423
6460
  @host_event_handler
6424
6461
  @try_with_connection_from_address
6425
6462
  def on_role_change_failure(
6426
- self, connection: Connection, address: hci.Address, error: int
6463
+ self, connection: Optional[Connection], address: hci.Address, error: int
6427
6464
  ):
6428
6465
  if connection:
6429
6466
  connection.emit(connection.EVENT_ROLE_CHANGE_FAILURE, error)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bumble
3
- Version: 0.0.215
3
+ Version: 0.0.216
4
4
  Summary: Bluetooth Stack for Apps, Emulation, Test and Experimentation
5
5
  Author-email: Google <bumble-dev@google.com>
6
6
  License-Expression: Apache-2.0
@@ -1,5 +1,5 @@
1
1
  bumble/__init__.py,sha256=Q8jkz6rgl95IMAeInQVt_2GLoJl3DcEP2cxtrQ-ho5c,110
2
- bumble/_version.py,sha256=SguWdOraXlfu-EcPyXxkjHQJ1IdMH5Jtv9-nD3eaHQw,708
2
+ bumble/_version.py,sha256=veynzO9___YfPnIypSQv3tYyxNmoE4TBaM2ten8_gK4,708
3
3
  bumble/a2dp.py,sha256=sVo3w6qSsGm7Ttsqu4zeTO_Gfo63a7STTlJnaq8iJ-M,32031
4
4
  bumble/at.py,sha256=u93DzB5Ghrxks_ufuUqoYV2RUSowLNLMDhq_j9GrCBc,3108
5
5
  bumble/att.py,sha256=vS1dUwiuUgNU6PztARg_qPB_olLOWsAxFz6DZGX8zII,33423
@@ -15,7 +15,7 @@ bumble/controller.py,sha256=oIo6_3Y2_lhMPn0MUfEEN8997ry1blzT2rTUQabQwv8,68282
15
15
  bumble/core.py,sha256=QojIUs4nP9qo_r-FWPVxHrCdVSg6CaIzHf6GVPTuu9s,94583
16
16
  bumble/data_types.py,sha256=jLELcRiUcvRc4JcEo6vMO9kZmumZ9WuibFN-AK7ZYbc,32831
17
17
  bumble/decoder.py,sha256=0-VNWZT-u7lvK3qBpAuYT0M6Rz_bMgMi4CjfUXX_6RM,9728
18
- bumble/device.py,sha256=AAOvl06muirnc0RWN884Xfo2mRL60MWYQO-W9gmCRS4,250023
18
+ bumble/device.py,sha256=VDvdXeMhoGTdG3AHuN0-glHDpJKDhSdKVGrauq2kni0,251675
19
19
  bumble/gap.py,sha256=j5mevt__i_fSdIc_B3x7YvCJLeCc7bVq8omRphxwXNw,2144
20
20
  bumble/gatt.py,sha256=dBd-opQVUumlLPGw7EYZM5DF-ssnym3LsxhskAJMhig,34552
21
21
  bumble/gatt_adapters.py,sha256=9uN2uXGIdlvNeSvv3nfwxCEa15uPfm5DVLR5bog_knI,13190
@@ -175,9 +175,9 @@ bumble/vendor/android/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
175
175
  bumble/vendor/android/hci.py,sha256=LcV4_OBpzoLtpSiP2su7F4r3bDrHWxcQPR4OGnMVXDk,10485
176
176
  bumble/vendor/zephyr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
177
177
  bumble/vendor/zephyr/hci.py,sha256=ysct40uIVohaKKLrWjcWo-7YqozU17xGia2dWeHoMoI,3435
178
- bumble-0.0.215.dist-info/licenses/LICENSE,sha256=FvaYh4NRWIGgS_OwoBs5gFgkCmAghZ-DYnIGBZPuw-s,12142
179
- bumble-0.0.215.dist-info/METADATA,sha256=KRRdkhAUhXZLRfsCh4wjIzTpGrkXelFnS0ovbEYnzy8,6155
180
- bumble-0.0.215.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
181
- bumble-0.0.215.dist-info/entry_points.txt,sha256=mX5dzixNMRo4CTAEQqiYTr-JIaWF62TYrRvJOstjjL8,1081
182
- bumble-0.0.215.dist-info/top_level.txt,sha256=tV6JJKaHPYMFiJYiBYFW24PCcfLxTJZdlu6BmH3Cb00,7
183
- bumble-0.0.215.dist-info/RECORD,,
178
+ bumble-0.0.216.dist-info/licenses/LICENSE,sha256=FvaYh4NRWIGgS_OwoBs5gFgkCmAghZ-DYnIGBZPuw-s,12142
179
+ bumble-0.0.216.dist-info/METADATA,sha256=MY056_VlCMC-BwKlWwCW6b29sSrlNeY1_LN4xrfp0pc,6155
180
+ bumble-0.0.216.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
181
+ bumble-0.0.216.dist-info/entry_points.txt,sha256=mX5dzixNMRo4CTAEQqiYTr-JIaWF62TYrRvJOstjjL8,1081
182
+ bumble-0.0.216.dist-info/top_level.txt,sha256=tV6JJKaHPYMFiJYiBYFW24PCcfLxTJZdlu6BmH3Cb00,7
183
+ bumble-0.0.216.dist-info/RECORD,,