Coverage for src / bluetooth_sig / gatt / characteristics / date_of_threshold_assessment.py: 90%

30 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-18 11:17 +0000

1"""Date of Threshold Assessment characteristic (0x2A86).""" 

2 

3from __future__ import annotations 

4 

5from ...types import DateData 

6from ..constants import MAX_YEAR_VALUE 

7from ..context import CharacteristicContext 

8from ..exceptions import ValueRangeError 

9from .base import BaseCharacteristic 

10from .utils import DataParser 

11from .utils.ieee11073_parser import IEEE11073Parser 

12 

13DateOfThresholdAssessmentData = DateData 

14 

15 

16class DateOfThresholdAssessmentCharacteristic(BaseCharacteristic[DateOfThresholdAssessmentData]): 

17 """Date of Threshold Assessment characteristic (0x2A86). 

18 

19 org.bluetooth.characteristic.date_of_threshold_assessment 

20 

21 Date of Threshold Assessment characteristic. 

22 """ 

23 

24 expected_length: int = 4 # Year(2) + Month(1) + Day(1) 

25 min_length: int = 4 

26 max_length: int = 4 

27 

28 def _decode_value( 

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

30 ) -> DateOfThresholdAssessmentData: 

31 """Decode Date of Threshold Assessment from raw bytes. 

32 

33 Args: 

34 data: Raw bytes from BLE characteristic (4 bytes) 

35 ctx: Optional context for parsing 

36 validate: Whether to validate ranges (default True) 

37 

38 Returns: 

39 DateOfThresholdAssessmentData with year, month, day 

40 

41 Raises: 

42 InsufficientDataError: If data length is not exactly 4 bytes 

43 """ 

44 year = DataParser.parse_int16(data, 0, signed=False) 

45 

46 # Month is uint8 

47 month = data[2] 

48 

49 # Day is uint8 

50 day = data[3] 

51 

52 return DateOfThresholdAssessmentData(year=year, month=month, day=day) 

53 

54 def _encode_value(self, data: DateOfThresholdAssessmentData) -> bytearray: 

55 """Encode Date of Threshold Assessment to bytes. 

56 

57 Args: 

58 data: DateOfThresholdAssessmentData to encode 

59 

60 Returns: 

61 Encoded bytes (4 bytes) 

62 

63 Raises: 

64 ValueRangeError: If year, month, or day are out of valid range 

65 """ 

66 # Validate year 

67 if not ((data.year == 0) or (IEEE11073Parser.IEEE11073_MIN_YEAR <= data.year <= MAX_YEAR_VALUE)): 

68 raise ValueRangeError("year", data.year, IEEE11073Parser.IEEE11073_MIN_YEAR, MAX_YEAR_VALUE) 

69 

70 # Validate month 

71 if not ((data.month == 0) or (IEEE11073Parser.MONTH_MIN <= data.month <= IEEE11073Parser.MONTH_MAX)): 

72 raise ValueRangeError("month", data.month, IEEE11073Parser.MONTH_MIN, IEEE11073Parser.MONTH_MAX) 

73 

74 # Validate day 

75 if not ((data.day == 0) or (IEEE11073Parser.DAY_MIN <= data.day <= IEEE11073Parser.DAY_MAX)): 

76 raise ValueRangeError("day", data.day, IEEE11073Parser.DAY_MIN, IEEE11073Parser.DAY_MAX) 

77 

78 result = bytearray() 

79 

80 # Encode year (uint16, little-endian) 

81 result.extend(DataParser.encode_int16(data.year, signed=False)) 

82 

83 # Encode month (uint8) 

84 result.append(data.month) 

85 

86 # Encode day (uint8) 

87 result.append(data.day) 

88 

89 return result