from pydantic import BaseModel, Field class ElevatorStatusUpdate(BaseModel): Floor: int = Field(..., description="Current floor (1-10)", ge=1, le=10) Dir: str = Field(..., description="Direction: UP, DOWN, or IDLE") Doors: str = Field(..., description="Door state: CLOSED, OPENING, OPEN, CLOSING") State: str = Field(..., description="FSM state: IDLE, MOVING, DOORS_OPENING, DOORS_OPEN, DOORS_CLOSING") class ElevatorCommandRequest(BaseModel): floor: int = Field(..., description="Target floor (1-10)", ge=1, le=10) class ElevatorCommandResponse(BaseModel): cmd: str = Field(..., description="Command string e.g. CALL_3, or NONE") class ElevatorStateResponse(BaseModel): Floor: int = Field(..., description="Current floor") Dir: str = Field(..., description="Direction") Doors: str = Field(..., description="Door state") State: str = Field(..., description="FSM state") class RobotPose(BaseModel): x: float = Field(..., description="X position in meters") y: float = Field(..., description="Y position in meters") theta: float = Field(..., description="Heading in radians") class RobotStatusUpdate(BaseModel): state: str = Field(..., description="Nav state: IDLE, NAVIGATING, ARRIVED, ERROR") floor: int = Field(..., description="Robot's current floor", ge=1, le=10) pose: RobotPose = Field(..., description="Current robot pose") class RobotGoalRequest(BaseModel): floor: int = Field(..., description="Target floor (1-10)", ge=1, le=10) pose: RobotPose = Field(..., description="Target pose on the floor") class RobotGoalResponse(BaseModel): goal: RobotGoalRequest | None = Field(..., description="Nav goal or null on timeout") class RobotStateResponse(BaseModel): state: str = Field(..., description="Nav state") floor: int = Field(..., description="Robot's current floor") pose: RobotPose = Field(..., description="Current robot pose") class LockerCommandRequest(BaseModel): locker_id: int = Field(..., description="Locker number", ge=1) action: str = Field(..., description="open, close, or pulse") duration_ms: int = Field(3000, description="Pulse duration in milliseconds", ge=100, le=60000) class LockerCommandResponse(BaseModel): ok: bool = Field(..., description="Whether command was accepted") command: dict | None = Field(None, description="Command payload for Jetson, or null on timeout")