Source code for MovellaDot.profile

from __future__ import annotations

import struct


MOVELLA_NAME = "Movella DOT"
MOVELLA_DEVICE_CONTROL_UUID = "15171002-4947-11e9-8646-d663bd873d93"
MOVELLA_START_STOP_STREAM_UUID = "15172001-4947-11e9-8646-d663bd873d93"
MOVELLA_LONG_PAYLOAD_UUID = "15172002-4947-11e9-8646-d663bd873d93"
MOVELLA_SET_RATE_HEX = {
    20: "100000000000000B4D6F76656C6C6120444F5400000000001400000000000000",
    60: "100000000000000B4D6F76656C6C6120444F5400000000003C00000000000000",
}
MOVELLA_START_HEX = "01011A"
MOVELLA_STOP_HEX = "01001A"
MOVELLA_MIN_PACKET_LEN = 4
DEFAULT_STARTUP_GATE = {
    "enabled": True,
    "stability_window_seconds": 5.0,
    "packets_required": 60,
    "min_rate_hz": 58.0,
    "min_observation_seconds": 2.0,
    "max_gap_events": 0,
    "gap_grace_seconds": 2.0,
}
DEFAULT_LOCATIONS = [
    "LEFT_ANKLE",
    "RIGHT_ANKLE",
    "LEFT_THIGH",
    "RIGHT_THIGH",
    "CHEST",
    "LOWER_BACK",
    "HEAD",
    "UPPER_BACK",
    "LEFT_WRIST",
    "RIGHT_WRIST",
]


[docs] def parse_sensor_timestamp(payload: bytes) -> int: if len(payload) < MOVELLA_MIN_PACKET_LEN: raise ValueError(f"Movella payload too short: {len(payload)} bytes") return int(struct.unpack_from("<I", payload, 0)[0])
[docs] def select_addresses(matches, count: int) -> list[str]: if len(matches) < count: raise RuntimeError(f"Requested {count} Movella DOT sensors, found {len(matches)}") return [entry.address for entry in matches[:count]]