Coverage for src / bluetooth_sig / gatt / characteristics / object_action_control_point.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"""Object Action 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 OACPOpcode(IntEnum):
16 """Object Action Control Point opcodes per OTS specification."""
18 CREATE = 0x01
19 DELETE = 0x02
20 CALCULATE_CHECKSUM = 0x03
21 EXECUTE = 0x04
22 READ = 0x05
23 WRITE = 0x06
24 ABORT = 0x07
25 RESPONSE = 0x60
28class OACPResultCode(IntEnum):
29 """OACP response result codes per OTS specification."""
31 SUCCESS = 0x01
32 OPCODE_NOT_SUPPORTED = 0x02
33 INVALID_PARAMETER = 0x03
34 INSUFFICIENT_RESOURCES = 0x04
35 INVALID_OBJECT = 0x05
36 CHANNEL_UNAVAILABLE = 0x06
37 UNSUPPORTED_TYPE = 0x07
38 PROCEDURE_NOT_PERMITTED = 0x08
39 OBJECT_LOCKED = 0x09
40 OPERATION_FAILED = 0x0A
43class OACPData(msgspec.Struct, frozen=True, kw_only=True):
44 """Parsed data from Object Action Control Point characteristic.
46 Attributes:
47 opcode: The OACP opcode.
48 parameters: Raw parameter bytes (opcode-dependent).
50 """
52 opcode: OACPOpcode
53 parameters: bytes = b""
56class ObjectActionControlPointCharacteristic(BaseCharacteristic[OACPData]):
57 """Object Action Control Point characteristic (0x2AC5).
59 org.bluetooth.characteristic.object_action_control_point
61 Control point for object actions in the Object Transfer Service (OTS).
62 Opcodes include Create, Delete, Calculate Checksum, Execute, Read,
63 Write, Abort, and Response.
64 """
66 _manual_role = CharacteristicRole.CONTROL
67 min_length: int = 1 # At minimum: opcode (1 byte)
68 allow_variable_length: bool = True
70 def _decode_value(
71 self,
72 data: bytearray,
73 ctx: CharacteristicContext | None = None,
74 *,
75 validate: bool = True,
76 ) -> OACPData:
77 """Parse OACP data.
79 Args:
80 data: Raw bytes (1+ bytes).
81 ctx: Optional CharacteristicContext.
82 validate: Whether to validate ranges (default True).
84 Returns:
85 OACPData with opcode and parameters.
87 """
88 opcode = OACPOpcode(DataParser.parse_int8(data, 0, signed=False))
89 parameters = bytes(data[1:])
90 return OACPData(opcode=opcode, parameters=parameters)
92 def _encode_value(self, data: OACPData) -> bytearray:
93 """Encode OACP data to bytes.
95 Args:
96 data: OACPData to encode.
98 Returns:
99 Encoded bytes.
101 """
102 result = DataParser.encode_int8(int(data.opcode), signed=False)
103 result.extend(data.parameters)
104 return result