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/core.py CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright 2021-2022 Google LLC
1
+ # Copyright 2021-2025 Google LLC
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -16,10 +16,10 @@
16
16
  # Imports
17
17
  # -----------------------------------------------------------------------------
18
18
  from __future__ import annotations
19
- import dataclasses
19
+
20
20
  import enum
21
21
  import struct
22
- from typing import List, Optional, Tuple, Union, cast, Dict
22
+ from typing import cast, overload, Literal, Union, Optional
23
23
  from typing_extensions import Self
24
24
 
25
25
  from bumble.company_ids import COMPANY_IDENTIFIERS
@@ -31,11 +31,12 @@ from bumble.utils import OpenIntEnum
31
31
  # -----------------------------------------------------------------------------
32
32
  # fmt: off
33
33
 
34
- BT_CENTRAL_ROLE = 0
35
- BT_PERIPHERAL_ROLE = 1
34
+ class PhysicalTransport(enum.IntEnum):
35
+ BR_EDR = 0
36
+ LE = 1
36
37
 
37
- BT_BR_EDR_TRANSPORT = 0
38
- BT_LE_TRANSPORT = 1
38
+ BT_BR_EDR_TRANSPORT = PhysicalTransport.BR_EDR
39
+ BT_LE_TRANSPORT = PhysicalTransport.LE
39
40
 
40
41
 
41
42
  # fmt: on
@@ -57,7 +58,7 @@ def bit_flags_to_strings(bits, bit_flag_names):
57
58
  return names
58
59
 
59
60
 
60
- def name_or_number(dictionary: Dict[int, str], number: int, width: int = 2) -> str:
61
+ def name_or_number(dictionary: dict[int, str], number: int, width: int = 2) -> str:
61
62
  name = dictionary.get(number)
62
63
  if name is not None:
63
64
  return name
@@ -200,7 +201,7 @@ class UUID:
200
201
  '''
201
202
 
202
203
  BASE_UUID = bytes.fromhex('00001000800000805F9B34FB')[::-1] # little-endian
203
- UUIDS: List[UUID] = [] # Registry of all instances created
204
+ UUIDS: list[UUID] = [] # Registry of all instances created
204
205
 
205
206
  uuid_bytes: bytes
206
207
  name: Optional[str]
@@ -259,11 +260,11 @@ class UUID:
259
260
  return cls.from_bytes(struct.pack('<I', uuid_32), name)
260
261
 
261
262
  @classmethod
262
- def parse_uuid(cls, uuid_as_bytes: bytes, offset: int) -> Tuple[int, UUID]:
263
+ def parse_uuid(cls, uuid_as_bytes: bytes, offset: int) -> tuple[int, UUID]:
263
264
  return len(uuid_as_bytes), cls.from_bytes(uuid_as_bytes[offset:])
264
265
 
265
266
  @classmethod
266
- def parse_uuid_2(cls, uuid_as_bytes: bytes, offset: int) -> Tuple[int, UUID]:
267
+ def parse_uuid_2(cls, uuid_as_bytes: bytes, offset: int) -> tuple[int, UUID]:
267
268
  return offset + 2, cls.from_bytes(uuid_as_bytes[offset : offset + 2])
268
269
 
269
270
  def to_bytes(self, force_128: bool = False) -> bytes:
@@ -1280,13 +1281,13 @@ class Appearance:
1280
1281
  # Advertising Data
1281
1282
  # -----------------------------------------------------------------------------
1282
1283
  AdvertisingDataObject = Union[
1283
- List[UUID],
1284
- Tuple[UUID, bytes],
1284
+ list[UUID],
1285
+ tuple[UUID, bytes],
1285
1286
  bytes,
1286
1287
  str,
1287
1288
  int,
1288
- Tuple[int, int],
1289
- Tuple[int, bytes],
1289
+ tuple[int, int],
1290
+ tuple[int, bytes],
1290
1291
  Appearance,
1291
1292
  ]
1292
1293
 
@@ -1295,116 +1296,116 @@ class AdvertisingData:
1295
1296
  # fmt: off
1296
1297
  # pylint: disable=line-too-long
1297
1298
 
1298
- FLAGS = 0x01
1299
- INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS = 0x02
1300
- COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS = 0x03
1301
- INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS = 0x04
1302
- COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS = 0x05
1303
- INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS = 0x06
1304
- COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS = 0x07
1305
- SHORTENED_LOCAL_NAME = 0x08
1306
- COMPLETE_LOCAL_NAME = 0x09
1307
- TX_POWER_LEVEL = 0x0A
1308
- CLASS_OF_DEVICE = 0x0D
1309
- SIMPLE_PAIRING_HASH_C = 0x0E
1310
- SIMPLE_PAIRING_HASH_C_192 = 0x0E
1311
- SIMPLE_PAIRING_RANDOMIZER_R = 0x0F
1312
- SIMPLE_PAIRING_RANDOMIZER_R_192 = 0x0F
1313
- DEVICE_ID = 0x10
1314
- SECURITY_MANAGER_TK_VALUE = 0x10
1315
- SECURITY_MANAGER_OUT_OF_BAND_FLAGS = 0x11
1316
- PERIPHERAL_CONNECTION_INTERVAL_RANGE = 0x12
1317
- LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS = 0x14
1318
- LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS = 0x15
1319
- SERVICE_DATA = 0x16
1320
- SERVICE_DATA_16_BIT_UUID = 0x16
1321
- PUBLIC_TARGET_ADDRESS = 0x17
1322
- RANDOM_TARGET_ADDRESS = 0x18
1323
- APPEARANCE = 0x19
1324
- ADVERTISING_INTERVAL = 0x1A
1325
- LE_BLUETOOTH_DEVICE_ADDRESS = 0x1B
1326
- LE_ROLE = 0x1C
1327
- SIMPLE_PAIRING_HASH_C_256 = 0x1D
1328
- SIMPLE_PAIRING_RANDOMIZER_R_256 = 0x1E
1329
- LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS = 0x1F
1330
- SERVICE_DATA_32_BIT_UUID = 0x20
1331
- SERVICE_DATA_128_BIT_UUID = 0x21
1332
- LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE = 0x22
1333
- LE_SECURE_CONNECTIONS_RANDOM_VALUE = 0x23
1334
- URI = 0x24
1335
- INDOOR_POSITIONING = 0x25
1336
- TRANSPORT_DISCOVERY_DATA = 0x26
1337
- LE_SUPPORTED_FEATURES = 0x27
1338
- CHANNEL_MAP_UPDATE_INDICATION = 0x28
1339
- PB_ADV = 0x29
1340
- MESH_MESSAGE = 0x2A
1341
- MESH_BEACON = 0x2B
1342
- BIGINFO = 0x2C
1343
- BROADCAST_CODE = 0x2D
1344
- RESOLVABLE_SET_IDENTIFIER = 0x2E
1345
- ADVERTISING_INTERVAL_LONG = 0x2F
1346
- BROADCAST_NAME = 0x30
1347
- ENCRYPTED_ADVERTISING_DATA = 0X31
1348
- PERIODIC_ADVERTISING_RESPONSE_TIMING_INFORMATION = 0X32
1349
- ELECTRONIC_SHELF_LABEL = 0X34
1350
- THREE_D_INFORMATION_DATA = 0x3D
1351
- MANUFACTURER_SPECIFIC_DATA = 0xFF
1352
-
1353
- AD_TYPE_NAMES = {
1354
- FLAGS: 'FLAGS',
1355
- INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: 'INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS',
1356
- COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: 'COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS',
1357
- INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS: 'INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS',
1358
- COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS: 'COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS',
1359
- INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: 'INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS',
1360
- COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: 'COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS',
1361
- SHORTENED_LOCAL_NAME: 'SHORTENED_LOCAL_NAME',
1362
- COMPLETE_LOCAL_NAME: 'COMPLETE_LOCAL_NAME',
1363
- TX_POWER_LEVEL: 'TX_POWER_LEVEL',
1364
- CLASS_OF_DEVICE: 'CLASS_OF_DEVICE',
1365
- SIMPLE_PAIRING_HASH_C: 'SIMPLE_PAIRING_HASH_C',
1366
- SIMPLE_PAIRING_HASH_C_192: 'SIMPLE_PAIRING_HASH_C_192',
1367
- SIMPLE_PAIRING_RANDOMIZER_R: 'SIMPLE_PAIRING_RANDOMIZER_R',
1368
- SIMPLE_PAIRING_RANDOMIZER_R_192: 'SIMPLE_PAIRING_RANDOMIZER_R_192',
1369
- DEVICE_ID: 'DEVICE_ID',
1370
- SECURITY_MANAGER_TK_VALUE: 'SECURITY_MANAGER_TK_VALUE',
1371
- SECURITY_MANAGER_OUT_OF_BAND_FLAGS: 'SECURITY_MANAGER_OUT_OF_BAND_FLAGS',
1372
- PERIPHERAL_CONNECTION_INTERVAL_RANGE: 'PERIPHERAL_CONNECTION_INTERVAL_RANGE',
1373
- LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS: 'LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS',
1374
- LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS: 'LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS',
1375
- SERVICE_DATA_16_BIT_UUID: 'SERVICE_DATA_16_BIT_UUID',
1376
- PUBLIC_TARGET_ADDRESS: 'PUBLIC_TARGET_ADDRESS',
1377
- RANDOM_TARGET_ADDRESS: 'RANDOM_TARGET_ADDRESS',
1378
- APPEARANCE: 'APPEARANCE',
1379
- ADVERTISING_INTERVAL: 'ADVERTISING_INTERVAL',
1380
- LE_BLUETOOTH_DEVICE_ADDRESS: 'LE_BLUETOOTH_DEVICE_ADDRESS',
1381
- LE_ROLE: 'LE_ROLE',
1382
- SIMPLE_PAIRING_HASH_C_256: 'SIMPLE_PAIRING_HASH_C_256',
1383
- SIMPLE_PAIRING_RANDOMIZER_R_256: 'SIMPLE_PAIRING_RANDOMIZER_R_256',
1384
- LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS: 'LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS',
1385
- SERVICE_DATA_32_BIT_UUID: 'SERVICE_DATA_32_BIT_UUID',
1386
- SERVICE_DATA_128_BIT_UUID: 'SERVICE_DATA_128_BIT_UUID',
1387
- LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE: 'LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE',
1388
- LE_SECURE_CONNECTIONS_RANDOM_VALUE: 'LE_SECURE_CONNECTIONS_RANDOM_VALUE',
1389
- URI: 'URI',
1390
- INDOOR_POSITIONING: 'INDOOR_POSITIONING',
1391
- TRANSPORT_DISCOVERY_DATA: 'TRANSPORT_DISCOVERY_DATA',
1392
- LE_SUPPORTED_FEATURES: 'LE_SUPPORTED_FEATURES',
1393
- CHANNEL_MAP_UPDATE_INDICATION: 'CHANNEL_MAP_UPDATE_INDICATION',
1394
- PB_ADV: 'PB_ADV',
1395
- MESH_MESSAGE: 'MESH_MESSAGE',
1396
- MESH_BEACON: 'MESH_BEACON',
1397
- BIGINFO: 'BIGINFO',
1398
- BROADCAST_CODE: 'BROADCAST_CODE',
1399
- RESOLVABLE_SET_IDENTIFIER: 'RESOLVABLE_SET_IDENTIFIER',
1400
- ADVERTISING_INTERVAL_LONG: 'ADVERTISING_INTERVAL_LONG',
1401
- BROADCAST_NAME: 'BROADCAST_NAME',
1402
- ENCRYPTED_ADVERTISING_DATA: 'ENCRYPTED_ADVERTISING_DATA',
1403
- PERIODIC_ADVERTISING_RESPONSE_TIMING_INFORMATION: 'PERIODIC_ADVERTISING_RESPONSE_TIMING_INFORMATION',
1404
- ELECTRONIC_SHELF_LABEL: 'ELECTRONIC_SHELF_LABEL',
1405
- THREE_D_INFORMATION_DATA: 'THREE_D_INFORMATION_DATA',
1406
- MANUFACTURER_SPECIFIC_DATA: 'MANUFACTURER_SPECIFIC_DATA'
1407
- }
1299
+ class Type(OpenIntEnum):
1300
+ FLAGS = 0x01
1301
+ INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS = 0x02
1302
+ COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS = 0x03
1303
+ INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS = 0x04
1304
+ COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS = 0x05
1305
+ INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS = 0x06
1306
+ COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS = 0x07
1307
+ SHORTENED_LOCAL_NAME = 0x08
1308
+ COMPLETE_LOCAL_NAME = 0x09
1309
+ TX_POWER_LEVEL = 0x0A
1310
+ CLASS_OF_DEVICE = 0x0D
1311
+ SIMPLE_PAIRING_HASH_C = 0x0E
1312
+ SIMPLE_PAIRING_HASH_C_192 = 0x0E
1313
+ SIMPLE_PAIRING_RANDOMIZER_R = 0x0F
1314
+ SIMPLE_PAIRING_RANDOMIZER_R_192 = 0x0F
1315
+ DEVICE_ID = 0x10
1316
+ SECURITY_MANAGER_TK_VALUE = 0x10
1317
+ SECURITY_MANAGER_OUT_OF_BAND_FLAGS = 0x11
1318
+ PERIPHERAL_CONNECTION_INTERVAL_RANGE = 0x12
1319
+ LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS = 0x14
1320
+ LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS = 0x15
1321
+ SERVICE_DATA_16_BIT_UUID = 0x16
1322
+ PUBLIC_TARGET_ADDRESS = 0x17
1323
+ RANDOM_TARGET_ADDRESS = 0x18
1324
+ APPEARANCE = 0x19
1325
+ ADVERTISING_INTERVAL = 0x1A
1326
+ LE_BLUETOOTH_DEVICE_ADDRESS = 0x1B
1327
+ LE_ROLE = 0x1C
1328
+ SIMPLE_PAIRING_HASH_C_256 = 0x1D
1329
+ SIMPLE_PAIRING_RANDOMIZER_R_256 = 0x1E
1330
+ LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS = 0x1F
1331
+ SERVICE_DATA_32_BIT_UUID = 0x20
1332
+ SERVICE_DATA_128_BIT_UUID = 0x21
1333
+ LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE = 0x22
1334
+ LE_SECURE_CONNECTIONS_RANDOM_VALUE = 0x23
1335
+ URI = 0x24
1336
+ INDOOR_POSITIONING = 0x25
1337
+ TRANSPORT_DISCOVERY_DATA = 0x26
1338
+ LE_SUPPORTED_FEATURES = 0x27
1339
+ CHANNEL_MAP_UPDATE_INDICATION = 0x28
1340
+ PB_ADV = 0x29
1341
+ MESH_MESSAGE = 0x2A
1342
+ MESH_BEACON = 0x2B
1343
+ BIGINFO = 0x2C
1344
+ BROADCAST_CODE = 0x2D
1345
+ RESOLVABLE_SET_IDENTIFIER = 0x2E
1346
+ ADVERTISING_INTERVAL_LONG = 0x2F
1347
+ BROADCAST_NAME = 0x30
1348
+ ENCRYPTED_ADVERTISING_DATA = 0x31
1349
+ PERIODIC_ADVERTISING_RESPONSE_TIMING_INFORMATION = 0x32
1350
+ ELECTRONIC_SHELF_LABEL = 0x34
1351
+ THREE_D_INFORMATION_DATA = 0x3D
1352
+ MANUFACTURER_SPECIFIC_DATA = 0xFF
1353
+
1354
+ # For backward-compatibility
1355
+ FLAGS = Type.FLAGS
1356
+ INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS = Type.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS
1357
+ COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS = Type.COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS
1358
+ INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS = Type.INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS
1359
+ COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS = Type.COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS
1360
+ INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS = Type.INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS
1361
+ COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS = Type.COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS
1362
+ SHORTENED_LOCAL_NAME = Type.SHORTENED_LOCAL_NAME
1363
+ COMPLETE_LOCAL_NAME = Type.COMPLETE_LOCAL_NAME
1364
+ TX_POWER_LEVEL = Type.TX_POWER_LEVEL
1365
+ CLASS_OF_DEVICE = Type.CLASS_OF_DEVICE
1366
+ SIMPLE_PAIRING_HASH_C = Type.SIMPLE_PAIRING_HASH_C
1367
+ SIMPLE_PAIRING_HASH_C_192 = Type.SIMPLE_PAIRING_HASH_C_192
1368
+ SIMPLE_PAIRING_RANDOMIZER_R = Type.SIMPLE_PAIRING_RANDOMIZER_R
1369
+ SIMPLE_PAIRING_RANDOMIZER_R_192 = Type.SIMPLE_PAIRING_RANDOMIZER_R_192
1370
+ DEVICE_ID = Type.DEVICE_ID
1371
+ SECURITY_MANAGER_TK_VALUE = Type.SECURITY_MANAGER_TK_VALUE
1372
+ SECURITY_MANAGER_OUT_OF_BAND_FLAGS = Type.SECURITY_MANAGER_OUT_OF_BAND_FLAGS
1373
+ PERIPHERAL_CONNECTION_INTERVAL_RANGE = Type.PERIPHERAL_CONNECTION_INTERVAL_RANGE
1374
+ LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS = Type.LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS
1375
+ LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS = Type.LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS
1376
+ SERVICE_DATA = Type.SERVICE_DATA_16_BIT_UUID
1377
+ SERVICE_DATA_16_BIT_UUID = Type.SERVICE_DATA_16_BIT_UUID
1378
+ PUBLIC_TARGET_ADDRESS = Type.PUBLIC_TARGET_ADDRESS
1379
+ RANDOM_TARGET_ADDRESS = Type.RANDOM_TARGET_ADDRESS
1380
+ APPEARANCE = Type.APPEARANCE
1381
+ ADVERTISING_INTERVAL = Type.ADVERTISING_INTERVAL
1382
+ LE_BLUETOOTH_DEVICE_ADDRESS = Type.LE_BLUETOOTH_DEVICE_ADDRESS
1383
+ LE_ROLE = Type.LE_ROLE
1384
+ SIMPLE_PAIRING_HASH_C_256 = Type.SIMPLE_PAIRING_HASH_C_256
1385
+ SIMPLE_PAIRING_RANDOMIZER_R_256 = Type.SIMPLE_PAIRING_RANDOMIZER_R_256
1386
+ LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS = Type.LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS
1387
+ SERVICE_DATA_32_BIT_UUID = Type.SERVICE_DATA_32_BIT_UUID
1388
+ SERVICE_DATA_128_BIT_UUID = Type.SERVICE_DATA_128_BIT_UUID
1389
+ LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE = Type.LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE
1390
+ LE_SECURE_CONNECTIONS_RANDOM_VALUE = Type.LE_SECURE_CONNECTIONS_RANDOM_VALUE
1391
+ URI = Type.URI
1392
+ INDOOR_POSITIONING = Type.INDOOR_POSITIONING
1393
+ TRANSPORT_DISCOVERY_DATA = Type.TRANSPORT_DISCOVERY_DATA
1394
+ LE_SUPPORTED_FEATURES = Type.LE_SUPPORTED_FEATURES
1395
+ CHANNEL_MAP_UPDATE_INDICATION = Type.CHANNEL_MAP_UPDATE_INDICATION
1396
+ PB_ADV = Type.PB_ADV
1397
+ MESH_MESSAGE = Type.MESH_MESSAGE
1398
+ MESH_BEACON = Type.MESH_BEACON
1399
+ BIGINFO = Type.BIGINFO
1400
+ BROADCAST_CODE = Type.BROADCAST_CODE
1401
+ RESOLVABLE_SET_IDENTIFIER = Type.RESOLVABLE_SET_IDENTIFIER
1402
+ ADVERTISING_INTERVAL_LONG = Type.ADVERTISING_INTERVAL_LONG
1403
+ BROADCAST_NAME = Type.BROADCAST_NAME
1404
+ ENCRYPTED_ADVERTISING_DATA = Type.ENCRYPTED_ADVERTISING_DATA
1405
+ PERIODIC_ADVERTISING_RESPONSE_TIMING_INFORMATION = Type.PERIODIC_ADVERTISING_RESPONSE_TIMING_INFORMATION
1406
+ ELECTRONIC_SHELF_LABEL = Type.ELECTRONIC_SHELF_LABEL
1407
+ THREE_D_INFORMATION_DATA = Type.THREE_D_INFORMATION_DATA
1408
+ MANUFACTURER_SPECIFIC_DATA = Type.MANUFACTURER_SPECIFIC_DATA
1408
1409
 
1409
1410
  LE_LIMITED_DISCOVERABLE_MODE_FLAG = 0x01
1410
1411
  LE_GENERAL_DISCOVERABLE_MODE_FLAG = 0x02
@@ -1412,12 +1413,12 @@ class AdvertisingData:
1412
1413
  BR_EDR_CONTROLLER_FLAG = 0x08
1413
1414
  BR_EDR_HOST_FLAG = 0x10
1414
1415
 
1415
- ad_structures: List[Tuple[int, bytes]]
1416
+ ad_structures: list[tuple[int, bytes]]
1416
1417
 
1417
1418
  # fmt: on
1418
1419
  # pylint: enable=line-too-long
1419
1420
 
1420
- def __init__(self, ad_structures: Optional[List[Tuple[int, bytes]]] = None) -> None:
1421
+ def __init__(self, ad_structures: Optional[list[tuple[int, bytes]]] = None) -> None:
1421
1422
  if ad_structures is None:
1422
1423
  ad_structures = []
1423
1424
  self.ad_structures = ad_structures[:]
@@ -1444,7 +1445,7 @@ class AdvertisingData:
1444
1445
  return ','.join(bit_flags_to_strings(flags, flag_names))
1445
1446
 
1446
1447
  @staticmethod
1447
- def uuid_list_to_objects(ad_data: bytes, uuid_size: int) -> List[UUID]:
1448
+ def uuid_list_to_objects(ad_data: bytes, uuid_size: int) -> list[UUID]:
1448
1449
  uuids = []
1449
1450
  offset = 0
1450
1451
  while (offset + uuid_size) <= len(ad_data):
@@ -1461,8 +1462,8 @@ class AdvertisingData:
1461
1462
  ]
1462
1463
  )
1463
1464
 
1464
- @staticmethod
1465
- def ad_data_to_string(ad_type, ad_data):
1465
+ @classmethod
1466
+ def ad_data_to_string(cls, ad_type: int, ad_data: bytes) -> str:
1466
1467
  if ad_type == AdvertisingData.FLAGS:
1467
1468
  ad_type_str = 'Flags'
1468
1469
  ad_data_str = AdvertisingData.flags_to_string(ad_data[0], short=True)
@@ -1521,72 +1522,72 @@ class AdvertisingData:
1521
1522
  ad_type_str = 'Broadcast Name'
1522
1523
  ad_data_str = ad_data.decode('utf-8')
1523
1524
  else:
1524
- ad_type_str = AdvertisingData.AD_TYPE_NAMES.get(ad_type, f'0x{ad_type:02X}')
1525
+ ad_type_str = AdvertisingData.Type(ad_type).name
1525
1526
  ad_data_str = ad_data.hex()
1526
1527
 
1527
1528
  return f'[{ad_type_str}]: {ad_data_str}'
1528
1529
 
1529
1530
  # pylint: disable=too-many-return-statements
1530
- @staticmethod
1531
- def ad_data_to_object(ad_type: int, ad_data: bytes) -> AdvertisingDataObject:
1531
+ @classmethod
1532
+ def ad_data_to_object(cls, ad_type: int, ad_data: bytes) -> AdvertisingDataObject:
1532
1533
  if ad_type in (
1533
- AdvertisingData.COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
1534
- AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
1535
- AdvertisingData.LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS,
1534
+ AdvertisingData.Type.COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
1535
+ AdvertisingData.Type.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
1536
+ AdvertisingData.Type.LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS,
1536
1537
  ):
1537
1538
  return AdvertisingData.uuid_list_to_objects(ad_data, 2)
1538
1539
 
1539
1540
  if ad_type in (
1540
- AdvertisingData.COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS,
1541
- AdvertisingData.INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS,
1542
- AdvertisingData.LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS,
1541
+ AdvertisingData.Type.COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS,
1542
+ AdvertisingData.Type.INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS,
1543
+ AdvertisingData.Type.LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS,
1543
1544
  ):
1544
1545
  return AdvertisingData.uuid_list_to_objects(ad_data, 4)
1545
1546
 
1546
1547
  if ad_type in (
1547
- AdvertisingData.COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS,
1548
- AdvertisingData.INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS,
1549
- AdvertisingData.LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS,
1548
+ AdvertisingData.Type.COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS,
1549
+ AdvertisingData.Type.INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS,
1550
+ AdvertisingData.Type.LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS,
1550
1551
  ):
1551
1552
  return AdvertisingData.uuid_list_to_objects(ad_data, 16)
1552
1553
 
1553
- if ad_type == AdvertisingData.SERVICE_DATA_16_BIT_UUID:
1554
+ if ad_type == AdvertisingData.Type.SERVICE_DATA_16_BIT_UUID:
1554
1555
  return (UUID.from_bytes(ad_data[:2]), ad_data[2:])
1555
1556
 
1556
- if ad_type == AdvertisingData.SERVICE_DATA_32_BIT_UUID:
1557
+ if ad_type == AdvertisingData.Type.SERVICE_DATA_32_BIT_UUID:
1557
1558
  return (UUID.from_bytes(ad_data[:4]), ad_data[4:])
1558
1559
 
1559
- if ad_type == AdvertisingData.SERVICE_DATA_128_BIT_UUID:
1560
+ if ad_type == AdvertisingData.Type.SERVICE_DATA_128_BIT_UUID:
1560
1561
  return (UUID.from_bytes(ad_data[:16]), ad_data[16:])
1561
1562
 
1562
1563
  if ad_type in (
1563
- AdvertisingData.SHORTENED_LOCAL_NAME,
1564
- AdvertisingData.COMPLETE_LOCAL_NAME,
1565
- AdvertisingData.URI,
1566
- AdvertisingData.BROADCAST_NAME,
1564
+ AdvertisingData.Type.SHORTENED_LOCAL_NAME,
1565
+ AdvertisingData.Type.COMPLETE_LOCAL_NAME,
1566
+ AdvertisingData.Type.URI,
1567
+ AdvertisingData.Type.BROADCAST_NAME,
1567
1568
  ):
1568
1569
  return ad_data.decode("utf-8")
1569
1570
 
1570
- if ad_type in (AdvertisingData.TX_POWER_LEVEL, AdvertisingData.FLAGS):
1571
+ if ad_type in (AdvertisingData.Type.TX_POWER_LEVEL, AdvertisingData.Type.FLAGS):
1571
1572
  return cast(int, struct.unpack('B', ad_data)[0])
1572
1573
 
1573
- if ad_type in (AdvertisingData.ADVERTISING_INTERVAL,):
1574
+ if ad_type in (AdvertisingData.Type.ADVERTISING_INTERVAL,):
1574
1575
  return cast(int, struct.unpack('<H', ad_data)[0])
1575
1576
 
1576
- if ad_type == AdvertisingData.CLASS_OF_DEVICE:
1577
+ if ad_type == AdvertisingData.Type.CLASS_OF_DEVICE:
1577
1578
  return cast(int, struct.unpack('<I', bytes([*ad_data, 0]))[0])
1578
1579
 
1579
- if ad_type == AdvertisingData.PERIPHERAL_CONNECTION_INTERVAL_RANGE:
1580
- return cast(Tuple[int, int], struct.unpack('<HH', ad_data))
1580
+ if ad_type == AdvertisingData.Type.PERIPHERAL_CONNECTION_INTERVAL_RANGE:
1581
+ return cast(tuple[int, int], struct.unpack('<HH', ad_data))
1581
1582
 
1582
- if ad_type == AdvertisingData.MANUFACTURER_SPECIFIC_DATA:
1583
- return (cast(int, struct.unpack_from('<H', ad_data, 0)[0]), ad_data[2:])
1584
-
1585
- if ad_type == AdvertisingData.APPEARANCE:
1583
+ if ad_type == AdvertisingData.Type.APPEARANCE:
1586
1584
  return Appearance.from_int(
1587
1585
  cast(int, struct.unpack_from('<H', ad_data, 0)[0])
1588
1586
  )
1589
1587
 
1588
+ if ad_type == AdvertisingData.Type.MANUFACTURER_SPECIFIC_DATA:
1589
+ return (cast(int, struct.unpack_from('<H', ad_data, 0)[0]), ad_data[2:])
1590
+
1590
1591
  return ad_data
1591
1592
 
1592
1593
  def append(self, data: bytes) -> None:
@@ -1600,7 +1601,80 @@ class AdvertisingData:
1600
1601
  self.ad_structures.append((ad_type, ad_data))
1601
1602
  offset += length
1602
1603
 
1603
- def get_all(self, type_id: int, raw: bool = False) -> List[AdvertisingDataObject]:
1604
+ @overload
1605
+ def get_all(
1606
+ self,
1607
+ type_id: Literal[
1608
+ AdvertisingData.Type.COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
1609
+ AdvertisingData.Type.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
1610
+ AdvertisingData.Type.LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS,
1611
+ AdvertisingData.Type.COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS,
1612
+ AdvertisingData.Type.INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS,
1613
+ AdvertisingData.Type.LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS,
1614
+ AdvertisingData.Type.COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS,
1615
+ AdvertisingData.Type.INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS,
1616
+ AdvertisingData.Type.LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS,
1617
+ ],
1618
+ raw: Literal[False] = False,
1619
+ ) -> list[list[UUID]]: ...
1620
+ @overload
1621
+ def get_all(
1622
+ self,
1623
+ type_id: Literal[
1624
+ AdvertisingData.Type.SERVICE_DATA_16_BIT_UUID,
1625
+ AdvertisingData.Type.SERVICE_DATA_32_BIT_UUID,
1626
+ AdvertisingData.Type.SERVICE_DATA_128_BIT_UUID,
1627
+ ],
1628
+ raw: Literal[False] = False,
1629
+ ) -> list[tuple[UUID, bytes]]: ...
1630
+ @overload
1631
+ def get_all(
1632
+ self,
1633
+ type_id: Literal[
1634
+ AdvertisingData.Type.SHORTENED_LOCAL_NAME,
1635
+ AdvertisingData.Type.COMPLETE_LOCAL_NAME,
1636
+ AdvertisingData.Type.URI,
1637
+ AdvertisingData.Type.BROADCAST_NAME,
1638
+ ],
1639
+ raw: Literal[False] = False,
1640
+ ) -> list[str]: ...
1641
+ @overload
1642
+ def get_all(
1643
+ self,
1644
+ type_id: Literal[
1645
+ AdvertisingData.Type.TX_POWER_LEVEL,
1646
+ AdvertisingData.Type.FLAGS,
1647
+ AdvertisingData.Type.ADVERTISING_INTERVAL,
1648
+ AdvertisingData.Type.CLASS_OF_DEVICE,
1649
+ ],
1650
+ raw: Literal[False] = False,
1651
+ ) -> list[int]: ...
1652
+ @overload
1653
+ def get_all(
1654
+ self,
1655
+ type_id: Literal[AdvertisingData.Type.PERIPHERAL_CONNECTION_INTERVAL_RANGE,],
1656
+ raw: Literal[False] = False,
1657
+ ) -> list[tuple[int, int]]: ...
1658
+ @overload
1659
+ def get_all(
1660
+ self,
1661
+ type_id: Literal[AdvertisingData.Type.MANUFACTURER_SPECIFIC_DATA,],
1662
+ raw: Literal[False] = False,
1663
+ ) -> list[tuple[int, bytes]]: ...
1664
+ @overload
1665
+ def get_all(
1666
+ self,
1667
+ type_id: Literal[AdvertisingData.Type.APPEARANCE,],
1668
+ raw: Literal[False] = False,
1669
+ ) -> list[Appearance]: ...
1670
+ @overload
1671
+ def get_all(self, type_id: int, raw: Literal[True]) -> list[bytes]: ...
1672
+ @overload
1673
+ def get_all(
1674
+ self, type_id: int, raw: bool = False
1675
+ ) -> list[AdvertisingDataObject]: ...
1676
+
1677
+ def get_all(self, type_id: int, raw: bool = False) -> list[AdvertisingDataObject]: # type: ignore[misc]
1604
1678
  '''
1605
1679
  Get Advertising Data Structure(s) with a given type
1606
1680
 
@@ -1612,6 +1686,79 @@ class AdvertisingData:
1612
1686
 
1613
1687
  return [process_ad_data(ad[1]) for ad in self.ad_structures if ad[0] == type_id]
1614
1688
 
1689
+ @overload
1690
+ def get(
1691
+ self,
1692
+ type_id: Literal[
1693
+ AdvertisingData.Type.COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
1694
+ AdvertisingData.Type.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
1695
+ AdvertisingData.Type.LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS,
1696
+ AdvertisingData.Type.COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS,
1697
+ AdvertisingData.Type.INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS,
1698
+ AdvertisingData.Type.LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS,
1699
+ AdvertisingData.Type.COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS,
1700
+ AdvertisingData.Type.INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS,
1701
+ AdvertisingData.Type.LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS,
1702
+ ],
1703
+ raw: Literal[False] = False,
1704
+ ) -> Optional[list[UUID]]: ...
1705
+ @overload
1706
+ def get(
1707
+ self,
1708
+ type_id: Literal[
1709
+ AdvertisingData.Type.SERVICE_DATA_16_BIT_UUID,
1710
+ AdvertisingData.Type.SERVICE_DATA_32_BIT_UUID,
1711
+ AdvertisingData.Type.SERVICE_DATA_128_BIT_UUID,
1712
+ ],
1713
+ raw: Literal[False] = False,
1714
+ ) -> Optional[tuple[UUID, bytes]]: ...
1715
+ @overload
1716
+ def get(
1717
+ self,
1718
+ type_id: Literal[
1719
+ AdvertisingData.Type.SHORTENED_LOCAL_NAME,
1720
+ AdvertisingData.Type.COMPLETE_LOCAL_NAME,
1721
+ AdvertisingData.Type.URI,
1722
+ AdvertisingData.Type.BROADCAST_NAME,
1723
+ ],
1724
+ raw: Literal[False] = False,
1725
+ ) -> Optional[Optional[str]]: ...
1726
+ @overload
1727
+ def get(
1728
+ self,
1729
+ type_id: Literal[
1730
+ AdvertisingData.Type.TX_POWER_LEVEL,
1731
+ AdvertisingData.Type.FLAGS,
1732
+ AdvertisingData.Type.ADVERTISING_INTERVAL,
1733
+ AdvertisingData.Type.CLASS_OF_DEVICE,
1734
+ ],
1735
+ raw: Literal[False] = False,
1736
+ ) -> Optional[int]: ...
1737
+ @overload
1738
+ def get(
1739
+ self,
1740
+ type_id: Literal[AdvertisingData.Type.PERIPHERAL_CONNECTION_INTERVAL_RANGE,],
1741
+ raw: Literal[False] = False,
1742
+ ) -> Optional[tuple[int, int]]: ...
1743
+ @overload
1744
+ def get(
1745
+ self,
1746
+ type_id: Literal[AdvertisingData.Type.MANUFACTURER_SPECIFIC_DATA,],
1747
+ raw: Literal[False] = False,
1748
+ ) -> Optional[tuple[int, bytes]]: ...
1749
+ @overload
1750
+ def get(
1751
+ self,
1752
+ type_id: Literal[AdvertisingData.Type.APPEARANCE,],
1753
+ raw: Literal[False] = False,
1754
+ ) -> Optional[Appearance]: ...
1755
+ @overload
1756
+ def get(self, type_id: int, raw: Literal[True]) -> Optional[bytes]: ...
1757
+ @overload
1758
+ def get(
1759
+ self, type_id: int, raw: bool = False
1760
+ ) -> Optional[AdvertisingDataObject]: ...
1761
+
1615
1762
  def get(self, type_id: int, raw: bool = False) -> Optional[AdvertisingDataObject]:
1616
1763
  '''
1617
1764
  Get Advertising Data Structure(s) with a given type