Coverage for src / bluetooth_sig / types / registry / appearance_info.py: 100%

14 statements  

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

1"""Appearance information data structures. 

2 

3This module contains only the data structures for appearance values, 

4with no dependencies on the registry system. This allows the registry 

5to import these types without creating circular dependencies. 

6""" 

7 

8from __future__ import annotations 

9 

10import msgspec 

11 

12 

13class AppearanceSubcategoryInfo(msgspec.Struct, frozen=True, kw_only=True): 

14 """Decoded appearance subcategory information. 

15 

16 Attributes: 

17 name: Human-readable subcategory name (e.g., "Heart Rate Belt") 

18 value: Subcategory value (0-63) 

19 """ 

20 

21 name: str 

22 value: int 

23 

24 

25class AppearanceInfo(msgspec.Struct, frozen=True, kw_only=True): 

26 """Decoded appearance information from registry. 

27 

28 The 16-bit appearance value encodes device type information: 

29 - Bits 15-6 (10 bits): Category value (0-1023) 

30 - Bits 5-0 (6 bits): Subcategory value (0-63) 

31 - Full code = (category << 6) | subcategory 

32 

33 Attributes: 

34 category: Human-readable device category name (e.g., "Heart Rate Sensor") 

35 category_value: Category value (upper 10 bits of appearance code) 

36 subcategory: Optional subcategory information (e.g., "Heart Rate Belt") 

37 """ 

38 

39 category: str 

40 category_value: int 

41 subcategory: AppearanceSubcategoryInfo | None = None 

42 

43 @property 

44 def full_name(self) -> str: 

45 """Get full appearance name. 

46 

47 Returns: 

48 Full name with category and optional subcategory 

49 (e.g., "Heart Rate Sensor: Heart Rate Belt" or "Phone") 

50 """ 

51 if self.subcategory: 

52 return f"{self.category}: {self.subcategory.name}" 

53 return self.category