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

26 statements  

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

1"""PLX Features characteristic implementation.""" 

2 

3from __future__ import annotations 

4 

5from enum import IntFlag 

6 

7from bluetooth_sig.gatt.context import CharacteristicContext 

8 

9from .base import BaseCharacteristic 

10from .utils import DataParser 

11 

12 

13class PLXFeatureFlags(IntFlag): 

14 """PLX Features flags per Bluetooth SIG specification. 

15 

16 Spec: Bluetooth SIG Assigned Numbers, PLX Features characteristic 

17 """ 

18 

19 MEASUREMENT_STATUS_SUPPORT = 0x0001 

20 DEVICE_AND_SENSOR_STATUS_SUPPORT = 0x0002 

21 MEASUREMENT_STORAGE_SUPPORT = 0x0004 

22 TIMESTAMP_SUPPORT = 0x0008 

23 SPO2PR_FAST_SUPPORT = 0x0010 

24 SPO2PR_SLOW_SUPPORT = 0x0020 

25 PULSE_AMPLITUDE_INDEX_SUPPORT = 0x0040 

26 MULTIPLE_BONDS_SUPPORT = 0x0080 

27 # Bits 8-15 are reserved for future use 

28 

29 

30class PLXFeaturesCharacteristic(BaseCharacteristic[PLXFeatureFlags]): 

31 """PLX Features characteristic (0x2A60). 

32 

33 Describes the supported features of a pulse oximeter device. 

34 Returns a 16-bit feature flags value. 

35 

36 Spec: Bluetooth SIG Assigned Numbers, PLX Features characteristic 

37 """ 

38 

39 _is_bitfield = True 

40 

41 # PLXS v1.0.1 Table 3.8: 2-byte features + optional 2-byte Measurement Status 

42 # Support (if bit 0 set) + optional 3-byte Device/Sensor Status Support (if bit 1 set) 

43 min_length: int | None = 2 

44 max_length: int | None = 7 

45 allow_variable_length: bool = True 

46 

47 def _decode_value( 

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

49 ) -> PLXFeatureFlags: 

50 """Decode PLX features from raw bytes. 

51 

52 Args: 

53 data: Raw bytes from BLE characteristic (2 bytes) 

54 ctx: Unused, for signature compatibility 

55 validate: Whether to validate ranges (default True) 

56 

57 Returns: 

58 PLXFeatureFlags enum with supported features 

59 

60 """ 

61 del ctx # Unused parameter 

62 

63 raw_value = DataParser.parse_int16(data, 0, signed=False) 

64 return PLXFeatureFlags(raw_value) 

65 

66 def _encode_value(self, data: PLXFeatureFlags | int) -> bytearray: 

67 """Encode PLX features to bytes. 

68 

69 Args: 

70 data: PLXFeatureFlags enum or 16-bit feature flags as integer 

71 

72 Returns: 

73 Encoded bytes (2 bytes, little-endian) 

74 

75 """ 

76 value = data.value if isinstance(data, PLXFeatureFlags) else data 

77 return DataParser.encode_int16(value, signed=False)