Coverage for src / bluetooth_sig / gatt / characteristics / ras_control_point.py: 100%

33 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-03 16:41 +0000

1"""RAS Control Point characteristic (0x2C17). 

2 

3Control point for Ranging Service operations. 

4 

5References: 

6 Bluetooth SIG Ranging Service 

7""" 

8 

9from __future__ import annotations 

10 

11from enum import IntEnum 

12 

13import msgspec 

14 

15from ...types.gatt_enums import CharacteristicRole 

16from ..context import CharacteristicContext 

17from .base import BaseCharacteristic 

18from .utils import DataParser 

19 

20 

21class RASControlPointOpCode(IntEnum): 

22 """RAS Control Point operation codes (RAS v1.0 Table 3.10).""" 

23 

24 GET_RANGING_DATA = 0x00 

25 ACK_RANGING_DATA = 0x01 

26 RETRIEVE_LOST_SEGMENTS = 0x02 

27 ABORT_OPERATION = 0x03 

28 SET_FILTER = 0x04 

29 

30 

31class RASControlPointResponseOpCode(IntEnum): 

32 """RAS Control Point response operation codes (RAS v1.0 Table 3.11).""" 

33 

34 COMPLETE_RANGING_DATA_RESPONSE = 0x00 

35 COMPLETE_LOST_SEGMENT_RESPONSE = 0x01 

36 RESPONSE_CODE = 0x02 

37 

38 

39class RASControlPointData(msgspec.Struct, frozen=True, kw_only=True): 

40 """Parsed data from RAS Control Point characteristic. 

41 

42 Attributes: 

43 opcode: RAS Control Point operation code. 

44 parameters: Raw parameter bytes. 

45 """ 

46 

47 opcode: RASControlPointOpCode 

48 parameters: bytes = b"" 

49 

50 

51class RASControlPointCharacteristic(BaseCharacteristic[RASControlPointData]): 

52 """RAS Control Point characteristic (0x2C17). 

53 

54 org.bluetooth.characteristic.ras_control_point 

55 

56 Control point for Ranging Service operations. 

57 """ 

58 

59 _manual_role = CharacteristicRole.CONTROL 

60 min_length = 1 

61 allow_variable_length = True 

62 

63 def _decode_value( 

64 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True 

65 ) -> RASControlPointData: 

66 """Parse RAS Control Point data. 

67 

68 Format: OpCode (uint8) + Parameters (variable). 

69 """ 

70 opcode = RASControlPointOpCode(DataParser.parse_int8(data, 0, signed=False)) 

71 parameters = bytes(data[1:]) 

72 

73 return RASControlPointData( 

74 opcode=opcode, 

75 parameters=parameters, 

76 ) 

77 

78 def _encode_value(self, data: RASControlPointData) -> bytearray: 

79 """Encode RAS Control Point data.""" 

80 result = bytearray() 

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

82 result.extend(data.parameters) 

83 return result