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

1"""Object List Control Point characteristic implementation.""" 

2 

3from __future__ import annotations 

4 

5from enum import IntEnum 

6 

7import msgspec 

8 

9from ...types.gatt_enums import CharacteristicRole 

10from ..context import CharacteristicContext 

11from .base import BaseCharacteristic 

12from .utils import DataParser 

13 

14 

15class OLCPOpcode(IntEnum): 

16 """Object List Control Point opcodes per OTS specification.""" 

17 

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 

27 

28 

29class OLCPResultCode(IntEnum): 

30 """OLCP response result codes per OTS specification.""" 

31 

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 

40 

41 

42class OLCPSortOrder(IntEnum): 

43 """OLCP sort order values per OTS specification.""" 

44 

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 

55 

56 

57class OLCPData(msgspec.Struct, frozen=True, kw_only=True): 

58 """Parsed data from Object List Control Point characteristic. 

59 

60 Attributes: 

61 opcode: The OLCP opcode. 

62 parameters: Raw parameter bytes (opcode-dependent). 

63 

64 """ 

65 

66 opcode: OLCPOpcode 

67 parameters: bytes = b"" 

68 

69 

70class ObjectListControlPointCharacteristic(BaseCharacteristic[OLCPData]): 

71 """Object List Control Point characteristic (0x2AC6). 

72 

73 org.bluetooth.characteristic.object_list_control_point 

74 

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 """ 

79 

80 _manual_role = CharacteristicRole.CONTROL 

81 min_length: int = 1 # At minimum: opcode (1 byte) 

82 allow_variable_length: bool = True 

83 

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. 

92 

93 Args: 

94 data: Raw bytes (1+ bytes). 

95 ctx: Optional CharacteristicContext. 

96 validate: Whether to validate ranges (default True). 

97 

98 Returns: 

99 OLCPData with opcode and parameters. 

100 

101 """ 

102 opcode = OLCPOpcode(DataParser.parse_int8(data, 0, signed=False)) 

103 parameters = bytes(data[1:]) 

104 return OLCPData(opcode=opcode, parameters=parameters) 

105 

106 def _encode_value(self, data: OLCPData) -> bytearray: 

107 """Encode OLCP data to bytes. 

108 

109 Args: 

110 data: OLCPData to encode. 

111 

112 Returns: 

113 Encoded bytes. 

114 

115 """ 

116 result = DataParser.encode_int8(int(data.opcode), signed=False) 

117 result.extend(data.parameters) 

118 return result