Coverage for src / bluetooth_sig / gatt / characteristics / blood_pressure_feature.py: 100%
36 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-18 11:17 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-18 11:17 +0000
1"""Blood Pressure Feature characteristic implementation."""
3from __future__ import annotations
5from enum import IntFlag
7import msgspec
9from ..constants import UINT16_MAX
10from ..context import CharacteristicContext
11from .base import BaseCharacteristic
12from .utils import DataParser
15class BloodPressureFeatures(IntFlag):
16 """Blood Pressure Feature flags as per Bluetooth SIG specification."""
18 BODY_MOVEMENT_DETECTION = 0x01
19 CUFF_FIT_DETECTION = 0x02
20 IRREGULAR_PULSE_DETECTION = 0x04
21 PULSE_RATE_RANGE_DETECTION = 0x08
22 MEASUREMENT_POSITION_DETECTION = 0x10
23 MULTIPLE_BOND_SUPPORT = 0x20
26class BloodPressureFeatureData(msgspec.Struct, frozen=True, kw_only=True): # pylint: disable=too-few-public-methods
27 """Parsed data from Blood Pressure Feature characteristic."""
29 features_bitmap: int
30 body_movement_detection_support: bool
31 cuff_fit_detection_support: bool
32 irregular_pulse_detection_support: bool
33 pulse_rate_range_detection_support: bool
34 measurement_position_detection_support: bool
35 multiple_bond_support: bool
38class BloodPressureFeatureCharacteristic(BaseCharacteristic[BloodPressureFeatureData]):
39 """Blood Pressure Feature characteristic (0x2A49).
41 Used to expose the supported features of a blood pressure monitoring
42 device. Indicates which optional measurements and capabilities are
43 available.
44 """
46 # YAML has no range constraint; enforce full uint16 bitmap range.
47 min_value: int = 0
48 max_value: int = UINT16_MAX
50 def _decode_value(
51 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True
52 ) -> BloodPressureFeatureData:
53 """Parse blood pressure feature data according to Bluetooth specification.
55 Format: Features(2) - 16-bit bitmap indicating supported features.
57 Args:
58 data: Raw bytearray from BLE characteristic.
59 ctx: Optional CharacteristicContext providing surrounding context (may be None).
60 validate: Whether to validate ranges (default True)
62 Returns:
63 BloodPressureFeatureData containing parsed feature bitmap and capabilities.
65 """
66 features_bitmap = DataParser.parse_int16(data, 0, signed=False)
68 body_movement_detection = bool(features_bitmap & BloodPressureFeatures.BODY_MOVEMENT_DETECTION)
69 cuff_fit_detection = bool(features_bitmap & BloodPressureFeatures.CUFF_FIT_DETECTION)
70 irregular_pulse_detection = bool(features_bitmap & BloodPressureFeatures.IRREGULAR_PULSE_DETECTION)
71 pulse_rate_range_detection = bool(features_bitmap & BloodPressureFeatures.PULSE_RATE_RANGE_DETECTION)
72 measurement_position_detection = bool(features_bitmap & BloodPressureFeatures.MEASUREMENT_POSITION_DETECTION)
73 multiple_bond_support = bool(features_bitmap & BloodPressureFeatures.MULTIPLE_BOND_SUPPORT)
75 return BloodPressureFeatureData(
76 features_bitmap=features_bitmap,
77 body_movement_detection_support=body_movement_detection,
78 cuff_fit_detection_support=cuff_fit_detection,
79 irregular_pulse_detection_support=irregular_pulse_detection,
80 pulse_rate_range_detection_support=pulse_rate_range_detection,
81 measurement_position_detection_support=measurement_position_detection,
82 multiple_bond_support=multiple_bond_support,
83 )
85 def _encode_value(self, data: BloodPressureFeatureData) -> bytearray:
86 """Encode BloodPressureFeatureData back to bytes.
88 Args:
89 data: BloodPressureFeatureData instance to encode
92 Returns:
93 Encoded bytes representing the blood pressure features
95 """
96 return DataParser.encode_int16(data.features_bitmap, signed=False)