Coverage for src / bluetooth_sig / gatt / characteristics / idd_status.py: 100%
42 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"""IDD Status characteristic (0x2B21).
3Reports the current status of the Insulin Delivery Device including
4therapy control state, operational state, and reservoir remaining.
6References:
7 Bluetooth SIG Insulin Delivery Service 1.0.1, Table 4.3
8"""
10from __future__ import annotations
12from enum import IntEnum, IntFlag
14import msgspec
16from ..context import CharacteristicContext
17from .base import BaseCharacteristic
18from .utils import DataParser, IEEE11073Parser
21class TherapyControlState(IntEnum):
22 """IDD therapy control state (Hamming-coded)."""
24 UNDETERMINED = 0x0F
25 STOP = 0x33
26 PAUSE = 0x3C
27 RUN = 0x55
30class IDDOperationalState(IntEnum):
31 """IDD operational state (Hamming-coded)."""
33 UNDETERMINED = 0x0F
34 OFF = 0x33
35 STANDBY = 0x3C
36 PREPARING = 0x55
37 PRIMING = 0x5A
38 WAITING = 0x66
39 READY = 0x96
42class IDDStatusFlags(IntFlag):
43 """IDD Status flags (8-bit)."""
45 RESERVOIR_ATTACHED = 0x01
48class IDDStatusData(msgspec.Struct, frozen=True, kw_only=True):
49 """Parsed data from IDD Status characteristic.
51 Attributes:
52 therapy_control_state: Current therapy control state.
53 operational_state: Current operational state.
54 reservoir_remaining: Reservoir remaining amount (SFLOAT).
55 flags: Status flags.
57 """
59 therapy_control_state: TherapyControlState
60 operational_state: IDDOperationalState
61 reservoir_remaining: float
62 flags: IDDStatusFlags
65class IDDStatusCharacteristic(BaseCharacteristic[IDDStatusData]):
66 """IDD Status characteristic (0x2B21).
68 org.bluetooth.characteristic.idd_status
70 Reports therapy control state, operational state, and
71 reservoir remaining for an Insulin Delivery Device.
72 """
74 min_length = 5 # therapy(1) + operational(1) + reservoir_sfloat(2) + flags(1)
75 allow_variable_length = True
77 def _decode_value(
78 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True
79 ) -> IDDStatusData:
80 """Parse IDD Status data.
82 Format: TherapyControlState (uint8) + OperationalState (uint8) +
83 ReservoirRemainingAmount (SFLOAT, 2 bytes) + Flags (uint8).
84 """
85 therapy_control_state = TherapyControlState(DataParser.parse_int8(data, 0, signed=False))
86 operational_state = IDDOperationalState(DataParser.parse_int8(data, 1, signed=False))
87 reservoir_remaining = IEEE11073Parser.parse_sfloat(data, 2)
88 flags = IDDStatusFlags(DataParser.parse_int8(data, 4, signed=False))
90 return IDDStatusData(
91 therapy_control_state=therapy_control_state,
92 operational_state=operational_state,
93 reservoir_remaining=reservoir_remaining,
94 flags=flags,
95 )
97 def _encode_value(self, data: IDDStatusData) -> bytearray:
98 """Encode IDD Status data."""
99 result = bytearray()
100 result.extend(DataParser.encode_int8(int(data.therapy_control_state), signed=False))
101 result.extend(DataParser.encode_int8(int(data.operational_state), signed=False))
102 result.extend(IEEE11073Parser.encode_sfloat(data.reservoir_remaining))
103 result.extend(DataParser.encode_int8(int(data.flags), signed=False))
104 return result