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

28 statements  

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

1"""User Control Point characteristic (0x2A9F). 

2 

3Control point for the User Data Service. 

4 

5References: 

6 Bluetooth SIG User Data Service 1.0 

7""" 

8 

9from __future__ import annotations 

10 

11from enum import IntEnum 

12 

13import msgspec 

14 

15from ..context import CharacteristicContext 

16from .base import BaseCharacteristic 

17from .utils import DataParser 

18 

19 

20class UserControlPointOpCode(IntEnum): 

21 """User Control Point Op Codes.""" 

22 

23 REGISTER_NEW_USER = 0x01 

24 CONSENT = 0x02 

25 DELETE_USER_DATA = 0x03 

26 LIST_ALL_USERS = 0x04 

27 DELETE_USER = 0x05 

28 RESPONSE = 0x20 

29 

30 

31class UserControlPointData(msgspec.Struct, frozen=True, kw_only=True): 

32 """Parsed data from User Control Point. 

33 

34 Attributes: 

35 opcode: The operation code. 

36 parameter: Raw parameter bytes (variable per opcode). Empty if none. 

37 

38 """ 

39 

40 opcode: UserControlPointOpCode 

41 parameter: bytes = b"" 

42 

43 

44class UserControlPointCharacteristic(BaseCharacteristic[UserControlPointData]): 

45 """User Control Point characteristic (0x2A9F). 

46 

47 org.bluetooth.characteristic.user_control_point 

48 

49 Control point for user management in the User Data Service. 

50 """ 

51 

52 min_length = 1 

53 allow_variable_length = True 

54 

55 def _decode_value( 

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

57 ) -> UserControlPointData: 

58 """Parse User Control Point data. 

59 

60 Format: OpCode (uint8) + Parameter (variable). 

61 """ 

62 opcode = UserControlPointOpCode(DataParser.parse_int8(data, 0, signed=False)) 

63 parameter = bytes(data[1:]) 

64 

65 return UserControlPointData( 

66 opcode=opcode, 

67 parameter=parameter, 

68 ) 

69 

70 def _encode_value(self, data: UserControlPointData) -> bytearray: 

71 """Encode User Control Point data.""" 

72 result = bytearray() 

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

74 result.extend(data.parameter) 

75 return result