|
from fastapi import APIRouter, HTTPException, WebSocket |
|
|
|
from .core import RoboticsCore |
|
from .models import ( |
|
CreateRoomRequest, |
|
JointCommand, |
|
ParticipantRole, |
|
) |
|
|
|
|
|
|
|
robotics_router = APIRouter(prefix="/robotics", tags=["robotics"]) |
|
robotics_core = RoboticsCore() |
|
|
|
|
|
|
|
|
|
|
|
|
|
@robotics_router.get("/rooms") |
|
async def list_rooms_legacy(): |
|
"""List all robotics rooms (legacy - requires workspace)""" |
|
raise HTTPException( |
|
status_code=400, |
|
detail="Workspace ID required. Use /workspaces/{workspace_id}/rooms instead", |
|
) |
|
|
|
|
|
@robotics_router.get("/workspaces/{workspace_id}/rooms") |
|
async def list_rooms(workspace_id: str): |
|
"""List all robotics rooms in a workspace""" |
|
return { |
|
"success": True, |
|
"workspace_id": workspace_id, |
|
"rooms": robotics_core.list_rooms(workspace_id), |
|
"total": len(robotics_core.list_rooms(workspace_id)), |
|
} |
|
|
|
|
|
|
|
@robotics_router.post("/rooms") |
|
async def create_room_legacy(request: CreateRoomRequest | None = None): |
|
"""Create a new robotics room (legacy - creates random workspace)""" |
|
workspace_id = None |
|
room_id = None |
|
if request: |
|
workspace_id = request.workspace_id |
|
room_id = request.room_id |
|
|
|
workspace_id, room_id = robotics_core.create_room(workspace_id, room_id) |
|
|
|
return { |
|
"success": True, |
|
"workspace_id": workspace_id, |
|
"room_id": room_id, |
|
"message": f"Room {room_id} created successfully in workspace {workspace_id}", |
|
} |
|
|
|
|
|
@robotics_router.post("/workspaces/{workspace_id}/rooms") |
|
async def create_room(workspace_id: str, request: CreateRoomRequest | None = None): |
|
"""Create a new robotics room in a workspace""" |
|
room_id = None |
|
if request and hasattr(request, "room_id"): |
|
room_id = request.room_id |
|
|
|
actual_workspace_id, room_id = robotics_core.create_room(workspace_id, room_id) |
|
|
|
return { |
|
"success": True, |
|
"workspace_id": actual_workspace_id, |
|
"room_id": room_id, |
|
"message": f"Room {room_id} created successfully in workspace {actual_workspace_id}", |
|
} |
|
|
|
|
|
@robotics_router.get("/workspaces/{workspace_id}/rooms/{room_id}") |
|
async def get_room(workspace_id: str, room_id: str): |
|
"""Get room details""" |
|
room_info = robotics_core.get_room_info(workspace_id, room_id) |
|
if "error" in room_info: |
|
raise HTTPException(status_code=404, detail="Room not found") |
|
|
|
return {"success": True, "room": room_info} |
|
|
|
|
|
@robotics_router.delete("/workspaces/{workspace_id}/rooms/{room_id}") |
|
async def delete_room(workspace_id: str, room_id: str): |
|
"""Delete a robotics room""" |
|
if robotics_core.delete_room(workspace_id, room_id): |
|
return { |
|
"success": True, |
|
"message": f"Room {room_id} deleted successfully from workspace {workspace_id}", |
|
} |
|
raise HTTPException(status_code=404, detail="Room not found") |
|
|
|
|
|
@robotics_router.get("/workspaces/{workspace_id}/rooms/{room_id}/state") |
|
async def get_room_state(workspace_id: str, room_id: str): |
|
"""Get current room state with joints and participants""" |
|
state = robotics_core.get_room_state(workspace_id, room_id) |
|
if "error" in state: |
|
raise HTTPException(status_code=404, detail="Room not found") |
|
|
|
return {"success": True, "state": state} |
|
|
|
|
|
|
|
|
|
|
|
@robotics_router.post("/workspaces/{workspace_id}/rooms/{room_id}/command") |
|
async def send_command(workspace_id: str, room_id: str, command: JointCommand): |
|
"""Send joint commands to a room""" |
|
room_info = robotics_core.get_room_info(workspace_id, room_id) |
|
if "error" in room_info: |
|
raise HTTPException(status_code=404, detail="Room not found") |
|
|
|
try: |
|
joints_data = [ |
|
{"name": j.name, "value": j.value, "speed": j.speed} for j in command.joints |
|
] |
|
changed = await robotics_core.send_command_to_room( |
|
workspace_id, room_id, joints_data |
|
) |
|
except ValueError as e: |
|
raise HTTPException(status_code=404) from e |
|
else: |
|
return { |
|
"success": True, |
|
"workspace_id": workspace_id, |
|
"room_id": room_id, |
|
"joints_updated": changed, |
|
"message": "Commands sent successfully", |
|
} |
|
|
|
|
|
|
|
|
|
|
|
@robotics_router.get("/status") |
|
async def get_status(): |
|
"""Get system status""" |
|
stats = robotics_core.get_connection_stats() |
|
return { |
|
"service": "robotics", |
|
"status": "active", |
|
"workspaces_count": stats["total_workspaces"], |
|
"rooms_count": stats["total_rooms"], |
|
"connections_count": stats["total_connections"], |
|
"version": "2.0.0", |
|
"supported_roles": [role.value for role in ParticipantRole], |
|
"supported_robot_types": ["so-arm100", "generic"], |
|
} |
|
|
|
|
|
@robotics_router.get("/health") |
|
async def health_check(): |
|
"""Health check endpoint""" |
|
return {"status": "healthy", "service": "robotics"} |
|
|
|
|
|
|
|
|
|
|
|
@robotics_router.websocket("/workspaces/{workspace_id}/rooms/{room_id}/ws") |
|
async def websocket_endpoint(websocket: WebSocket, workspace_id: str, room_id: str): |
|
"""WebSocket connection for real-time room communication""" |
|
await robotics_core.handle_websocket(websocket, workspace_id, room_id) |
|
|