Coverage for src / bluetooth_sig / gatt / characteristics / object_list_control_point.py: 100%
52 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"""Object List Control Point characteristic implementation."""
3from __future__ import annotations
5from enum import IntEnum
7import msgspec
9from ...types.gatt_enums import CharacteristicRole
10from ..context import CharacteristicContext
11from .base import BaseCharacteristic
12from .utils import DataParser
15class OLCPOpcode(IntEnum):
16 """Object List Control Point opcodes per OTS specification."""
18 FIRST = 0x01
19 LAST = 0x02
20 PREVIOUS = 0x03
21 NEXT = 0x04
22 GO_TO = 0x05
23 ORDER = 0x06
24 REQUEST_NUMBER_OF_OBJECTS = 0x07
25 CLEAR_MARKING = 0x08
26 RESPONSE = 0x70
29class OLCPResultCode(IntEnum):
30 """OLCP response result codes per OTS specification."""
32 SUCCESS = 0x01
33 OPCODE_NOT_SUPPORTED = 0x02
34 INVALID_PARAMETER = 0x03
35 OPERATION_FAILED = 0x04
36 OUT_OF_BOUNDS = 0x05
37 TOO_MANY_OBJECTS = 0x06
38 NO_OBJECT = 0x07
39 OBJECT_ID_NOT_FOUND = 0x08
42class OLCPSortOrder(IntEnum):
43 """OLCP sort order values per OTS specification."""
45 NAME_ASCENDING = 0x01
46 TYPE_ASCENDING = 0x02
47 CURRENT_SIZE_ASCENDING = 0x03
48 FIRST_CREATED_ASCENDING = 0x04
49 LAST_MODIFIED_ASCENDING = 0x05
50 NAME_DESCENDING = 0x11
51 TYPE_DESCENDING = 0x12
52 CURRENT_SIZE_DESCENDING = 0x13
53 FIRST_CREATED_DESCENDING = 0x14
54 LAST_MODIFIED_DESCENDING = 0x15
57class OLCPData(msgspec.Struct, frozen=True, kw_only=True):
58 """Parsed data from Object List Control Point characteristic.
60 Attributes:
61 opcode: The OLCP opcode.
62 parameters: Raw parameter bytes (opcode-dependent).
64 """
66 opcode: OLCPOpcode
67 parameters: bytes = b""
70class ObjectListControlPointCharacteristic(BaseCharacteristic[OLCPData]):
71 """Object List Control Point characteristic (0x2AC6).
73 org.bluetooth.characteristic.object_list_control_point
75 Control point for object list navigation in the Object Transfer
76 Service (OTS). Opcodes include First, Last, Previous, Next, Go To,
77 Order, Request Number of Objects, Clear Marking, and Response.
78 """
80 _manual_role = CharacteristicRole.CONTROL
81 min_length: int = 1 # At minimum: opcode (1 byte)
82 allow_variable_length: bool = True
84 def _decode_value(
85 self,
86 data: bytearray,
87 ctx: CharacteristicContext | None = None,
88 *,
89 validate: bool = True,
90 ) -> OLCPData:
91 """Parse OLCP data.
93 Args:
94 data: Raw bytes (1+ bytes).
95 ctx: Optional CharacteristicContext.
96 validate: Whether to validate ranges (default True).
98 Returns:
99 OLCPData with opcode and parameters.
101 """
102 opcode = OLCPOpcode(DataParser.parse_int8(data, 0, signed=False))
103 parameters = bytes(data[1:])
104 return OLCPData(opcode=opcode, parameters=parameters)
106 def _encode_value(self, data: OLCPData) -> bytearray:
107 """Encode OLCP data to bytes.
109 Args:
110 data: OLCPData to encode.
112 Returns:
113 Encoded bytes.
115 """
116 result = DataParser.encode_int8(int(data.opcode), signed=False)
117 result.extend(data.parameters)
118 return result