Coverage for src / bluetooth_sig / gatt / characteristics / sleep_activity_summary_data.py: 100%
43 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-03 16:41 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-03 16:41 +0000
1"""Sleep Activity Summary Data characteristic (0x2B42)."""
3from __future__ import annotations
5from enum import IntFlag
7import msgspec
9from ..context import CharacteristicContext
10from .base import BaseCharacteristic
11from .utils import DataParser
14class SleepActivitySummaryFlags(IntFlag):
15 """Flags for Sleep Activity Summary Data (Table 3.20)."""
17 TOTAL_SLEEP_TIME_PRESENT = 0x000001
18 TOTAL_WAKE_TIME_PRESENT = 0x000002
19 TOTAL_BED_TIME_PRESENT = 0x000004
20 NUMBER_OF_AWAKENINGS_PRESENT = 0x000008
21 SLEEP_LATENCY_PRESENT = 0x000010
22 SLEEP_EFFICIENCY_PRESENT = 0x000020
23 SNOOZE_TIME_PRESENT = 0x000040
24 TOSS_TURN_EVENTS_PRESENT = 0x000080
25 AWAKENING_AFTER_ALARM_PRESENT = 0x000100
26 MIN_VISIBLE_LIGHT_PRESENT = 0x000200
27 MAX_VISIBLE_LIGHT_PRESENT = 0x000400
28 AVG_VISIBLE_LIGHT_PRESENT = 0x000800
29 MIN_UV_LIGHT_PRESENT = 0x001000
30 MAX_UV_LIGHT_PRESENT = 0x002000
31 AVG_UV_LIGHT_PRESENT = 0x004000
32 MIN_IR_LIGHT_PRESENT = 0x008000
33 MAX_IR_LIGHT_PRESENT = 0x010000
34 AVG_IR_LIGHT_PRESENT = 0x020000
35 AVG_SLEEPING_HR_PRESENT = 0x040000
36 WORN_DURATION_PRESENT = 0x080000
39_ADDITIONAL_DATA_START_OFFSET = 3
42class SleepActivitySummaryData(msgspec.Struct, frozen=True, kw_only=True): # pylint: disable=too-few-public-methods
43 """Parsed data from Sleep Activity Summary Data.
45 Contains flags and any additional summary field data as raw bytes.
46 The flags field indicates which optional summary fields are present.
47 """
49 flags: SleepActivitySummaryFlags
50 additional_data: bytes = b""
53class SleepActivitySummaryDataCharacteristic(
54 BaseCharacteristic[SleepActivitySummaryData],
55):
56 """Sleep Activity Summary Data characteristic (0x2B42).
58 org.bluetooth.characteristic.sleep_activity_summary_data
60 Summary sleep activity data from the Physical Activity Monitor
61 service. Flags indicate which optional summary fields are present.
62 """
64 min_length = 3 # flags (uint24)
65 allow_variable_length = True
67 def _decode_value(
68 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True
69 ) -> SleepActivitySummaryData:
70 """Parse Sleep Activity Summary Data.
72 Format: flags (uint24) + variable optional fields.
73 """
74 flags = SleepActivitySummaryFlags(DataParser.parse_int24(data, 0, signed=False))
75 additional_data = (
76 bytes(data[_ADDITIONAL_DATA_START_OFFSET:]) if len(data) > _ADDITIONAL_DATA_START_OFFSET else b""
77 )
79 return SleepActivitySummaryData(
80 flags=flags,
81 additional_data=additional_data,
82 )
84 def _encode_value(self, data: SleepActivitySummaryData) -> bytearray:
85 """Encode Sleep Activity Summary Data to bytes."""
86 result = bytearray()
87 result += DataParser.encode_int24(int(data.flags), signed=False)
88 result += bytearray(data.additional_data)
89 return result