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

25 statements  

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

1"""GHS Control Point characteristic (0x2BF4). 

2 

3Control point for the Generic Health Sensor service. 

4 

5References: 

6 Bluetooth SIG Generic Health Sensor Service specification 

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

21 """GHS Control Point Op Codes.""" 

22 

23 START_SEND_LIVE_OBSERVATIONS = 0x01 

24 STOP_SEND_LIVE_OBSERVATIONS = 0x02 

25 RESPONSE_CODE = 0x80 

26 

27 

28class GHSControlPointData(msgspec.Struct, frozen=True, kw_only=True): 

29 """Parsed data from GHS Control Point. 

30 

31 Attributes: 

32 opcode: The operation code. 

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

34 

35 """ 

36 

37 opcode: GHSControlPointOpCode 

38 parameter: bytes = b"" 

39 

40 

41class GHSControlPointCharacteristic(BaseCharacteristic[GHSControlPointData]): 

42 """GHS Control Point characteristic (0x2BF4). 

43 

44 org.bluetooth.characteristic.ghs_control_point 

45 

46 Control point for managing observations in the Generic Health 

47 Sensor service. 

48 """ 

49 

50 min_length = 1 

51 allow_variable_length = True 

52 

53 def _decode_value( 

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

55 ) -> GHSControlPointData: 

56 """Parse GHS Control Point data. 

57 

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

59 """ 

60 opcode = GHSControlPointOpCode(DataParser.parse_int8(data, 0, signed=False)) 

61 parameter = bytes(data[1:]) 

62 

63 return GHSControlPointData( 

64 opcode=opcode, 

65 parameter=parameter, 

66 ) 

67 

68 def _encode_value(self, data: GHSControlPointData) -> bytearray: 

69 """Encode GHS Control Point data.""" 

70 result = bytearray() 

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

72 result.extend(data.parameter) 

73 return result