Coverage for src / bluetooth_sig / gatt / characteristics / idd_record_access_control_point.py: 100%
47 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 Record Access Control Point characteristic (0x2B27).
3IDD-specific record access control point for managing insulin delivery
4history records. Same pattern as generic RACP (0x2A52) but IDD-specific.
6References:
7 Bluetooth SIG Insulin Delivery Service 1.0.1, Table 3.21, 3.25
8"""
10from __future__ import annotations
12from enum import IntEnum
14import msgspec
16from ..context import CharacteristicContext
17from .base import BaseCharacteristic
18from .utils import DataParser
21class IDDRACPOpCode(IntEnum):
22 """IDD Record Access Control Point Op Codes (Table 3.25, Hamming codes)."""
24 RESPONSE_CODE = 0x0F
25 REPORT_STORED_RECORDS = 0x33
26 DELETE_STORED_RECORDS = 0x3C
27 ABORT_OPERATION = 0x55
28 REPORT_NUMBER_OF_STORED_RECORDS = 0x5A
29 NUMBER_OF_STORED_RECORDS_RESPONSE = 0x66
32class IDDRACPOperator(IntEnum):
33 """IDD Record Access Control Point Operators (Table 3.26, Hamming codes)."""
35 NULL = 0x0F
36 ALL_RECORDS = 0x33
37 LESS_THAN_OR_EQUAL = 0x3C
38 GREATER_THAN_OR_EQUAL = 0x55
39 RANGE_INCLUSIVE = 0x5A
40 FIRST_RECORD = 0x66
41 LAST_RECORD = 0x69
44class IDDRACPResponseCode(IntEnum):
45 """IDD RACP response codes (Table 3.27)."""
47 # Error codes 0x02-0x09 range (from generic RACP)
48 UNSUPPORTED_OPERATOR = 0x02
49 INVALID_OPERATOR = 0x03
50 UNSUPPORTED_OPERAND = 0x04
51 INVALID_OPERAND = 0x05
52 UNCLEAR_OPERATOR = 0x06
53 # IDD-specific codes
54 PROCEDURE_NOT_APPLICABLE = 0x0A
55 SUCCESS = 0xF0
58class IDDRecordAccessControlPointData(msgspec.Struct, frozen=True, kw_only=True):
59 """Parsed data from IDD Record Access Control Point.
61 Attributes:
62 opcode: The operation code.
63 operator: The operator for the operation.
64 operand: Raw operand bytes. Empty if none.
66 """
68 opcode: IDDRACPOpCode
69 operator: IDDRACPOperator
70 operand: bytes = b""
73class IDDRecordAccessControlPointCharacteristic(BaseCharacteristic[IDDRecordAccessControlPointData]):
74 """IDD Record Access Control Point characteristic (0x2B27).
76 org.bluetooth.characteristic.idd_record_access_control_point
78 IDD-specific record access control point.
79 ROLE: CONTROL
80 """
82 min_length = 2 # OpCode(1) + Operator(1)
83 allow_variable_length = True
85 def _decode_value(
86 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True
87 ) -> IDDRecordAccessControlPointData:
88 """Parse IDD RACP data.
90 Format: OpCode (uint8) + Operator (uint8) + Operand (variable).
91 """
92 opcode = IDDRACPOpCode(DataParser.parse_int8(data, 0, signed=False))
93 operator = IDDRACPOperator(DataParser.parse_int8(data, 1, signed=False))
94 operand = bytes(data[2:])
96 return IDDRecordAccessControlPointData(
97 opcode=opcode,
98 operator=operator,
99 operand=operand,
100 )
102 def _encode_value(self, data: IDDRecordAccessControlPointData) -> bytearray:
103 """Encode IDD RACP data."""
104 result = bytearray()
105 result.extend(DataParser.encode_int8(int(data.opcode), signed=False))
106 result.extend(DataParser.encode_int8(int(data.operator), signed=False))
107 result.extend(data.operand)
108 return result