From 5e9fc89f805aa0b7252467af87b917f375d2ea7e Mon Sep 17 00:00:00 2001 From: Josh Wu Date: Wed, 16 Apr 2025 17:08:07 +0800 Subject: [PATCH] Add missing characteristic type parameters --- bumble/device.py | 6 ++-- bumble/gatt_client.py | 30 ++++++++++++-------- bumble/profiles/ascs.py | 8 +++--- bumble/profiles/asha.py | 10 +++---- bumble/profiles/bass.py | 2 +- bumble/profiles/csip.py | 16 +++++------ bumble/profiles/gatt_service.py | 24 ++++++++-------- bumble/profiles/hap.py | 6 ++-- bumble/profiles/mcp.py | 50 +++++++++++++++++---------------- bumble/profiles/pacs.py | 12 ++++---- bumble/profiles/vcs.py | 6 ++-- 11 files changed, 89 insertions(+), 81 deletions(-) diff --git a/bumble/device.py b/bumble/device.py index c367a7e5..97a32f3c 100644 --- a/bumble/device.py +++ b/bumble/device.py @@ -1244,7 +1244,7 @@ class Peer: self, uuids: Iterable[Union[core.UUID, str]] = (), service: Optional[gatt_client.ServiceProxy] = None, - ) -> list[gatt_client.CharacteristicProxy]: + ) -> list[gatt_client.CharacteristicProxy[bytes]]: return await self.gatt_client.discover_characteristics( uuids=uuids, service=service ) @@ -1259,7 +1259,7 @@ class Peer: characteristic, start_handle, end_handle ) - async def discover_attributes(self) -> list[gatt_client.AttributeProxy]: + async def discover_attributes(self) -> list[gatt_client.AttributeProxy[bytes]]: return await self.gatt_client.discover_attributes() async def discover_all(self): @@ -1313,7 +1313,7 @@ class Peer: self, uuid: core.UUID, service: Optional[Union[gatt_client.ServiceProxy, core.UUID]] = None, - ) -> list[gatt_client.CharacteristicProxy]: + ) -> list[gatt_client.CharacteristicProxy[bytes]]: if isinstance(service, core.UUID): return list( itertools.chain( diff --git a/bumble/gatt_client.py b/bumble/gatt_client.py index 05e9e9c8..fbe4e77d 100644 --- a/bumble/gatt_client.py +++ b/bumble/gatt_client.py @@ -149,7 +149,7 @@ class AttributeProxy(utils.EventEmitter, Generic[_T]): class ServiceProxy(AttributeProxy): uuid: UUID - characteristics: List[CharacteristicProxy] + characteristics: List[CharacteristicProxy[bytes]] included_services: List[ServiceProxy] @staticmethod @@ -170,14 +170,20 @@ class ServiceProxy(AttributeProxy): self.uuid = uuid self.characteristics = [] - async def discover_characteristics(self, uuids=()) -> list[CharacteristicProxy]: + async def discover_characteristics( + self, uuids=() + ) -> list[CharacteristicProxy[bytes]]: return await self.client.discover_characteristics(uuids, self) - def get_characteristics_by_uuid(self, uuid: UUID) -> list[CharacteristicProxy]: + def get_characteristics_by_uuid( + self, uuid: UUID + ) -> list[CharacteristicProxy[bytes]]: """Get all the characteristics with a specified UUID.""" return self.client.get_characteristics_by_uuid(uuid, self) - def get_required_characteristic_by_uuid(self, uuid: UUID) -> CharacteristicProxy: + def get_required_characteristic_by_uuid( + self, uuid: UUID + ) -> CharacteristicProxy[bytes]: """ Get the first characteristic with a specified UUID. @@ -256,7 +262,7 @@ class CharacteristicProxy(AttributeProxy[_T]): ) -class DescriptorProxy(AttributeProxy): +class DescriptorProxy(AttributeProxy[bytes]): def __init__(self, client: Client, handle: int, descriptor_type: UUID) -> None: super().__init__(client, handle, 0, descriptor_type) @@ -376,7 +382,7 @@ class Client: def get_characteristics_by_uuid( self, uuid: UUID, service: Optional[ServiceProxy] = None - ) -> List[CharacteristicProxy]: + ) -> List[CharacteristicProxy[bytes]]: services = [service] if service else self.services return [ c @@ -628,7 +634,7 @@ class Client: async def discover_characteristics( self, uuids, service: Optional[ServiceProxy] - ) -> List[CharacteristicProxy]: + ) -> List[CharacteristicProxy[bytes]]: ''' See Vol 3, Part G - 4.6.1 Discover All Characteristics of a Service and 4.6.2 Discover Characteristics by UUID @@ -641,12 +647,12 @@ class Client: services = [service] if service else self.services # Perform characteristic discovery for each service - discovered_characteristics: List[CharacteristicProxy] = [] + discovered_characteristics: List[CharacteristicProxy[bytes]] = [] for service in services: starting_handle = service.handle ending_handle = service.end_group_handle - characteristics: List[CharacteristicProxy] = [] + characteristics: List[CharacteristicProxy[bytes]] = [] while starting_handle <= ending_handle: response = await self.send_request( ATT_Read_By_Type_Request( @@ -686,7 +692,7 @@ class Client: properties, handle = struct.unpack_from(' List[AttributeProxy]: + async def discover_attributes(self) -> List[AttributeProxy[bytes]]: ''' Discover all attributes, regardless of type ''' @@ -812,7 +818,7 @@ class Client: logger.warning(f'bogus handle value: {attribute_handle}') return [] - attribute: AttributeProxy = AttributeProxy( + attribute = AttributeProxy[bytes]( self, attribute_handle, 0, UUID.from_bytes(attribute_uuid) ) attributes.append(attribute) diff --git a/bumble/profiles/ascs.py b/bumble/profiles/ascs.py index 5b488036..cab70da1 100644 --- a/bumble/profiles/ascs.py +++ b/bumble/profiles/ascs.py @@ -599,7 +599,7 @@ class AudioStreamControlService(gatt.TemplateService): UUID = gatt.GATT_AUDIO_STREAM_CONTROL_SERVICE ase_state_machines: Dict[int, AseStateMachine] - ase_control_point: gatt.Characteristic + ase_control_point: gatt.Characteristic[bytes] _active_client: Optional[device.Connection] = None def __init__( @@ -717,9 +717,9 @@ class AudioStreamControlService(gatt.TemplateService): class AudioStreamControlServiceProxy(gatt_client.ProfileServiceProxy): SERVICE_CLASS = AudioStreamControlService - sink_ase: List[gatt_client.CharacteristicProxy] - source_ase: List[gatt_client.CharacteristicProxy] - ase_control_point: gatt_client.CharacteristicProxy + sink_ase: List[gatt_client.CharacteristicProxy[bytes]] + source_ase: List[gatt_client.CharacteristicProxy[bytes]] + ase_control_point: gatt_client.CharacteristicProxy[bytes] def __init__(self, service_proxy: gatt_client.ServiceProxy): self.service_proxy = service_proxy diff --git a/bumble/profiles/asha.py b/bumble/profiles/asha.py index c5dd2d3d..7422d53b 100644 --- a/bumble/profiles/asha.py +++ b/bumble/profiles/asha.py @@ -259,11 +259,11 @@ class AshaService(gatt.TemplateService): # ----------------------------------------------------------------------------- class AshaServiceProxy(gatt_client.ProfileServiceProxy): SERVICE_CLASS = AshaService - read_only_properties_characteristic: gatt_client.CharacteristicProxy - audio_control_point_characteristic: gatt_client.CharacteristicProxy - audio_status_point_characteristic: gatt_client.CharacteristicProxy - volume_characteristic: gatt_client.CharacteristicProxy - psm_characteristic: gatt_client.CharacteristicProxy + read_only_properties_characteristic: gatt_client.CharacteristicProxy[bytes] + audio_control_point_characteristic: gatt_client.CharacteristicProxy[bytes] + audio_status_point_characteristic: gatt_client.CharacteristicProxy[bytes] + volume_characteristic: gatt_client.CharacteristicProxy[bytes] + psm_characteristic: gatt_client.CharacteristicProxy[bytes] def __init__(self, service_proxy: gatt_client.ServiceProxy) -> None: self.service_proxy = service_proxy diff --git a/bumble/profiles/bass.py b/bumble/profiles/bass.py index b81bc377..67599a07 100644 --- a/bumble/profiles/bass.py +++ b/bumble/profiles/bass.py @@ -354,7 +354,7 @@ class BroadcastAudioScanService(gatt.TemplateService): class BroadcastAudioScanServiceProxy(gatt_client.ProfileServiceProxy): SERVICE_CLASS = BroadcastAudioScanService - broadcast_audio_scan_control_point: gatt_client.CharacteristicProxy + broadcast_audio_scan_control_point: gatt_client.CharacteristicProxy[bytes] broadcast_receive_states: list[ gatt_client.CharacteristicProxy[Optional[BroadcastReceiveState]] ] diff --git a/bumble/profiles/csip.py b/bumble/profiles/csip.py index 4a7e941a..c5e3f404 100644 --- a/bumble/profiles/csip.py +++ b/bumble/profiles/csip.py @@ -99,10 +99,10 @@ class CoordinatedSetIdentificationService(gatt.TemplateService): UUID = gatt.GATT_COORDINATED_SET_IDENTIFICATION_SERVICE set_identity_resolving_key: bytes - set_identity_resolving_key_characteristic: gatt.Characteristic - coordinated_set_size_characteristic: Optional[gatt.Characteristic] = None - set_member_lock_characteristic: Optional[gatt.Characteristic] = None - set_member_rank_characteristic: Optional[gatt.Characteristic] = None + set_identity_resolving_key_characteristic: gatt.Characteristic[bytes] + coordinated_set_size_characteristic: Optional[gatt.Characteristic[bytes]] = None + set_member_lock_characteristic: Optional[gatt.Characteristic[bytes]] = None + set_member_rank_characteristic: Optional[gatt.Characteristic[bytes]] = None def __init__( self, @@ -203,10 +203,10 @@ class CoordinatedSetIdentificationService(gatt.TemplateService): class CoordinatedSetIdentificationProxy(gatt_client.ProfileServiceProxy): SERVICE_CLASS = CoordinatedSetIdentificationService - set_identity_resolving_key: gatt_client.CharacteristicProxy - coordinated_set_size: Optional[gatt_client.CharacteristicProxy] = None - set_member_lock: Optional[gatt_client.CharacteristicProxy] = None - set_member_rank: Optional[gatt_client.CharacteristicProxy] = None + set_identity_resolving_key: gatt_client.CharacteristicProxy[bytes] + coordinated_set_size: Optional[gatt_client.CharacteristicProxy[bytes]] = None + set_member_lock: Optional[gatt_client.CharacteristicProxy[bytes]] = None + set_member_rank: Optional[gatt_client.CharacteristicProxy[bytes]] = None def __init__(self, service_proxy: gatt_client.ServiceProxy) -> None: self.service_proxy = service_proxy diff --git a/bumble/profiles/gatt_service.py b/bumble/profiles/gatt_service.py index 8fce9d2c..539ff952 100644 --- a/bumble/profiles/gatt_service.py +++ b/bumble/profiles/gatt_service.py @@ -32,10 +32,10 @@ class GenericAttributeProfileService(gatt.TemplateService): UUID = gatt.GATT_GENERIC_ATTRIBUTE_SERVICE - client_supported_features_characteristic: gatt.Characteristic | None = None - server_supported_features_characteristic: gatt.Characteristic | None = None - database_hash_characteristic: gatt.Characteristic | None = None - service_changed_characteristic: gatt.Characteristic | None = None + client_supported_features_characteristic: gatt.Characteristic[bytes] | None = None + server_supported_features_characteristic: gatt.Characteristic[bytes] | None = None + database_hash_characteristic: gatt.Characteristic[bytes] | None = None + service_changed_characteristic: gatt.Characteristic[bytes] | None = None def __init__( self, @@ -143,14 +143,14 @@ class GenericAttributeProfileService(gatt.TemplateService): class GenericAttributeProfileServiceProxy(gatt_client.ProfileServiceProxy): SERVICE_CLASS = GenericAttributeProfileService - client_supported_features_characteristic: gatt_client.CharacteristicProxy | None = ( - None - ) - server_supported_features_characteristic: gatt_client.CharacteristicProxy | None = ( - None - ) - database_hash_characteristic: gatt_client.CharacteristicProxy | None = None - service_changed_characteristic: gatt_client.CharacteristicProxy | None = None + client_supported_features_characteristic: ( + gatt_client.CharacteristicProxy[bytes] | None + ) = None + server_supported_features_characteristic: ( + gatt_client.CharacteristicProxy[bytes] | None + ) = None + database_hash_characteristic: gatt_client.CharacteristicProxy[bytes] | None = None + service_changed_characteristic: gatt_client.CharacteristicProxy[bytes] | None = None _CHARACTERISTICS = { gatt.GATT_CLIENT_SUPPORTED_FEATURES_CHARACTERISTIC: 'client_supported_features_characteristic', diff --git a/bumble/profiles/hap.py b/bumble/profiles/hap.py index a2d3db2d..655cc6a6 100644 --- a/bumble/profiles/hap.py +++ b/bumble/profiles/hap.py @@ -224,9 +224,9 @@ class PresetRecord: class HearingAccessService(gatt.TemplateService): UUID = gatt.GATT_HEARING_ACCESS_SERVICE - hearing_aid_features_characteristic: gatt.Characteristic - hearing_aid_preset_control_point: gatt.Characteristic - active_preset_index_characteristic: gatt.Characteristic + hearing_aid_features_characteristic: gatt.Characteristic[bytes] + hearing_aid_preset_control_point: gatt.Characteristic[bytes] + active_preset_index_characteristic: gatt.Characteristic[bytes] active_preset_index: int active_preset_index_per_device: Dict[Address, int] diff --git a/bumble/profiles/mcp.py b/bumble/profiles/mcp.py index c4952f47..abd35e2b 100644 --- a/bumble/profiles/mcp.py +++ b/bumble/profiles/mcp.py @@ -338,30 +338,32 @@ class MediaControlServiceProxy( 'content_control_id': gatt.GATT_CONTENT_CONTROL_ID_CHARACTERISTIC, } - media_player_name: Optional[gatt_client.CharacteristicProxy] = None - media_player_icon_object_id: Optional[gatt_client.CharacteristicProxy] = None - media_player_icon_url: Optional[gatt_client.CharacteristicProxy] = None - track_changed: Optional[gatt_client.CharacteristicProxy] = None - track_title: Optional[gatt_client.CharacteristicProxy] = None - track_duration: Optional[gatt_client.CharacteristicProxy] = None - track_position: Optional[gatt_client.CharacteristicProxy] = None - playback_speed: Optional[gatt_client.CharacteristicProxy] = None - seeking_speed: Optional[gatt_client.CharacteristicProxy] = None - current_track_segments_object_id: Optional[gatt_client.CharacteristicProxy] = None - current_track_object_id: Optional[gatt_client.CharacteristicProxy] = None - next_track_object_id: Optional[gatt_client.CharacteristicProxy] = None - parent_group_object_id: Optional[gatt_client.CharacteristicProxy] = None - current_group_object_id: Optional[gatt_client.CharacteristicProxy] = None - playing_order: Optional[gatt_client.CharacteristicProxy] = None - playing_orders_supported: Optional[gatt_client.CharacteristicProxy] = None - media_state: Optional[gatt_client.CharacteristicProxy] = None - media_control_point: Optional[gatt_client.CharacteristicProxy] = None - media_control_point_opcodes_supported: Optional[gatt_client.CharacteristicProxy] = ( - None - ) - search_control_point: Optional[gatt_client.CharacteristicProxy] = None - search_results_object_id: Optional[gatt_client.CharacteristicProxy] = None - content_control_id: Optional[gatt_client.CharacteristicProxy] = None + media_player_name: Optional[gatt_client.CharacteristicProxy[bytes]] = None + media_player_icon_object_id: Optional[gatt_client.CharacteristicProxy[bytes]] = None + media_player_icon_url: Optional[gatt_client.CharacteristicProxy[bytes]] = None + track_changed: Optional[gatt_client.CharacteristicProxy[bytes]] = None + track_title: Optional[gatt_client.CharacteristicProxy[bytes]] = None + track_duration: Optional[gatt_client.CharacteristicProxy[bytes]] = None + track_position: Optional[gatt_client.CharacteristicProxy[bytes]] = None + playback_speed: Optional[gatt_client.CharacteristicProxy[bytes]] = None + seeking_speed: Optional[gatt_client.CharacteristicProxy[bytes]] = None + current_track_segments_object_id: Optional[ + gatt_client.CharacteristicProxy[bytes] + ] = None + current_track_object_id: Optional[gatt_client.CharacteristicProxy[bytes]] = None + next_track_object_id: Optional[gatt_client.CharacteristicProxy[bytes]] = None + parent_group_object_id: Optional[gatt_client.CharacteristicProxy[bytes]] = None + current_group_object_id: Optional[gatt_client.CharacteristicProxy[bytes]] = None + playing_order: Optional[gatt_client.CharacteristicProxy[bytes]] = None + playing_orders_supported: Optional[gatt_client.CharacteristicProxy[bytes]] = None + media_state: Optional[gatt_client.CharacteristicProxy[bytes]] = None + media_control_point: Optional[gatt_client.CharacteristicProxy[bytes]] = None + media_control_point_opcodes_supported: Optional[ + gatt_client.CharacteristicProxy[bytes] + ] = None + search_control_point: Optional[gatt_client.CharacteristicProxy[bytes]] = None + search_results_object_id: Optional[gatt_client.CharacteristicProxy[bytes]] = None + content_control_id: Optional[gatt_client.CharacteristicProxy[bytes]] = None if TYPE_CHECKING: media_control_point_notifications: asyncio.Queue[bytes] diff --git a/bumble/profiles/pacs.py b/bumble/profiles/pacs.py index d0952ece..585afcb5 100644 --- a/bumble/profiles/pacs.py +++ b/bumble/profiles/pacs.py @@ -104,12 +104,12 @@ class PacRecord: class PublishedAudioCapabilitiesService(gatt.TemplateService): UUID = gatt.GATT_PUBLISHED_AUDIO_CAPABILITIES_SERVICE - sink_pac: Optional[gatt.Characteristic] - sink_audio_locations: Optional[gatt.Characteristic] - source_pac: Optional[gatt.Characteristic] - source_audio_locations: Optional[gatt.Characteristic] - available_audio_contexts: gatt.Characteristic - supported_audio_contexts: gatt.Characteristic + sink_pac: Optional[gatt.Characteristic[bytes]] + sink_audio_locations: Optional[gatt.Characteristic[bytes]] + source_pac: Optional[gatt.Characteristic[bytes]] + source_audio_locations: Optional[gatt.Characteristic[bytes]] + available_audio_contexts: gatt.Characteristic[bytes] + supported_audio_contexts: gatt.Characteristic[bytes] def __init__( self, diff --git a/bumble/profiles/vcs.py b/bumble/profiles/vcs.py index 20328431..30c820e6 100644 --- a/bumble/profiles/vcs.py +++ b/bumble/profiles/vcs.py @@ -91,9 +91,9 @@ class VolumeState: class VolumeControlService(gatt.TemplateService): UUID = gatt.GATT_VOLUME_CONTROL_SERVICE - volume_state: gatt.Characteristic - volume_control_point: gatt.Characteristic - volume_flags: gatt.Characteristic + volume_state: gatt.Characteristic[bytes] + volume_control_point: gatt.Characteristic[bytes] + volume_flags: gatt.Characteristic[bytes] volume_setting: int muted: int