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

1"""Sleep Activity Summary Data characteristic (0x2B42).""" 

2 

3from __future__ import annotations 

4 

5from enum import IntFlag 

6 

7import msgspec 

8 

9from ..context import CharacteristicContext 

10from .base import BaseCharacteristic 

11from .utils import DataParser 

12 

13 

14class SleepActivitySummaryFlags(IntFlag): 

15 """Flags for Sleep Activity Summary Data (Table 3.20).""" 

16 

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 

37 

38 

39_ADDITIONAL_DATA_START_OFFSET = 3 

40 

41 

42class SleepActivitySummaryData(msgspec.Struct, frozen=True, kw_only=True): # pylint: disable=too-few-public-methods 

43 """Parsed data from Sleep Activity Summary Data. 

44 

45 Contains flags and any additional summary field data as raw bytes. 

46 The flags field indicates which optional summary fields are present. 

47 """ 

48 

49 flags: SleepActivitySummaryFlags 

50 additional_data: bytes = b"" 

51 

52 

53class SleepActivitySummaryDataCharacteristic( 

54 BaseCharacteristic[SleepActivitySummaryData], 

55): 

56 """Sleep Activity Summary Data characteristic (0x2B42). 

57 

58 org.bluetooth.characteristic.sleep_activity_summary_data 

59 

60 Summary sleep activity data from the Physical Activity Monitor 

61 service. Flags indicate which optional summary fields are present. 

62 """ 

63 

64 min_length = 3 # flags (uint24) 

65 allow_variable_length = True 

66 

67 def _decode_value( 

68 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True 

69 ) -> SleepActivitySummaryData: 

70 """Parse Sleep Activity Summary Data. 

71 

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 ) 

78 

79 return SleepActivitySummaryData( 

80 flags=flags, 

81 additional_data=additional_data, 

82 ) 

83 

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