Coverage for src / bluetooth_sig / gatt / characteristics / cgm_session_run_time.py: 100%
24 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"""CGM Session Run Time characteristic implementation.
3Implements the CGM Session Run Time characteristic (0x2AAB).
5Structure (from GSS YAML):
6 CGM Session Run Time (uint16) -- expected run time in hours
7 E2E-CRC (uint16, optional) -- present if E2E-CRC Supported
9References:
10 Bluetooth SIG Continuous Glucose Monitoring Service
11 org.bluetooth.characteristic.cgm_session_run_time (GSS YAML)
12"""
14from __future__ import annotations
16import msgspec
18from ..context import CharacteristicContext
19from .base import BaseCharacteristic
20from .utils import DataParser
23class CGMSessionRunTimeData(msgspec.Struct, frozen=True, kw_only=True):
24 """Parsed data from CGM Session Run Time characteristic.
26 Attributes:
27 run_time_hours: Expected run time of the CGM session in hours.
28 e2e_crc: E2E-CRC value. None if absent.
30 """
32 run_time_hours: int
33 e2e_crc: int | None = None
36class CGMSessionRunTimeCharacteristic(BaseCharacteristic[CGMSessionRunTimeData]):
37 """CGM Session Run Time characteristic (0x2AAB).
39 Reports the expected run time of the CGM session in hours.
40 """
42 expected_type = CGMSessionRunTimeData
43 min_length: int = 2 # run_time(2)
44 allow_variable_length: bool = True # optional E2E-CRC
46 def _decode_value(
47 self,
48 data: bytearray,
49 ctx: CharacteristicContext | None = None,
50 *,
51 validate: bool = True,
52 ) -> CGMSessionRunTimeData:
53 """Parse CGM Session Run Time from raw BLE bytes.
55 Args:
56 data: Raw bytearray from BLE characteristic (2 or 4 bytes).
57 ctx: Optional context (unused).
58 validate: Whether to validate ranges.
60 Returns:
61 CGMSessionRunTimeData with parsed run time.
63 """
64 run_time_hours = DataParser.parse_int16(data, 0, signed=False)
66 _min_length_with_crc = 4
67 e2e_crc: int | None = None
68 if len(data) >= _min_length_with_crc:
69 e2e_crc = DataParser.parse_int16(data, 2, signed=False)
71 return CGMSessionRunTimeData(
72 run_time_hours=run_time_hours,
73 e2e_crc=e2e_crc,
74 )
76 def _encode_value(self, data: CGMSessionRunTimeData) -> bytearray:
77 """Encode CGMSessionRunTimeData back to BLE bytes.
79 Args:
80 data: CGMSessionRunTimeData instance.
82 Returns:
83 Encoded bytearray (2 or 4 bytes).
85 """
86 result = DataParser.encode_int16(data.run_time_hours, signed=False)
87 if data.e2e_crc is not None:
88 result.extend(DataParser.encode_int16(data.e2e_crc, signed=False))
89 return result