"""REST endpoints backing the 3D motor-temperature dashboard (N1). Serves the motor name/mesh mapping + thresholds, and a one-shot temperature snapshot (the front-end's initial fetch fallback). The live stream is over /ws/motor-temps (dashboard/websockets/motor_temps.py). The 3D view itself is the static page at /static/temp3d/index.html. """ from __future__ import annotations import time from fastapi import APIRouter from Project.Sanad.dashboard.temp_motor_map import ( MOTOR_NAMES, MOTOR_TO_MESH, TEMP_HOT_THRESHOLD, TEMP_MAX, TEMP_MIN, TEMP_WARM_THRESHOLD, build_payload, ) router = APIRouter() def _get_arm(): """Lazy import — avoids a circular import on dashboard load.""" try: from Project.Sanad.main import arm # type: ignore return arm except Exception: return None @router.get("/mapping") async def motor_mapping(): """Motor id → name / mesh map + the temperature gradient thresholds.""" return { "motor_names": MOTOR_NAMES, "motor_to_mesh": MOTOR_TO_MESH, "thresholds": { "min": TEMP_MIN, "max": TEMP_MAX, "warm": TEMP_WARM_THRESHOLD, "hot": TEMP_HOT_THRESHOLD, }, } @router.get("/motors") async def motors_snapshot(): """One-shot motor temperature + position snapshot (Marcus payload shape).""" arm = _get_arm() temps: list = [] positions: list = [] if arm is not None: try: temps = arm.get_motor_temps() except Exception: temps = [] try: positions = arm.get_current_q() except Exception: positions = [] return build_payload(temps, positions, time.time())