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
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-03 16:41 +0000
1"""User Control Point characteristic (0x2A9F).
3Control point for the User Data Service.
5References:
6 Bluetooth SIG User Data Service 1.0
7"""
9from __future__ import annotations
11from enum import IntEnum
13import msgspec
15from ..context import CharacteristicContext
16from .base import BaseCharacteristic
17from .utils import DataParser
20class UserControlPointOpCode(IntEnum):
21 """User Control Point Op Codes."""
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
31class UserControlPointData(msgspec.Struct, frozen=True, kw_only=True):
32 """Parsed data from User Control Point.
34 Attributes:
35 opcode: The operation code.
36 parameter: Raw parameter bytes (variable per opcode). Empty if none.
38 """
40 opcode: UserControlPointOpCode
41 parameter: bytes = b""
44class UserControlPointCharacteristic(BaseCharacteristic[UserControlPointData]):
45 """User Control Point characteristic (0x2A9F).
47 org.bluetooth.characteristic.user_control_point
49 Control point for user management in the User Data Service.
50 """
52 min_length = 1
53 allow_variable_length = True
55 def _decode_value(
56 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True
57 ) -> UserControlPointData:
58 """Parse User Control Point data.
60 Format: OpCode (uint8) + Parameter (variable).
61 """
62 opcode = UserControlPointOpCode(DataParser.parse_int8(data, 0, signed=False))
63 parameter = bytes(data[1:])
65 return UserControlPointData(
66 opcode=opcode,
67 parameter=parameter,
68 )
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