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

22 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-03 16:41 +0000

1"""Time with DST characteristic (0x2A11). 

2 

3Represents the date and time with DST offset information. 

4Structure: DateTime(7 bytes) + DST Offset(1 byte) = 8 bytes total. 

5 

6References: 

7 Bluetooth SIG Assigned Numbers / GATT Service Specifications 

8""" 

9 

10from __future__ import annotations 

11 

12import struct 

13from datetime import datetime 

14 

15import msgspec 

16 

17from ..context import CharacteristicContext 

18from .base import BaseCharacteristic 

19from .dst_offset import DSTOffset 

20 

21 

22class TimeWithDstData(msgspec.Struct, frozen=True, kw_only=True): 

23 """Parsed Time with DST data.""" 

24 

25 dt: datetime 

26 dst_offset: DSTOffset 

27 

28 

29class TimeWithDstCharacteristic(BaseCharacteristic[TimeWithDstData]): 

30 """Time with DST characteristic (0x2A11). 

31 

32 Structure (8 bytes): 

33 - DateTime: Year(uint16) + Month(uint8) + Day(uint8) + Hours(uint8) + Minutes(uint8) + Seconds(uint8) = 7 bytes 

34 - DST Offset: uint8 = 1 byte 

35 """ 

36 

37 min_length: int | None = 8 

38 max_length: int | None = 8 

39 

40 def _decode_value( 

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

42 ) -> TimeWithDstData: 

43 """Parse Time with DST data. 

44 

45 Format: DateTime(7) + DSTOffset(1). 

46 """ 

47 year, month, day, hours, minutes, seconds = struct.unpack("<HBBBBB", data[0:7]) 

48 dt = datetime(year, month, day, hours, minutes, seconds) 

49 dst_offset = DSTOffset(data[7]) 

50 return TimeWithDstData(dt=dt, dst_offset=dst_offset) 

51 

52 def _encode_value(self, data: TimeWithDstData) -> bytearray: 

53 """Encode Time with DST value back to bytes.""" 

54 result = bytearray( 

55 struct.pack( 

56 "<HBBBBB", 

57 data.dt.year, 

58 data.dt.month, 

59 data.dt.day, 

60 data.dt.hour, 

61 data.dt.minute, 

62 data.dt.second, 

63 ) 

64 ) 

65 result.append(int(data.dst_offset)) 

66 return result