Coverage for src / bluetooth_sig / gatt / characteristics / unread_alert_status.py: 100%
22 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"""Unread Alert Status characteristic (0x2A45) implementation.
3Represents the number of unread alerts in a specific category.
4Used by Alert Notification Service (0x1811).
6Based on Bluetooth SIG GATT Specification:
7- Unread Alert Status: 2 bytes (Category ID + Unread Count)
8"""
10from __future__ import annotations
12import msgspec
14from ...types import AlertCategoryID
15from ..context import CharacteristicContext
16from .base import BaseCharacteristic
17from .utils import DataParser
20class UnreadAlertStatusData(msgspec.Struct):
21 """Unread Alert Status characteristic data structure."""
23 category_id: AlertCategoryID
24 unread_count: int # 0-254, 255 means >254
27class UnreadAlertStatusCharacteristic(BaseCharacteristic[UnreadAlertStatusData]):
28 """Unread Alert Status characteristic (0x2A45).
30 Represents the number of unread alerts in a specific category.
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)
36 Used by Alert Notification Service (0x1811).
37 """
39 expected_length: int | None = 2
41 def _decode_value(
42 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True
43 ) -> UnreadAlertStatusData:
44 """Decode Unread Alert Status data from bytes.
46 Args:
47 data: Raw characteristic data (2 bytes)
48 ctx: Optional characteristic context
49 validate: Whether to validate ranges (default True)
51 Returns:
52 UnreadAlertStatusData with all fields
54 Raises:
55 ValueError: If data contains invalid values
57 """
58 # Parse Category ID (1 byte)
59 category_id_raw = DataParser.parse_int8(data, 0, signed=False)
60 category_id = AlertCategoryID(category_id_raw)
62 # Parse Unread Count (1 byte)
63 unread_count = DataParser.parse_int8(data, 1, signed=False)
65 return UnreadAlertStatusData(
66 category_id=category_id,
67 unread_count=unread_count,
68 )
70 def _encode_value(self, data: UnreadAlertStatusData) -> bytearray:
71 """Encode Unread Alert Status data to bytes.
73 Args:
74 data: UnreadAlertStatusData to encode
76 Returns:
77 Encoded unread alert status (2 bytes)
79 Raises:
80 ValueError: If data contains invalid values
82 """
83 result = bytearray()
85 # Encode Category ID (1 byte)
86 category_id_value = int(data.category_id)
87 result.append(category_id_value)
89 # Encode Unread Count (1 byte)
90 result.append(data.unread_count)
92 return result