bumble 0.0.219__py3-none-any.whl → 0.0.221__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 +5 -5
- bumble/apps/auracast.py +746 -479
- bumble/apps/bench.py +4 -5
- bumble/apps/console.py +5 -10
- bumble/apps/controller_info.py +12 -7
- bumble/apps/controller_loopback.py +1 -2
- bumble/apps/device_info.py +2 -3
- bumble/apps/gatt_dump.py +0 -1
- bumble/apps/lea_unicast/app.py +1 -1
- bumble/apps/pair.py +49 -46
- bumble/apps/pandora_server.py +2 -2
- bumble/apps/player/player.py +10 -12
- bumble/apps/rfcomm_bridge.py +10 -11
- bumble/apps/scan.py +1 -3
- bumble/apps/speaker/speaker.py +3 -4
- bumble/at.py +4 -5
- bumble/att.py +91 -25
- bumble/audio/io.py +8 -6
- bumble/avc.py +1 -2
- bumble/avctp.py +2 -3
- bumble/avdtp.py +53 -57
- bumble/avrcp.py +25 -27
- bumble/codecs.py +15 -15
- bumble/colors.py +7 -8
- bumble/controller.py +1201 -643
- bumble/core.py +41 -49
- bumble/crypto/__init__.py +2 -1
- bumble/crypto/builtin.py +2 -8
- bumble/data_types.py +2 -1
- bumble/decoder.py +2 -3
- bumble/device.py +278 -325
- bumble/drivers/__init__.py +3 -2
- bumble/drivers/intel.py +6 -8
- bumble/drivers/rtk.py +1 -1
- bumble/gatt.py +9 -9
- bumble/gatt_adapters.py +6 -6
- bumble/gatt_client.py +110 -60
- bumble/gatt_server.py +209 -139
- bumble/hci.py +87 -74
- bumble/helpers.py +5 -5
- bumble/hfp.py +27 -26
- bumble/hid.py +9 -9
- bumble/host.py +44 -50
- bumble/keys.py +17 -17
- bumble/l2cap.py +1015 -218
- bumble/link.py +54 -284
- bumble/ll.py +200 -0
- bumble/lmp.py +324 -0
- bumble/pairing.py +14 -15
- bumble/pandora/__init__.py +2 -2
- bumble/pandora/device.py +6 -4
- bumble/pandora/host.py +19 -10
- bumble/pandora/l2cap.py +8 -9
- bumble/pandora/security.py +18 -16
- bumble/pandora/utils.py +4 -4
- bumble/profiles/aics.py +6 -8
- bumble/profiles/ams.py +3 -5
- bumble/profiles/ancs.py +11 -11
- bumble/profiles/ascs.py +5 -5
- bumble/profiles/asha.py +10 -9
- bumble/profiles/bass.py +9 -3
- bumble/profiles/battery_service.py +1 -2
- bumble/profiles/csip.py +9 -10
- bumble/profiles/device_information_service.py +16 -17
- bumble/profiles/gap.py +3 -4
- bumble/profiles/gatt_service.py +0 -1
- bumble/profiles/gmap.py +12 -13
- bumble/profiles/hap.py +3 -3
- bumble/profiles/heart_rate_service.py +7 -8
- bumble/profiles/le_audio.py +1 -1
- bumble/profiles/mcp.py +28 -28
- bumble/profiles/pacs.py +13 -17
- bumble/profiles/pbp.py +16 -0
- bumble/profiles/vcs.py +2 -2
- bumble/profiles/vocs.py +6 -9
- bumble/rfcomm.py +19 -18
- bumble/sdp.py +12 -11
- bumble/smp.py +20 -30
- bumble/snoop.py +12 -5
- bumble/tools/generate_company_id_list.py +1 -1
- bumble/tools/intel_util.py +2 -2
- bumble/tools/rtk_fw_download.py +1 -1
- bumble/tools/rtk_util.py +1 -1
- bumble/transport/__init__.py +1 -2
- bumble/transport/android_emulator.py +2 -3
- bumble/transport/android_netsim.py +49 -40
- bumble/transport/common.py +9 -9
- bumble/transport/file.py +1 -2
- bumble/transport/hci_socket.py +2 -3
- bumble/transport/pty.py +3 -5
- bumble/transport/pyusb.py +8 -5
- bumble/transport/serial.py +1 -2
- bumble/transport/vhci.py +1 -2
- bumble/transport/ws_server.py +2 -3
- bumble/utils.py +23 -14
- bumble/vendor/android/hci.py +4 -2
- {bumble-0.0.219.dist-info → bumble-0.0.221.dist-info}/METADATA +4 -3
- bumble-0.0.221.dist-info/RECORD +185 -0
- bumble-0.0.219.dist-info/RECORD +0 -183
- {bumble-0.0.219.dist-info → bumble-0.0.221.dist-info}/WHEEL +0 -0
- {bumble-0.0.219.dist-info → bumble-0.0.221.dist-info}/entry_points.txt +0 -0
- {bumble-0.0.219.dist-info → bumble-0.0.221.dist-info}/licenses/LICENSE +0 -0
- {bumble-0.0.219.dist-info → bumble-0.0.221.dist-info}/top_level.txt +0 -0
bumble/pandora/utils.py
CHANGED
|
@@ -18,7 +18,8 @@ import contextlib
|
|
|
18
18
|
import functools
|
|
19
19
|
import inspect
|
|
20
20
|
import logging
|
|
21
|
-
from
|
|
21
|
+
from collections.abc import Generator, MutableMapping
|
|
22
|
+
from typing import Any
|
|
22
23
|
|
|
23
24
|
import grpc
|
|
24
25
|
from google.protobuf.message import Message # pytype: disable=pyi-error
|
|
@@ -34,7 +35,7 @@ ADDRESS_TYPES: dict[str, AddressType] = {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
|
|
37
|
-
def address_from_request(request: Message, field:
|
|
38
|
+
def address_from_request(request: Message, field: str | None) -> Address:
|
|
38
39
|
if field is None:
|
|
39
40
|
return Address.ANY
|
|
40
41
|
return Address(bytes(reversed(getattr(request, field))), ADDRESS_TYPES[field])
|
|
@@ -95,8 +96,7 @@ def rpc(func: Any) -> Any:
|
|
|
95
96
|
@functools.wraps(func)
|
|
96
97
|
def gen_wrapper(self: Any, request: Any, context: grpc.ServicerContext) -> Any:
|
|
97
98
|
with exception_to_rpc_error(context):
|
|
98
|
-
|
|
99
|
-
yield v
|
|
99
|
+
yield from func(self, request, context)
|
|
100
100
|
|
|
101
101
|
@functools.wraps(func)
|
|
102
102
|
def wrapper(self: Any, request: Any, context: grpc.ServicerContext) -> Any:
|
bumble/profiles/aics.py
CHANGED
|
@@ -22,7 +22,6 @@ from __future__ import annotations
|
|
|
22
22
|
import logging
|
|
23
23
|
import struct
|
|
24
24
|
from dataclasses import dataclass
|
|
25
|
-
from typing import Optional
|
|
26
25
|
|
|
27
26
|
from bumble import utils
|
|
28
27
|
from bumble.att import ATT_Error
|
|
@@ -129,7 +128,7 @@ class AudioInputState:
|
|
|
129
128
|
mute: Mute = Mute.NOT_MUTED
|
|
130
129
|
gain_mode: GainMode = GainMode.MANUAL
|
|
131
130
|
change_counter: int = 0
|
|
132
|
-
attribute:
|
|
131
|
+
attribute: Attribute | None = None
|
|
133
132
|
|
|
134
133
|
def __bytes__(self) -> bytes:
|
|
135
134
|
return bytes(
|
|
@@ -199,7 +198,6 @@ class AudioInputControlPoint:
|
|
|
199
198
|
gain_settings_properties: GainSettingsProperties
|
|
200
199
|
|
|
201
200
|
async def on_write(self, connection: Connection, value: bytes) -> None:
|
|
202
|
-
|
|
203
201
|
opcode = AudioInputControlPointOpCode(value[0])
|
|
204
202
|
|
|
205
203
|
if opcode == AudioInputControlPointOpCode.SET_GAIN_SETTING:
|
|
@@ -317,7 +315,7 @@ class AudioInputDescription:
|
|
|
317
315
|
'''
|
|
318
316
|
|
|
319
317
|
audio_input_description: str = "Bluetooth"
|
|
320
|
-
attribute:
|
|
318
|
+
attribute: Attribute | None = None
|
|
321
319
|
|
|
322
320
|
def on_read(self, _connection: Connection) -> str:
|
|
323
321
|
return self.audio_input_description
|
|
@@ -340,11 +338,11 @@ class AICSService(TemplateService):
|
|
|
340
338
|
|
|
341
339
|
def __init__(
|
|
342
340
|
self,
|
|
343
|
-
audio_input_state:
|
|
344
|
-
gain_settings_properties:
|
|
341
|
+
audio_input_state: AudioInputState | None = None,
|
|
342
|
+
gain_settings_properties: GainSettingsProperties | None = None,
|
|
345
343
|
audio_input_type: str = "local",
|
|
346
|
-
audio_input_status:
|
|
347
|
-
audio_input_description:
|
|
344
|
+
audio_input_status: AudioInputStatus | None = None,
|
|
345
|
+
audio_input_description: AudioInputDescription | None = None,
|
|
348
346
|
):
|
|
349
347
|
self.audio_input_state = (
|
|
350
348
|
AudioInputState() if audio_input_state is None else audio_input_state
|
bumble/profiles/ams.py
CHANGED
|
@@ -25,7 +25,7 @@ import asyncio
|
|
|
25
25
|
import dataclasses
|
|
26
26
|
import enum
|
|
27
27
|
import logging
|
|
28
|
-
from
|
|
28
|
+
from collections.abc import Iterable
|
|
29
29
|
|
|
30
30
|
from bumble import utils
|
|
31
31
|
from bumble.device import Peer
|
|
@@ -230,7 +230,7 @@ class AmsClient(utils.EventEmitter):
|
|
|
230
230
|
self.supported_commands = set()
|
|
231
231
|
|
|
232
232
|
@classmethod
|
|
233
|
-
async def for_peer(cls, peer: Peer) ->
|
|
233
|
+
async def for_peer(cls, peer: Peer) -> AmsClient | None:
|
|
234
234
|
ams_proxy = await peer.discover_service_and_create_proxy(AmsProxy)
|
|
235
235
|
if ams_proxy is None:
|
|
236
236
|
return None
|
|
@@ -263,9 +263,7 @@ class AmsClient(utils.EventEmitter):
|
|
|
263
263
|
async def observe(
|
|
264
264
|
self,
|
|
265
265
|
entity: EntityId,
|
|
266
|
-
attributes: Iterable[
|
|
267
|
-
Union[PlayerAttributeId, QueueAttributeId, TrackAttributeId]
|
|
268
|
-
],
|
|
266
|
+
attributes: Iterable[PlayerAttributeId | QueueAttributeId | TrackAttributeId],
|
|
269
267
|
) -> None:
|
|
270
268
|
await self._ams_proxy.entity_update.write_value(
|
|
271
269
|
bytes([entity] + list(attributes)), with_response=True
|
bumble/profiles/ancs.py
CHANGED
|
@@ -27,7 +27,7 @@ import datetime
|
|
|
27
27
|
import enum
|
|
28
28
|
import logging
|
|
29
29
|
import struct
|
|
30
|
-
from
|
|
30
|
+
from collections.abc import Sequence
|
|
31
31
|
|
|
32
32
|
from bumble import utils
|
|
33
33
|
from bumble.att import ATT_Error
|
|
@@ -116,7 +116,7 @@ class NotificationAttributeId(utils.OpenIntEnum):
|
|
|
116
116
|
@dataclasses.dataclass
|
|
117
117
|
class NotificationAttribute:
|
|
118
118
|
attribute_id: NotificationAttributeId
|
|
119
|
-
value:
|
|
119
|
+
value: str | int | datetime.datetime
|
|
120
120
|
|
|
121
121
|
|
|
122
122
|
@dataclasses.dataclass
|
|
@@ -242,10 +242,10 @@ class AncsProxy(ProfileServiceProxy):
|
|
|
242
242
|
|
|
243
243
|
|
|
244
244
|
class AncsClient(utils.EventEmitter):
|
|
245
|
-
_expected_response_command_id:
|
|
246
|
-
_expected_response_notification_uid:
|
|
247
|
-
_expected_response_app_identifier:
|
|
248
|
-
_expected_app_identifier:
|
|
245
|
+
_expected_response_command_id: CommandId | None
|
|
246
|
+
_expected_response_notification_uid: int | None
|
|
247
|
+
_expected_response_app_identifier: str | None
|
|
248
|
+
_expected_app_identifier: str | None
|
|
249
249
|
_expected_response_tuples: int
|
|
250
250
|
_response_accumulator: bytes
|
|
251
251
|
|
|
@@ -255,12 +255,12 @@ class AncsClient(utils.EventEmitter):
|
|
|
255
255
|
super().__init__()
|
|
256
256
|
self._ancs_proxy = ancs_proxy
|
|
257
257
|
self._command_semaphore = asyncio.Semaphore()
|
|
258
|
-
self._response:
|
|
258
|
+
self._response: asyncio.Future | None = None
|
|
259
259
|
self._reset_response()
|
|
260
260
|
self._started = False
|
|
261
261
|
|
|
262
262
|
@classmethod
|
|
263
|
-
async def for_peer(cls, peer: Peer) ->
|
|
263
|
+
async def for_peer(cls, peer: Peer) -> AncsClient | None:
|
|
264
264
|
ancs_proxy = await peer.discover_service_and_create_proxy(AncsProxy)
|
|
265
265
|
if ancs_proxy is None:
|
|
266
266
|
return None
|
|
@@ -316,7 +316,7 @@ class AncsClient(utils.EventEmitter):
|
|
|
316
316
|
# Not enough data yet.
|
|
317
317
|
return
|
|
318
318
|
|
|
319
|
-
attributes: list[
|
|
319
|
+
attributes: list[NotificationAttribute | AppAttribute] = []
|
|
320
320
|
|
|
321
321
|
if command_id == CommandId.GET_NOTIFICATION_ATTRIBUTES:
|
|
322
322
|
(notification_uid,) = struct.unpack_from(
|
|
@@ -342,7 +342,7 @@ class AncsClient(utils.EventEmitter):
|
|
|
342
342
|
str_value = attribute_data[3 : 3 + attribute_data_length].decode(
|
|
343
343
|
"utf-8"
|
|
344
344
|
)
|
|
345
|
-
value:
|
|
345
|
+
value: str | int | datetime.datetime
|
|
346
346
|
if attribute_id == NotificationAttributeId.MESSAGE_SIZE:
|
|
347
347
|
value = int(str_value)
|
|
348
348
|
elif attribute_id == NotificationAttributeId.DATE:
|
|
@@ -415,7 +415,7 @@ class AncsClient(utils.EventEmitter):
|
|
|
415
415
|
self,
|
|
416
416
|
notification_uid: int,
|
|
417
417
|
attributes: Sequence[
|
|
418
|
-
|
|
418
|
+
NotificationAttributeId | tuple[NotificationAttributeId, int]
|
|
419
419
|
],
|
|
420
420
|
) -> list[NotificationAttribute]:
|
|
421
421
|
if not self._started:
|
bumble/profiles/ascs.py
CHANGED
|
@@ -24,7 +24,7 @@ import logging
|
|
|
24
24
|
import struct
|
|
25
25
|
from collections.abc import Sequence
|
|
26
26
|
from dataclasses import dataclass, field
|
|
27
|
-
from typing import Any,
|
|
27
|
+
from typing import Any, TypeVar
|
|
28
28
|
|
|
29
29
|
from bumble import colors, device, gatt, gatt_client, hci, utils
|
|
30
30
|
from bumble.profiles import le_audio
|
|
@@ -49,7 +49,7 @@ class ASE_Operation:
|
|
|
49
49
|
classes: dict[int, type[ASE_Operation]] = {}
|
|
50
50
|
op_code: Opcode
|
|
51
51
|
name: str
|
|
52
|
-
fields:
|
|
52
|
+
fields: Sequence[Any] | None = None
|
|
53
53
|
ase_id: Sequence[int]
|
|
54
54
|
|
|
55
55
|
class Opcode(enum.IntEnum):
|
|
@@ -278,7 +278,7 @@ class AseStateMachine(gatt.Characteristic):
|
|
|
278
278
|
|
|
279
279
|
EVENT_STATE_CHANGE = "state_change"
|
|
280
280
|
|
|
281
|
-
cis_link:
|
|
281
|
+
cis_link: device.CisLink | None = None
|
|
282
282
|
|
|
283
283
|
# Additional parameters in CODEC_CONFIGURED State
|
|
284
284
|
preferred_framing = 0 # Unframed PDU supported
|
|
@@ -290,7 +290,7 @@ class AseStateMachine(gatt.Characteristic):
|
|
|
290
290
|
preferred_presentation_delay_min = 0
|
|
291
291
|
preferred_presentation_delay_max = 0
|
|
292
292
|
codec_id = hci.CodingFormat(hci.CodecID.LC3)
|
|
293
|
-
codec_specific_configuration:
|
|
293
|
+
codec_specific_configuration: CodecSpecificConfiguration | bytes = b''
|
|
294
294
|
|
|
295
295
|
# Additional parameters in QOS_CONFIGURED State
|
|
296
296
|
cig_id = 0
|
|
@@ -610,7 +610,7 @@ class AudioStreamControlService(gatt.TemplateService):
|
|
|
610
610
|
|
|
611
611
|
ase_state_machines: dict[int, AseStateMachine]
|
|
612
612
|
ase_control_point: gatt.Characteristic[bytes]
|
|
613
|
-
_active_client:
|
|
613
|
+
_active_client: device.Connection | None = None
|
|
614
614
|
|
|
615
615
|
def __init__(
|
|
616
616
|
self,
|
bumble/profiles/asha.py
CHANGED
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
import enum
|
|
20
20
|
import logging
|
|
21
21
|
import struct
|
|
22
|
-
from
|
|
22
|
+
from collections.abc import Callable
|
|
23
|
+
from typing import Any
|
|
23
24
|
|
|
24
25
|
from bumble import data_types, gatt, gatt_client, l2cap, utils
|
|
25
26
|
from bumble.core import AdvertisingData
|
|
@@ -90,20 +91,20 @@ class AshaService(gatt.TemplateService):
|
|
|
90
91
|
EVENT_DISCONNECTED = "disconnected"
|
|
91
92
|
EVENT_VOLUME_CHANGED = "volume_changed"
|
|
92
93
|
|
|
93
|
-
audio_sink:
|
|
94
|
-
active_codec:
|
|
95
|
-
audio_type:
|
|
96
|
-
volume:
|
|
97
|
-
other_state:
|
|
98
|
-
connection:
|
|
94
|
+
audio_sink: Callable[[bytes], Any] | None
|
|
95
|
+
active_codec: Codec | None = None
|
|
96
|
+
audio_type: AudioType | None = None
|
|
97
|
+
volume: int | None = None
|
|
98
|
+
other_state: int | None = None
|
|
99
|
+
connection: Connection | None = None
|
|
99
100
|
|
|
100
101
|
def __init__(
|
|
101
102
|
self,
|
|
102
103
|
capability: int,
|
|
103
|
-
hisyncid:
|
|
104
|
+
hisyncid: list[int] | bytes,
|
|
104
105
|
device: Device,
|
|
105
106
|
psm: int = 0,
|
|
106
|
-
audio_sink:
|
|
107
|
+
audio_sink: Callable[[bytes], Any] | None = None,
|
|
107
108
|
feature_map: int = FeatureMap.LE_COC_AUDIO_OUTPUT_STREAMING_SUPPORTED,
|
|
108
109
|
protocol_version: int = 0x01,
|
|
109
110
|
render_delay_milliseconds: int = 0,
|
bumble/profiles/bass.py
CHANGED
|
@@ -21,7 +21,8 @@ from __future__ import annotations
|
|
|
21
21
|
import dataclasses
|
|
22
22
|
import logging
|
|
23
23
|
import struct
|
|
24
|
-
from
|
|
24
|
+
from collections.abc import Sequence
|
|
25
|
+
from typing import ClassVar
|
|
25
26
|
|
|
26
27
|
from bumble import core, device, gatt, gatt_adapters, gatt_client, hci, utils
|
|
27
28
|
|
|
@@ -337,7 +338,12 @@ class BroadcastAudioScanService(gatt.TemplateService):
|
|
|
337
338
|
b"12", # TEST
|
|
338
339
|
)
|
|
339
340
|
|
|
340
|
-
super().__init__(
|
|
341
|
+
super().__init__(
|
|
342
|
+
[
|
|
343
|
+
self.broadcast_audio_scan_control_point_characteristic,
|
|
344
|
+
self.broadcast_receive_state_characteristic,
|
|
345
|
+
]
|
|
346
|
+
)
|
|
341
347
|
|
|
342
348
|
def on_broadcast_audio_scan_control_point_write(
|
|
343
349
|
self, connection: device.Connection, value: bytes
|
|
@@ -351,7 +357,7 @@ class BroadcastAudioScanServiceProxy(gatt_client.ProfileServiceProxy):
|
|
|
351
357
|
|
|
352
358
|
broadcast_audio_scan_control_point: gatt_client.CharacteristicProxy[bytes]
|
|
353
359
|
broadcast_receive_states: list[
|
|
354
|
-
gatt_client.CharacteristicProxy[
|
|
360
|
+
gatt_client.CharacteristicProxy[BroadcastReceiveState | None]
|
|
355
361
|
]
|
|
356
362
|
|
|
357
363
|
def __init__(self, service_proxy: gatt_client.ServiceProxy):
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
# -----------------------------------------------------------------------------
|
|
17
17
|
# Imports
|
|
18
18
|
# -----------------------------------------------------------------------------
|
|
19
|
-
from typing import Optional
|
|
20
19
|
|
|
21
20
|
from bumble.gatt import (
|
|
22
21
|
GATT_BATTERY_LEVEL_CHARACTERISTIC,
|
|
@@ -56,7 +55,7 @@ class BatteryService(TemplateService):
|
|
|
56
55
|
class BatteryServiceProxy(ProfileServiceProxy):
|
|
57
56
|
SERVICE_CLASS = BatteryService
|
|
58
57
|
|
|
59
|
-
battery_level:
|
|
58
|
+
battery_level: CharacteristicProxy[int] | None
|
|
60
59
|
|
|
61
60
|
def __init__(self, service_proxy):
|
|
62
61
|
self.service_proxy = service_proxy
|
bumble/profiles/csip.py
CHANGED
|
@@ -20,7 +20,6 @@ from __future__ import annotations
|
|
|
20
20
|
|
|
21
21
|
import enum
|
|
22
22
|
import struct
|
|
23
|
-
from typing import Optional
|
|
24
23
|
|
|
25
24
|
from bumble import core, crypto, device, gatt, gatt_client
|
|
26
25
|
|
|
@@ -96,17 +95,17 @@ class CoordinatedSetIdentificationService(gatt.TemplateService):
|
|
|
96
95
|
|
|
97
96
|
set_identity_resolving_key: bytes
|
|
98
97
|
set_identity_resolving_key_characteristic: gatt.Characteristic[bytes]
|
|
99
|
-
coordinated_set_size_characteristic:
|
|
100
|
-
set_member_lock_characteristic:
|
|
101
|
-
set_member_rank_characteristic:
|
|
98
|
+
coordinated_set_size_characteristic: gatt.Characteristic[bytes] | None = None
|
|
99
|
+
set_member_lock_characteristic: gatt.Characteristic[bytes] | None = None
|
|
100
|
+
set_member_rank_characteristic: gatt.Characteristic[bytes] | None = None
|
|
102
101
|
|
|
103
102
|
def __init__(
|
|
104
103
|
self,
|
|
105
104
|
set_identity_resolving_key: bytes,
|
|
106
105
|
set_identity_resolving_key_type: SirkType,
|
|
107
|
-
coordinated_set_size:
|
|
108
|
-
set_member_lock:
|
|
109
|
-
set_member_rank:
|
|
106
|
+
coordinated_set_size: int | None = None,
|
|
107
|
+
set_member_lock: MemberLock | None = None,
|
|
108
|
+
set_member_rank: int | None = None,
|
|
110
109
|
) -> None:
|
|
111
110
|
if len(set_identity_resolving_key) != SET_IDENTITY_RESOLVING_KEY_LENGTH:
|
|
112
111
|
raise core.InvalidArgumentError(
|
|
@@ -198,9 +197,9 @@ class CoordinatedSetIdentificationProxy(gatt_client.ProfileServiceProxy):
|
|
|
198
197
|
SERVICE_CLASS = CoordinatedSetIdentificationService
|
|
199
198
|
|
|
200
199
|
set_identity_resolving_key: gatt_client.CharacteristicProxy[bytes]
|
|
201
|
-
coordinated_set_size:
|
|
202
|
-
set_member_lock:
|
|
203
|
-
set_member_rank:
|
|
200
|
+
coordinated_set_size: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
201
|
+
set_member_lock: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
202
|
+
set_member_rank: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
204
203
|
|
|
205
204
|
def __init__(self, service_proxy: gatt_client.ServiceProxy) -> None:
|
|
206
205
|
self.service_proxy = service_proxy
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
# Imports
|
|
18
18
|
# -----------------------------------------------------------------------------
|
|
19
19
|
import struct
|
|
20
|
-
from typing import Optional
|
|
21
20
|
|
|
22
21
|
from bumble.gatt import (
|
|
23
22
|
GATT_DEVICE_INFORMATION_SERVICE,
|
|
@@ -54,14 +53,14 @@ class DeviceInformationService(TemplateService):
|
|
|
54
53
|
|
|
55
54
|
def __init__(
|
|
56
55
|
self,
|
|
57
|
-
manufacturer_name:
|
|
58
|
-
model_number:
|
|
59
|
-
serial_number:
|
|
60
|
-
hardware_revision:
|
|
61
|
-
firmware_revision:
|
|
62
|
-
software_revision:
|
|
63
|
-
system_id:
|
|
64
|
-
ieee_regulatory_certification_data_list:
|
|
56
|
+
manufacturer_name: str | None = None,
|
|
57
|
+
model_number: str | None = None,
|
|
58
|
+
serial_number: str | None = None,
|
|
59
|
+
hardware_revision: str | None = None,
|
|
60
|
+
firmware_revision: str | None = None,
|
|
61
|
+
software_revision: str | None = None,
|
|
62
|
+
system_id: tuple[int, int] | None = None, # (OUI, Manufacturer ID)
|
|
63
|
+
ieee_regulatory_certification_data_list: bytes | None = None,
|
|
65
64
|
# TODO: pnp_id
|
|
66
65
|
):
|
|
67
66
|
characteristics: list[Characteristic[bytes]] = [
|
|
@@ -109,14 +108,14 @@ class DeviceInformationService(TemplateService):
|
|
|
109
108
|
class DeviceInformationServiceProxy(ProfileServiceProxy):
|
|
110
109
|
SERVICE_CLASS = DeviceInformationService
|
|
111
110
|
|
|
112
|
-
manufacturer_name:
|
|
113
|
-
model_number:
|
|
114
|
-
serial_number:
|
|
115
|
-
hardware_revision:
|
|
116
|
-
firmware_revision:
|
|
117
|
-
software_revision:
|
|
118
|
-
system_id:
|
|
119
|
-
ieee_regulatory_certification_data_list:
|
|
111
|
+
manufacturer_name: CharacteristicProxy[str] | None
|
|
112
|
+
model_number: CharacteristicProxy[str] | None
|
|
113
|
+
serial_number: CharacteristicProxy[str] | None
|
|
114
|
+
hardware_revision: CharacteristicProxy[str] | None
|
|
115
|
+
firmware_revision: CharacteristicProxy[str] | None
|
|
116
|
+
software_revision: CharacteristicProxy[str] | None
|
|
117
|
+
system_id: CharacteristicProxy[tuple[int, int]] | None
|
|
118
|
+
ieee_regulatory_certification_data_list: CharacteristicProxy[bytes] | None
|
|
120
119
|
|
|
121
120
|
def __init__(self, service_proxy: ServiceProxy):
|
|
122
121
|
self.service_proxy = service_proxy
|
bumble/profiles/gap.py
CHANGED
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
# -----------------------------------------------------------------------------
|
|
20
20
|
import logging
|
|
21
21
|
import struct
|
|
22
|
-
from typing import Optional, Union
|
|
23
22
|
|
|
24
23
|
from bumble.core import Appearance
|
|
25
24
|
from bumble.gatt import (
|
|
@@ -54,7 +53,7 @@ class GenericAccessService(TemplateService):
|
|
|
54
53
|
appearance_characteristic: Characteristic[bytes]
|
|
55
54
|
|
|
56
55
|
def __init__(
|
|
57
|
-
self, device_name: str, appearance:
|
|
56
|
+
self, device_name: str, appearance: Appearance | tuple[int, int] | int = 0
|
|
58
57
|
):
|
|
59
58
|
if isinstance(appearance, int):
|
|
60
59
|
appearance_int = appearance
|
|
@@ -88,8 +87,8 @@ class GenericAccessService(TemplateService):
|
|
|
88
87
|
class GenericAccessServiceProxy(ProfileServiceProxy):
|
|
89
88
|
SERVICE_CLASS = GenericAccessService
|
|
90
89
|
|
|
91
|
-
device_name:
|
|
92
|
-
appearance:
|
|
90
|
+
device_name: CharacteristicProxy[str] | None
|
|
91
|
+
appearance: CharacteristicProxy[Appearance] | None
|
|
93
92
|
|
|
94
93
|
def __init__(self, service_proxy: ServiceProxy):
|
|
95
94
|
self.service_proxy = service_proxy
|
bumble/profiles/gatt_service.py
CHANGED
|
@@ -40,7 +40,6 @@ class GenericAttributeProfileService(gatt.TemplateService):
|
|
|
40
40
|
database_hash_enabled: bool = True,
|
|
41
41
|
service_change_enabled: bool = True,
|
|
42
42
|
) -> None:
|
|
43
|
-
|
|
44
43
|
if server_supported_features is not None:
|
|
45
44
|
self.server_supported_features_characteristic = gatt.Characteristic(
|
|
46
45
|
uuid=gatt.GATT_SERVER_SUPPORTED_FEATURES_CHARACTERISTIC,
|
bumble/profiles/gmap.py
CHANGED
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
# -----------------------------------------------------------------------------
|
|
20
20
|
import struct
|
|
21
21
|
from enum import IntFlag
|
|
22
|
-
from typing import Optional
|
|
23
22
|
|
|
24
23
|
from bumble.gatt import (
|
|
25
24
|
GATT_BGR_FEATURES_CHARACTERISTIC,
|
|
@@ -77,18 +76,18 @@ class GamingAudioService(TemplateService):
|
|
|
77
76
|
UUID = GATT_GAMING_AUDIO_SERVICE
|
|
78
77
|
|
|
79
78
|
gmap_role: Characteristic
|
|
80
|
-
ugg_features:
|
|
81
|
-
ugt_features:
|
|
82
|
-
bgs_features:
|
|
83
|
-
bgr_features:
|
|
79
|
+
ugg_features: Characteristic | None = None
|
|
80
|
+
ugt_features: Characteristic | None = None
|
|
81
|
+
bgs_features: Characteristic | None = None
|
|
82
|
+
bgr_features: Characteristic | None = None
|
|
84
83
|
|
|
85
84
|
def __init__(
|
|
86
85
|
self,
|
|
87
86
|
gmap_role: GmapRole,
|
|
88
|
-
ugg_features:
|
|
89
|
-
ugt_features:
|
|
90
|
-
bgs_features:
|
|
91
|
-
bgr_features:
|
|
87
|
+
ugg_features: UggFeatures | None = None,
|
|
88
|
+
ugt_features: UgtFeatures | None = None,
|
|
89
|
+
bgs_features: BgsFeatures | None = None,
|
|
90
|
+
bgr_features: BgrFeatures | None = None,
|
|
92
91
|
) -> None:
|
|
93
92
|
characteristics = []
|
|
94
93
|
|
|
@@ -150,10 +149,10 @@ class GamingAudioService(TemplateService):
|
|
|
150
149
|
class GamingAudioServiceProxy(ProfileServiceProxy):
|
|
151
150
|
SERVICE_CLASS = GamingAudioService
|
|
152
151
|
|
|
153
|
-
ugg_features:
|
|
154
|
-
ugt_features:
|
|
155
|
-
bgs_features:
|
|
156
|
-
bgr_features:
|
|
152
|
+
ugg_features: CharacteristicProxy[UggFeatures] | None = None
|
|
153
|
+
ugt_features: CharacteristicProxy[UgtFeatures] | None = None
|
|
154
|
+
bgs_features: CharacteristicProxy[BgsFeatures] | None = None
|
|
155
|
+
bgr_features: CharacteristicProxy[BgrFeatures] | None = None
|
|
157
156
|
|
|
158
157
|
def __init__(self, service_proxy: ServiceProxy) -> None:
|
|
159
158
|
self.service_proxy = service_proxy
|
bumble/profiles/hap.py
CHANGED
|
@@ -20,7 +20,7 @@ from __future__ import annotations
|
|
|
20
20
|
import asyncio
|
|
21
21
|
import logging
|
|
22
22
|
from dataclasses import dataclass, field
|
|
23
|
-
from typing import Any
|
|
23
|
+
from typing import Any
|
|
24
24
|
|
|
25
25
|
from bumble import att, gatt, gatt_adapters, gatt_client, utils
|
|
26
26
|
from bumble.core import InvalidArgumentError, InvalidStateError
|
|
@@ -145,7 +145,7 @@ class PresetChangedOperation:
|
|
|
145
145
|
return bytes([self.prev_index]) + bytes(self.preset_record)
|
|
146
146
|
|
|
147
147
|
change_id: ChangeId
|
|
148
|
-
additional_parameters:
|
|
148
|
+
additional_parameters: Generic | int
|
|
149
149
|
|
|
150
150
|
def to_bytes(self, is_last: bool) -> bytes:
|
|
151
151
|
if isinstance(self.additional_parameters, PresetChangedOperation.Generic):
|
|
@@ -235,7 +235,7 @@ class HearingAccessService(gatt.TemplateService):
|
|
|
235
235
|
preset_records: dict[int, PresetRecord] # key is the preset index
|
|
236
236
|
read_presets_request_in_progress: bool
|
|
237
237
|
|
|
238
|
-
other_server_in_binaural_set:
|
|
238
|
+
other_server_in_binaural_set: HearingAccessService | None = None
|
|
239
239
|
|
|
240
240
|
preset_changed_operations_history_per_device: dict[
|
|
241
241
|
Address, list[PresetChangedOperation]
|
|
@@ -20,7 +20,6 @@ from __future__ import annotations
|
|
|
20
20
|
|
|
21
21
|
import struct
|
|
22
22
|
from enum import IntEnum
|
|
23
|
-
from typing import Optional
|
|
24
23
|
|
|
25
24
|
from bumble import core
|
|
26
25
|
from bumble.att import ATT_Error
|
|
@@ -207,13 +206,13 @@ class HeartRateService(TemplateService):
|
|
|
207
206
|
class HeartRateServiceProxy(ProfileServiceProxy):
|
|
208
207
|
SERVICE_CLASS = HeartRateService
|
|
209
208
|
|
|
210
|
-
heart_rate_measurement:
|
|
211
|
-
CharacteristicProxy[HeartRateService.HeartRateMeasurement]
|
|
212
|
-
|
|
213
|
-
body_sensor_location:
|
|
214
|
-
CharacteristicProxy[HeartRateService.BodySensorLocation]
|
|
215
|
-
|
|
216
|
-
heart_rate_control_point:
|
|
209
|
+
heart_rate_measurement: (
|
|
210
|
+
CharacteristicProxy[HeartRateService.HeartRateMeasurement] | None
|
|
211
|
+
)
|
|
212
|
+
body_sensor_location: (
|
|
213
|
+
CharacteristicProxy[HeartRateService.BodySensorLocation] | None
|
|
214
|
+
)
|
|
215
|
+
heart_rate_control_point: CharacteristicProxy[int] | None
|
|
217
216
|
|
|
218
217
|
def __init__(self, service_proxy):
|
|
219
218
|
self.service_proxy = service_proxy
|
bumble/profiles/le_audio.py
CHANGED
bumble/profiles/mcp.py
CHANGED
|
@@ -22,7 +22,7 @@ import asyncio
|
|
|
22
22
|
import dataclasses
|
|
23
23
|
import enum
|
|
24
24
|
import struct
|
|
25
|
-
from typing import TYPE_CHECKING, ClassVar
|
|
25
|
+
from typing import TYPE_CHECKING, ClassVar
|
|
26
26
|
|
|
27
27
|
from typing_extensions import Self
|
|
28
28
|
|
|
@@ -196,7 +196,7 @@ class MediaControlService(gatt.TemplateService):
|
|
|
196
196
|
|
|
197
197
|
UUID = gatt.GATT_MEDIA_CONTROL_SERVICE
|
|
198
198
|
|
|
199
|
-
def __init__(self, media_player_name:
|
|
199
|
+
def __init__(self, media_player_name: str | None = None) -> None:
|
|
200
200
|
self.track_position = 0
|
|
201
201
|
|
|
202
202
|
self.media_player_name_characteristic = gatt.Characteristic(
|
|
@@ -337,32 +337,32 @@ class MediaControlServiceProxy(
|
|
|
337
337
|
EVENT_TRACK_DURATION = "track_duration"
|
|
338
338
|
EVENT_TRACK_POSITION = "track_position"
|
|
339
339
|
|
|
340
|
-
media_player_name:
|
|
341
|
-
media_player_icon_object_id:
|
|
342
|
-
media_player_icon_url:
|
|
343
|
-
track_changed:
|
|
344
|
-
track_title:
|
|
345
|
-
track_duration:
|
|
346
|
-
track_position:
|
|
347
|
-
playback_speed:
|
|
348
|
-
seeking_speed:
|
|
349
|
-
current_track_segments_object_id:
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
current_track_object_id:
|
|
353
|
-
next_track_object_id:
|
|
354
|
-
parent_group_object_id:
|
|
355
|
-
current_group_object_id:
|
|
356
|
-
playing_order:
|
|
357
|
-
playing_orders_supported:
|
|
358
|
-
media_state:
|
|
359
|
-
media_control_point:
|
|
360
|
-
media_control_point_opcodes_supported:
|
|
361
|
-
gatt_client.CharacteristicProxy[bytes]
|
|
362
|
-
|
|
363
|
-
search_control_point:
|
|
364
|
-
search_results_object_id:
|
|
365
|
-
content_control_id:
|
|
340
|
+
media_player_name: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
341
|
+
media_player_icon_object_id: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
342
|
+
media_player_icon_url: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
343
|
+
track_changed: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
344
|
+
track_title: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
345
|
+
track_duration: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
346
|
+
track_position: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
347
|
+
playback_speed: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
348
|
+
seeking_speed: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
349
|
+
current_track_segments_object_id: gatt_client.CharacteristicProxy[bytes] | None = (
|
|
350
|
+
None
|
|
351
|
+
)
|
|
352
|
+
current_track_object_id: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
353
|
+
next_track_object_id: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
354
|
+
parent_group_object_id: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
355
|
+
current_group_object_id: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
356
|
+
playing_order: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
357
|
+
playing_orders_supported: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
358
|
+
media_state: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
359
|
+
media_control_point: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
360
|
+
media_control_point_opcodes_supported: (
|
|
361
|
+
gatt_client.CharacteristicProxy[bytes] | None
|
|
362
|
+
) = None
|
|
363
|
+
search_control_point: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
364
|
+
search_results_object_id: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
365
|
+
content_control_id: gatt_client.CharacteristicProxy[bytes] | None = None
|
|
366
366
|
|
|
367
367
|
if TYPE_CHECKING:
|
|
368
368
|
media_control_point_notifications: asyncio.Queue[bytes]
|