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

29 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-30 00:10 +0000

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

2 

3from __future__ import annotations 

4 

5from ...types.gatt_enums import ValueType 

6from ...types.units import PhysicalUnit 

7from ..context import CharacteristicContext 

8from .base import BaseCharacteristic 

9from .templates import VectorData 

10from .utils import DataParser 

11 

12 

13class MagneticFluxDensity3DCharacteristic(BaseCharacteristic): 

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

15 

16 org.bluetooth.characteristic.magnetic_flux_density_3d 

17 

18 Magnetic flux density 3D characteristic. 

19 

20 Represents measurements of magnetic flux density for three 

21 orthogonal axes: X, Y, and Z. Note that 1 x 10^-7 Tesla equals 0.001 

22 Gauss. 

23 

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

25 """ 

26 

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

28 _manual_value_type: ValueType | str | None = ValueType.STRING # Override since decode_value returns dict 

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

30 

31 _vector_components: list[str] = ["x_axis", "y_axis", "z_axis"] 

32 resolution: float = 1e-7 

33 

34 def decode_value(self, data: bytearray, ctx: CharacteristicContext | None = None) -> VectorData: 

35 """Parse 3D magnetic flux density (3 x sint16 with resolution). 

36 

37 Args: 

38 data: Raw bytearray from BLE characteristic. 

39 ctx: Optional CharacteristicContext providing surrounding context (may be None). 

40 

41 Returns: 

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

43 

44 # Parameter `ctx` is part of the public API but unused in this implementation. 

45 # Explicitly delete it to satisfy linters. 

46 del ctx 

47 """ 

48 if len(data) < 6: 

49 raise ValueError("Insufficient data for 3D magnetic flux density (need 6 bytes)") 

50 

51 x_raw = DataParser.parse_int16(data, 0, signed=True) 

52 y_raw = DataParser.parse_int16(data, 2, signed=True) 

53 z_raw = DataParser.parse_int16(data, 4, signed=True) 

54 

55 return VectorData( 

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

57 ) 

58 

59 def encode_value(self, data: VectorData) -> bytearray: 

60 """Encode 3D magnetic flux density.""" 

61 x_raw = int(data.x_axis / self.resolution) 

62 y_raw = int(data.y_axis / self.resolution) 

63 z_raw = int(data.z_axis / self.resolution) 

64 

65 result = bytearray() 

66 result.extend(DataParser.encode_int16(x_raw, signed=True)) 

67 result.extend(DataParser.encode_int16(y_raw, signed=True)) 

68 result.extend(DataParser.encode_int16(z_raw, signed=True)) 

69 return result