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
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-03 16:41 +0000
1"""PLX Features characteristic implementation."""
3from __future__ import annotations
5from enum import IntFlag
7from bluetooth_sig.gatt.context import CharacteristicContext
9from .base import BaseCharacteristic
10from .utils import DataParser
13class PLXFeatureFlags(IntFlag):
14 """PLX Features flags per Bluetooth SIG specification.
16 Spec: Bluetooth SIG Assigned Numbers, PLX Features characteristic
17 """
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
30class PLXFeaturesCharacteristic(BaseCharacteristic[PLXFeatureFlags]):
31 """PLX Features characteristic (0x2A60).
33 Describes the supported features of a pulse oximeter device.
34 Returns a 16-bit feature flags value.
36 Spec: Bluetooth SIG Assigned Numbers, PLX Features characteristic
37 """
39 _is_bitfield = True
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
47 def _decode_value(
48 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True
49 ) -> PLXFeatureFlags:
50 """Decode PLX features from raw bytes.
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)
57 Returns:
58 PLXFeatureFlags enum with supported features
60 """
61 del ctx # Unused parameter
63 raw_value = DataParser.parse_int16(data, 0, signed=False)
64 return PLXFeatureFlags(raw_value)
66 def _encode_value(self, data: PLXFeatureFlags | int) -> bytearray:
67 """Encode PLX features to bytes.
69 Args:
70 data: PLXFeatureFlags enum or 16-bit feature flags as integer
72 Returns:
73 Encoded bytes (2 bytes, little-endian)
75 """
76 value = data.value if isinstance(data, PLXFeatureFlags) else data
77 return DataParser.encode_int16(value, signed=False)