Coverage for src / bluetooth_sig / gatt / descriptors / characteristic_extended_properties.py: 79%
28 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-18 11:17 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-18 11:17 +0000
1"""Characteristic Extended Properties Descriptor implementation."""
3from __future__ import annotations
5from enum import IntFlag
7import msgspec
9from ..characteristics.utils import DataParser
10from ..constants import SIZE_UINT16
11from .base import BaseDescriptor
14class ExtendedPropertiesFlags(IntFlag):
15 """Characteristic Extended Properties flags."""
17 RELIABLE_WRITE = 0x0001
18 WRITABLE_AUXILIARIES = 0x0002
21class CharacteristicExtendedPropertiesData(msgspec.Struct, frozen=True, kw_only=True):
22 """Characteristic Extended Properties descriptor data."""
24 reliable_write: bool
25 writable_auxiliaries: bool
28class CharacteristicExtendedPropertiesDescriptor(BaseDescriptor):
29 """Characteristic Extended Properties Descriptor (0x2900).
31 Defines extended properties for a characteristic using bit flags.
32 Indicates support for reliable writes and writable auxiliaries.
33 """
35 def _has_structured_data(self) -> bool:
36 return True
38 def _get_data_format(self) -> str:
39 return "uint16"
41 def _parse_descriptor_value(self, data: bytes) -> CharacteristicExtendedPropertiesData:
42 """Parse Characteristic Extended Properties value.
44 Args:
45 data: Raw bytes (should be 2 bytes for uint16)
47 Returns:
48 CharacteristicExtendedPropertiesData with property flags
50 Raises:
51 ValueError: If data is not exactly 2 bytes
52 """
53 if len(data) != SIZE_UINT16:
54 raise ValueError(f"Characteristic Extended Properties data must be exactly 2 bytes, got {len(data)}")
56 # Parse as little-endian uint16
57 value = DataParser.parse_int16(data, endian="little")
59 return CharacteristicExtendedPropertiesData(
60 reliable_write=bool(value & ExtendedPropertiesFlags.RELIABLE_WRITE),
61 writable_auxiliaries=bool(value & ExtendedPropertiesFlags.WRITABLE_AUXILIARIES),
62 )
64 def supports_reliable_write(self, data: bytes) -> bool:
65 """Check if reliable write is supported."""
66 parsed = self._parse_descriptor_value(data)
67 return parsed.reliable_write
69 def supports_writable_auxiliaries(self, data: bytes) -> bool:
70 """Check if writable auxiliaries are supported."""
71 parsed = self._parse_descriptor_value(data)
72 return parsed.writable_auxiliaries