Coverage for src / bluetooth_sig / gatt / characteristics / record_access_control_point.py: 100%
51 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"""Record Access Control Point characteristic (0x2A52).
3Generic control point for managing stored records in services like
4Glucose, CGM, and Blood Pressure.
6References:
7 Bluetooth SIG GATT Specification Supplement
8 org.bluetooth.characteristic.record_access_control_point (GSS YAML)
9"""
11from __future__ import annotations
13from enum import IntEnum
15import msgspec
17from ..context import CharacteristicContext
18from .base import BaseCharacteristic
19from .utils import DataParser
22class RACPOpCode(IntEnum):
23 """Record Access Control Point Op Codes."""
25 REPORT_STORED_RECORDS = 0x01
26 DELETE_STORED_RECORDS = 0x02
27 ABORT_OPERATION = 0x03
28 REPORT_NUMBER_OF_STORED_RECORDS = 0x04
29 NUMBER_OF_STORED_RECORDS_RESPONSE = 0x05
30 RESPONSE_CODE = 0x06
31 COMBINED_REPORT = 0x07
32 COMBINED_REPORT_RESPONSE = 0x08
35class RACPOperator(IntEnum):
36 """Record Access Control Point Operators."""
38 NULL = 0x00
39 ALL_RECORDS = 0x01
40 LESS_THAN_OR_EQUAL_TO = 0x02
41 GREATER_THAN_OR_EQUAL_TO = 0x03
42 WITHIN_RANGE_OF = 0x04
43 FIRST_RECORD = 0x05
44 LAST_RECORD = 0x06
47class RACPResponseCode(IntEnum):
48 """Record Access Control Point Response Code Values."""
50 SUCCESS = 0x01
51 OP_CODE_NOT_SUPPORTED = 0x02
52 INVALID_OPERATOR = 0x03
53 OPERATOR_NOT_SUPPORTED = 0x04
54 INVALID_OPERAND = 0x05
55 NO_RECORDS_FOUND = 0x06
56 ABORT_UNSUCCESSFUL = 0x07
57 PROCEDURE_NOT_COMPLETED = 0x08
58 OPERAND_NOT_SUPPORTED = 0x09
61class RecordAccessControlPointData(msgspec.Struct, frozen=True, kw_only=True):
62 """Parsed data from Record Access Control Point.
64 Attributes:
65 opcode: The operation code.
66 operator: The operator for the operation.
67 operand: Raw operand bytes (service-specific). Empty if none.
69 """
71 opcode: RACPOpCode
72 operator: RACPOperator
73 operand: bytes = b""
76class RecordAccessControlPointCharacteristic(BaseCharacteristic[RecordAccessControlPointData]):
77 """Record Access Control Point characteristic (0x2A52).
79 org.bluetooth.characteristic.record_access_control_point
81 Generic control point for managing stored records.
82 ROLE: CONTROL
83 """
85 min_length = 2 # OpCode(1) + Operator(1)
86 allow_variable_length = True
88 def _decode_value(
89 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True
90 ) -> RecordAccessControlPointData:
91 """Parse Record Access Control Point data.
93 Format: OpCode (uint8) + Operator (uint8) + Operand (variable).
94 """
95 opcode = RACPOpCode(DataParser.parse_int8(data, 0, signed=False))
96 operator = RACPOperator(DataParser.parse_int8(data, 1, signed=False))
97 operand = bytes(data[2:])
99 return RecordAccessControlPointData(
100 opcode=opcode,
101 operator=operator,
102 operand=operand,
103 )
105 def _encode_value(self, data: RecordAccessControlPointData) -> bytearray:
106 """Encode Record Access Control Point data."""
107 result = bytearray()
108 result.extend(DataParser.encode_int8(int(data.opcode), signed=False))
109 result.extend(DataParser.encode_int8(int(data.operator), signed=False))
110 result.extend(data.operand)
111 return result