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

1"""Magnetic Flux Density 3D characteristic implementation.""" 

2 

3from __future__ import annotations 

4 

5from typing import ClassVar 

6 

7from ...types.units import PhysicalUnit 

8from ..context import CharacteristicContext 

9from .base import BaseCharacteristic 

10from .templates import VectorData 

11from .utils import DataParser 

12 

13 

14class MagneticFluxDensity3DCharacteristic(BaseCharacteristic[VectorData]): 

15 """Magnetic Flux Density - 3D characteristic (0x2AA1). 

16 

17 org.bluetooth.characteristic.magnetic_flux_density_3d 

18 

19 Magnetic flux density 3D characteristic. 

20 

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. 

24 

25 Format: 3 x sint16 (6 bytes total) with 1e-7 Tesla resolution. 

26 """ 

27 

28 _characteristic_name: str | None = "Magnetic Flux Density - 3D" 

29 _manual_unit: str | None = PhysicalUnit.TESLA.value # Override template's "units" default 

30 

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 

35 

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). 

40 

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) 

45 

46 Returns: 

47 VectorData with x, y, z axis values in Tesla. 

48 

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) 

56 

57 return VectorData( 

58 x_axis=x_raw * self.resolution, y_axis=y_raw * self.resolution, z_axis=z_raw * self.resolution 

59 ) 

60 

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) 

66 

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