from enum import StrEnum CONTROLLER_SCHEMA_VERSION = "controller-job.v1" RUN_LOG_SCHEMA_VERSION = "run-log.v1" MANUAL_SESSION_SCHEMA_VERSION = "manual-session-log.v1" MACHINE_CAPABILITIES_SCHEMA_VERSION = "machine-capabilities.v1" MACHINE_ID = "fullum-alpha" CONTROLLER_VERSION_PREFIX = "polisher-control/" class SpindleDirection(StrEnum): """Toolhead spindle rotation direction using stable protocol/schema values. Physical convention: clockwise/counter-clockwise are as viewed from above the toolhead looking down toward the mirror/tool contact. ODrive sign mapping is a commissioning item and must be configured so these UI/protocol values match the observed tool rotation. """ CLOCKWISE = "cw" COUNTER_CLOCKWISE = "ccw" @classmethod def allowed_values(cls) -> list[str]: return [direction.value for direction in cls] _SPINDLE_DIRECTION_ALIASES = { "cw": SpindleDirection.CLOCKWISE, "clockwise": SpindleDirection.CLOCKWISE, "c.w.": SpindleDirection.CLOCKWISE, "ccw": SpindleDirection.COUNTER_CLOCKWISE, "counterclockwise": SpindleDirection.COUNTER_CLOCKWISE, "counter-clockwise": SpindleDirection.COUNTER_CLOCKWISE, "counter_clockwise": SpindleDirection.COUNTER_CLOCKWISE, "anticlockwise": SpindleDirection.COUNTER_CLOCKWISE, } def normalize_spindle_direction(value: str | SpindleDirection) -> SpindleDirection: """Normalize UI/protocol aliases to a SpindleDirection enum.""" if isinstance(value, SpindleDirection): return value key = value.strip().lower() try: return _SPINDLE_DIRECTION_ALIASES[key] except KeyError as exc: allowed = ", ".join(SpindleDirection.allowed_values()) raise ValueError(f"Unsupported spindle direction {value!r}; expected one of: {allowed}") from exc