Coverage for src / bluetooth_sig / gatt / characteristics / magnetic_flux_density_3d.py: 100%
28 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"""Magnetic Flux Density 3D characteristic implementation."""
3from __future__ import annotations
5from typing import ClassVar
7from ...types.units import PhysicalUnit
8from ..context import CharacteristicContext
9from .base import BaseCharacteristic
10from .templates import VectorData
11from .utils import DataParser
14class MagneticFluxDensity3DCharacteristic(BaseCharacteristic[VectorData]):
15 """Magnetic Flux Density - 3D characteristic (0x2AA1).
17 org.bluetooth.characteristic.magnetic_flux_density_3d
19 Magnetic flux density 3D characteristic.
21 Represents measurements of magnetic flux density for three
22 orthogonal axes: X, Y, and Z. Note that 1 x 10^-7 Tesla equals 0.001
23 Gauss.
25 Format: 3 x sint16 (6 bytes total) with 1e-7 Tesla resolution.
26 """
28 _characteristic_name: str | None = "Magnetic Flux Density - 3D"
29 _manual_unit: str | None = PhysicalUnit.TESLA.value # Override template's "units" default
31 _vector_components: ClassVar[list[str]] = ["x_axis", "y_axis", "z_axis"]
32 resolution: float = 1e-7
33 expected_length: int = 6 # 3 x sint16
34 min_length: int = 6
36 def _decode_value(
37 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True
38 ) -> VectorData:
39 """Parse 3D magnetic flux density (3 x sint16 with resolution).
41 Args:
42 data: Raw bytearray from BLE characteristic.
43 ctx: Optional CharacteristicContext providing surrounding context (may be None).
44 validate: Whether to validate ranges (default True)
46 Returns:
47 VectorData with x, y, z axis values in Tesla.
49 # Parameter `ctx` is part of the public API but unused in this implementation.
50 # Explicitly delete it to satisfy linters.
51 del ctx
52 """
53 x_raw = DataParser.parse_int16(data, 0, signed=True)
54 y_raw = DataParser.parse_int16(data, 2, signed=True)
55 z_raw = DataParser.parse_int16(data, 4, signed=True)
57 return VectorData(
58 x_axis=x_raw * self.resolution, y_axis=y_raw * self.resolution, z_axis=z_raw * self.resolution
59 )
61 def _encode_value(self, data: VectorData) -> bytearray:
62 """Encode 3D magnetic flux density."""
63 x_raw = int(data.x_axis / self.resolution)
64 y_raw = int(data.y_axis / self.resolution)
65 z_raw = int(data.z_axis / self.resolution)
67 result = bytearray()
68 result.extend(DataParser.encode_int16(x_raw, signed=True))
69 result.extend(DataParser.encode_int16(y_raw, signed=True))
70 result.extend(DataParser.encode_int16(z_raw, signed=True))
71 return result