Coverage for src / bluetooth_sig / gatt / characteristics / alert_status.py: 57%
30 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"""Alert Status characteristic implementation."""
3from __future__ import annotations
5import msgspec
7from ..context import CharacteristicContext
8from .base import BaseCharacteristic
9from .utils import DataParser
12class AlertStatusData(msgspec.Struct, frozen=True, kw_only=True): # pylint: disable=too-few-public-methods
13 """Parsed data from Alert Status characteristic."""
15 ringer_state: bool
16 vibrate_state: bool
17 display_alert_status: bool
20class AlertStatusCharacteristic(BaseCharacteristic[AlertStatusData]):
21 """Alert Status characteristic (0x2A3F).
23 org.bluetooth.characteristic.alert_status
25 The Alert Status characteristic defines the Status of alert.
26 Bit 0: Ringer State (0=not active, 1=active)
27 Bit 1: Vibrate State (0=not active, 1=active)
28 Bit 2: Display Alert Status (0=not active, 1=active)
29 Bits 3-7: Reserved for future use
30 """
32 expected_length: int = 1
33 min_length: int = 1
35 # Bit masks for alert status flags
36 RINGER_STATE_MASK = 0x01 # Bit 0
37 VIBRATE_STATE_MASK = 0x02 # Bit 1
38 DISPLAY_ALERT_STATUS_MASK = 0x04 # Bit 2
40 def _decode_value(
41 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True
42 ) -> AlertStatusData:
43 """Parse alert status data according to Bluetooth specification.
45 Args:
46 data: Raw bytearray from BLE characteristic.
47 ctx: Optional CharacteristicContext (unused)
48 validate: Whether to validate ranges (default True)
50 Returns:
51 AlertStatusData containing parsed alert status flags.
53 Raises:
54 ValueError: If data format is invalid.
56 """
57 status_byte = DataParser.parse_int8(data, 0, signed=False)
59 # Extract bit fields according to specification
60 ringer_state = bool(status_byte & self.RINGER_STATE_MASK)
61 vibrate_state = bool(status_byte & self.VIBRATE_STATE_MASK)
62 display_alert_status = bool(status_byte & self.DISPLAY_ALERT_STATUS_MASK)
64 return AlertStatusData(
65 ringer_state=ringer_state,
66 vibrate_state=vibrate_state,
67 display_alert_status=display_alert_status,
68 )
70 def _encode_value(self, data: AlertStatusData) -> bytearray:
71 """Encode AlertStatusData back to bytes.
73 Args:
74 data: AlertStatusData instance to encode
76 Returns:
77 Encoded bytes representing the alert status
79 """
80 status_byte = 0
81 if data.ringer_state:
82 status_byte |= self.RINGER_STATE_MASK
83 if data.vibrate_state:
84 status_byte |= self.VIBRATE_STATE_MASK
85 if data.display_alert_status:
86 status_byte |= self.DISPLAY_ALERT_STATUS_MASK
88 return bytearray([status_byte])