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

30 statements  

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

1"""Broadcast Audio Scan Control Point characteristic (0x2BC7).""" 

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 BroadcastAudioScanControlPointOpCode(IntEnum): 

16 """Broadcast Audio Scan Control Point operation codes.""" 

17 

18 REMOTE_SCAN_STOPPED = 0x00 

19 REMOTE_SCAN_STARTED = 0x01 

20 ADD_SOURCE = 0x02 

21 MODIFY_SOURCE = 0x03 

22 SET_BROADCAST_CODE = 0x04 

23 REMOVE_SOURCE = 0x05 

24 

25 

26class BroadcastAudioScanControlPointData(msgspec.Struct, frozen=True, kw_only=True): # pylint: disable=too-few-public-methods 

27 """Parsed data from Broadcast Audio Scan Control Point characteristic. 

28 

29 Contains the opcode and any additional parameters as raw bytes. 

30 """ 

31 

32 op_code: BroadcastAudioScanControlPointOpCode 

33 parameter_data: bytes = b"" 

34 

35 

36class BroadcastAudioScanControlPointCharacteristic(BaseCharacteristic[BroadcastAudioScanControlPointData]): 

37 """Broadcast Audio Scan Control Point characteristic (0x2BC7). 

38 

39 org.bluetooth.characteristic.broadcast_audio_scan_control_point 

40 

41 Used for controlling broadcast audio scanning in the Broadcast 

42 Audio Scan Service. 

43 """ 

44 

45 _manual_role = CharacteristicRole.CONTROL 

46 min_length = 1 

47 allow_variable_length = True 

48 

49 def _decode_value( 

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

51 ) -> BroadcastAudioScanControlPointData: 

52 """Parse Broadcast Audio Scan Control Point data. 

53 

54 Format: opcode (uint8) + optional parameters. 

55 """ 

56 op_code = BroadcastAudioScanControlPointOpCode(DataParser.parse_int8(data, 0, signed=False)) 

57 parameter_data = bytes(data[1:]) if len(data) > 1 else b"" 

58 

59 return BroadcastAudioScanControlPointData( 

60 op_code=op_code, 

61 parameter_data=parameter_data, 

62 ) 

63 

64 def _encode_value(self, data: BroadcastAudioScanControlPointData) -> bytearray: 

65 """Encode Broadcast Audio Scan Control Point data to bytes.""" 

66 result = bytearray() 

67 result += DataParser.encode_int8(int(data.op_code)) 

68 result += bytearray(data.parameter_data) 

69 return result