Coverage for src/bluetooth_sig/gatt/descriptors/characteristic_extended_properties.py: 85%
27 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-30 00:10 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-30 00:10 +0000
1"""Characteristic Extended Properties Descriptor implementation."""
3from __future__ import annotations
5from enum import IntFlag
7import msgspec
9from ..characteristics.utils import DataParser
10from .base import BaseDescriptor
13class ExtendedPropertiesFlags(IntFlag):
14 """Characteristic Extended Properties flags."""
16 RELIABLE_WRITE = 0x0001
17 WRITABLE_AUXILIARIES = 0x0002
20class CharacteristicExtendedPropertiesData(msgspec.Struct, frozen=True, kw_only=True):
21 """Characteristic Extended Properties descriptor data."""
23 reliable_write: bool
24 writable_auxiliaries: bool
27class CharacteristicExtendedPropertiesDescriptor(BaseDescriptor):
28 """Characteristic Extended Properties Descriptor (0x2900).
30 Defines extended properties for a characteristic using bit flags.
31 Indicates support for reliable writes and writable auxiliaries.
32 """
34 def _has_structured_data(self) -> bool:
35 return True
37 def _get_data_format(self) -> str:
38 return "uint16"
40 def _parse_descriptor_value(self, data: bytes) -> CharacteristicExtendedPropertiesData:
41 """Parse Characteristic Extended Properties value.
43 Args:
44 data: Raw bytes (should be 2 bytes for uint16)
46 Returns:
47 CharacteristicExtendedPropertiesData with property flags
49 Raises:
50 ValueError: If data is not exactly 2 bytes
51 """
52 if len(data) != 2:
53 raise ValueError(f"Characteristic Extended Properties data must be exactly 2 bytes, got {len(data)}")
55 # Parse as little-endian uint16
56 value = DataParser.parse_int16(data, endian="little")
58 return CharacteristicExtendedPropertiesData(
59 reliable_write=bool(value & ExtendedPropertiesFlags.RELIABLE_WRITE),
60 writable_auxiliaries=bool(value & ExtendedPropertiesFlags.WRITABLE_AUXILIARIES),
61 )
63 def supports_reliable_write(self, data: bytes) -> bool:
64 """Check if reliable write is supported."""
65 parsed = self._parse_descriptor_value(data)
66 return parsed.reliable_write
68 def supports_writable_auxiliaries(self, data: bytes) -> bool:
69 """Check if writable auxiliaries are supported."""
70 parsed = self._parse_descriptor_value(data)
71 return parsed.writable_auxiliaries