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

22 statements  

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

1"""Unread Alert Status characteristic (0x2A45) implementation. 

2 

3Represents the number of unread alerts in a specific category. 

4Used by Alert Notification Service (0x1811). 

5 

6Based on Bluetooth SIG GATT Specification: 

7- Unread Alert Status: 2 bytes (Category ID + Unread Count) 

8""" 

9 

10from __future__ import annotations 

11 

12import msgspec 

13 

14from ...types import AlertCategoryID 

15from ..context import CharacteristicContext 

16from .base import BaseCharacteristic 

17from .utils import DataParser 

18 

19 

20class UnreadAlertStatusData(msgspec.Struct): 

21 """Unread Alert Status characteristic data structure.""" 

22 

23 category_id: AlertCategoryID 

24 unread_count: int # 0-254, 255 means >254 

25 

26 

27class UnreadAlertStatusCharacteristic(BaseCharacteristic[UnreadAlertStatusData]): 

28 """Unread Alert Status characteristic (0x2A45). 

29 

30 Represents the number of unread alerts in a specific category. 

31 

32 Structure (2 bytes): 

33 - Category ID: uint8 (0=Simple Alert, 1=Email, etc.) 

34 - Unread Count: uint8 (0-254, 255 means more than 254 unread alerts) 

35 

36 Used by Alert Notification Service (0x1811). 

37 """ 

38 

39 expected_length: int | None = 2 

40 

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

42 """Decode Unread Alert Status data from bytes. 

43 

44 Args: 

45 data: Raw characteristic data (2 bytes) 

46 ctx: Optional characteristic context 

47 

48 Returns: 

49 UnreadAlertStatusData with all fields 

50 

51 Raises: 

52 ValueError: If data contains invalid values 

53 

54 """ 

55 # Parse Category ID (1 byte) 

56 category_id_raw = DataParser.parse_int8(data, 0, signed=False) 

57 category_id = AlertCategoryID(category_id_raw) 

58 

59 # Parse Unread Count (1 byte) 

60 unread_count = DataParser.parse_int8(data, 1, signed=False) 

61 

62 return UnreadAlertStatusData( 

63 category_id=category_id, 

64 unread_count=unread_count, 

65 ) 

66 

67 def _encode_value(self, data: UnreadAlertStatusData) -> bytearray: 

68 """Encode Unread Alert Status data to bytes. 

69 

70 Args: 

71 data: UnreadAlertStatusData to encode 

72 

73 Returns: 

74 Encoded unread alert status (2 bytes) 

75 

76 Raises: 

77 ValueError: If data contains invalid values 

78 

79 """ 

80 result = bytearray() 

81 

82 # Encode Category ID (1 byte) 

83 category_id_value = int(data.category_id) 

84 result.append(category_id_value) 

85 

86 # Encode Unread Count (1 byte) 

87 result.append(data.unread_count) 

88 

89 return result