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

25 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-18 11:17 +0000

1"""Precise Acceleration 3D characteristic implementation.""" 

2 

3from __future__ import annotations 

4 

5from ..context import CharacteristicContext 

6from .base import BaseCharacteristic 

7from .templates import VectorData 

8from .utils import DataParser 

9 

10_RESOLUTION = 0.001 # M=1, d=-3, b=0 -> 0.001 standard gravity 

11 

12 

13class PreciseAcceleration3DCharacteristic(BaseCharacteristic[VectorData]): 

14 """Precise Acceleration 3D characteristic (0x2C1E). 

15 

16 org.bluetooth.characteristic.precise_acceleration_3d 

17 

18 Represents a precise 3D acceleration measurement in standard gravity. 

19 Three fields: x, y, z (sint16 each, 0.001 gn resolution). 

20 """ 

21 

22 _characteristic_name: str | None = "Precise Acceleration 3D" 

23 resolution: float = _RESOLUTION 

24 expected_length: int = 6 # 3 x sint16 

25 min_length: int = 6 

26 

27 def _decode_value( 

28 self, data: bytearray, ctx: CharacteristicContext | None = None, *, validate: bool = True 

29 ) -> VectorData: 

30 """Parse precise 3D acceleration (3 x sint16). 

31 

32 Args: 

33 data: Raw bytes (6 bytes). 

34 ctx: Optional CharacteristicContext. 

35 validate: Whether to validate ranges (default True). 

36 

37 Returns: 

38 VectorData with x, y, z axis values in gn (standard gravity). 

39 

40 """ 

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

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

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

44 

45 return VectorData( 

46 x_axis=x_raw * _RESOLUTION, 

47 y_axis=y_raw * _RESOLUTION, 

48 z_axis=z_raw * _RESOLUTION, 

49 ) 

50 

51 def _encode_value(self, data: VectorData) -> bytearray: 

52 """Encode precise 3D acceleration. 

53 

54 Args: 

55 data: VectorData with x, y, z axis values in gn. 

56 

57 Returns: 

58 Encoded bytes (6 bytes). 

59 

60 """ 

61 x_raw = round(data.x_axis / _RESOLUTION) 

62 y_raw = round(data.y_axis / _RESOLUTION) 

63 z_raw = round(data.z_axis / _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