Coverage for src / bluetooth_sig / gatt / characteristics / bond_management_feature.py: 96%

26 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-11 20:14 +0000

1"""Bond Management Feature characteristic implementation.""" 

2 

3from __future__ import annotations 

4 

5import msgspec 

6 

7from ..context import CharacteristicContext 

8from .base import BaseCharacteristic 

9from .utils import DataParser 

10 

11 

12class BondManagementFeatureData(msgspec.Struct, frozen=True, kw_only=True): 

13 """Bond Management Feature characteristic data structure.""" 

14 

15 delete_bond_of_requesting_device_supported: bool 

16 delete_all_bonds_on_server_supported: bool 

17 delete_all_but_active_bond_on_server_supported: bool 

18 

19 

20class BondManagementFeatureCharacteristic(BaseCharacteristic[BondManagementFeatureData]): 

21 """Bond Management Feature characteristic (0x2AA5). 

22 

23 org.bluetooth.characteristic.bond_management_feature 

24 

25 Read-only characteristic containing feature flags for bond management operations. 

26 3 bytes containing boolean flags for supported operations. 

27 """ 

28 

29 # SIG spec: three uint8 feature flags → fixed 3-byte payload; no GSS YAML 

30 expected_length = 3 

31 min_length = 3 

32 max_length = 3 

33 

34 def _decode_value(self, data: bytearray, ctx: CharacteristicContext | None = None) -> BondManagementFeatureData: 

35 """Decode Bond Management Feature data from bytes. 

36 

37 Args: 

38 data: Raw characteristic data (3 bytes) 

39 ctx: Optional characteristic context 

40 

41 Returns: 

42 BondManagementFeatureData with feature flags 

43 

44 Raises: 

45 ValueError: If data is insufficient 

46 

47 """ 

48 if len(data) < 3: 

49 raise ValueError(f"Insufficient data for Bond Management Feature: expected 3 bytes, got {len(data)}") 

50 

51 # Parse feature flags (1 byte each) 

52 delete_bond_supported = bool(DataParser.parse_int8(data, 0, signed=False)) 

53 delete_all_bonds_supported = bool(DataParser.parse_int8(data, 1, signed=False)) 

54 delete_all_but_active_supported = bool(DataParser.parse_int8(data, 2, signed=False)) 

55 

56 return BondManagementFeatureData( 

57 delete_bond_of_requesting_device_supported=delete_bond_supported, 

58 delete_all_bonds_on_server_supported=delete_all_bonds_supported, 

59 delete_all_but_active_bond_on_server_supported=delete_all_but_active_supported, 

60 ) 

61 

62 def _encode_value(self, data: BondManagementFeatureData) -> bytearray: 

63 """Encode Bond Management Feature data to bytes. 

64 

65 Args: 

66 data: BondManagementFeatureData to encode 

67 

68 Returns: 

69 Encoded feature flags (3 bytes) 

70 

71 """ 

72 result = bytearray() 

73 

74 # Encode feature flags (1 byte each) 

75 result.append(1 if data.delete_bond_of_requesting_device_supported else 0) 

76 result.append(1 if data.delete_all_bonds_on_server_supported else 0) 

77 result.append(1 if data.delete_all_but_active_bond_on_server_supported else 0) 

78 

79 return result