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
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-18 11:17 +0000
1"""Precise Acceleration 3D characteristic implementation."""
3from __future__ import annotations
5from ..context import CharacteristicContext
6from .base import BaseCharacteristic
7from .templates import VectorData
8from .utils import DataParser
10_RESOLUTION = 0.001 # M=1, d=-3, b=0 -> 0.001 standard gravity
13class PreciseAcceleration3DCharacteristic(BaseCharacteristic[VectorData]):
14 """Precise Acceleration 3D characteristic (0x2C1E).
16 org.bluetooth.characteristic.precise_acceleration_3d
18 Represents a precise 3D acceleration measurement in standard gravity.
19 Three fields: x, y, z (sint16 each, 0.001 gn resolution).
20 """
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
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).
32 Args:
33 data: Raw bytes (6 bytes).
34 ctx: Optional CharacteristicContext.
35 validate: Whether to validate ranges (default True).
37 Returns:
38 VectorData with x, y, z axis values in gn (standard gravity).
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)
45 return VectorData(
46 x_axis=x_raw * _RESOLUTION,
47 y_axis=y_raw * _RESOLUTION,
48 z_axis=z_raw * _RESOLUTION,
49 )
51 def _encode_value(self, data: VectorData) -> bytearray:
52 """Encode precise 3D acceleration.
54 Args:
55 data: VectorData with x, y, z axis values in gn.
57 Returns:
58 Encoded bytes (6 bytes).
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)
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