Coverage for src / bluetooth_sig / gatt / characteristics / appearance.py: 100%

16 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-18 11:17 +0000

1"""Appearance characteristic implementation.""" 

2 

3from __future__ import annotations 

4 

5from ...registry.core.appearance_values import appearance_values_registry 

6from ...types.appearance import AppearanceData 

7from ...types.gatt_enums import CharacteristicRole 

8from ..context import CharacteristicContext 

9from .base import BaseCharacteristic 

10from .utils import DataParser 

11 

12 

13class AppearanceCharacteristic(BaseCharacteristic[AppearanceData]): 

14 """Appearance characteristic (0x2A01). 

15 

16 org.bluetooth.characteristic.gap.appearance 

17 

18 Appearance characteristic with human-readable device type information. 

19 """ 

20 

21 _manual_role = CharacteristicRole.INFO 

22 expected_length = 2 

23 

24 def _decode_value( 

25 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True 

26 ) -> AppearanceData: 

27 """Parse appearance value with human-readable info. 

28 

29 Args: 

30 data: Raw bytearray from BLE characteristic (2 bytes). 

31 ctx: Optional CharacteristicContext providing surrounding context (may be None). 

32 validate: Whether to validate ranges (default True) 

33 

34 Returns: 

35 AppearanceData with raw value and optional human-readable info. 

36 """ 

37 raw_value = DataParser.parse_int16(data, 0, signed=False) 

38 appearance_info = appearance_values_registry.get_appearance_info(raw_value) 

39 

40 return AppearanceData( 

41 raw_value=raw_value, 

42 info=appearance_info, 

43 ) 

44 

45 def _encode_value(self, data: AppearanceData) -> bytearray: 

46 """Encode appearance value back to bytes. 

47 

48 Args: 

49 data: Appearance value as AppearanceData 

50 

51 Returns: 

52 Encoded bytes representing the appearance 

53 """ 

54 return DataParser.encode_int16(data.raw_value, signed=False)