From daf31ac6a6d349be82ae7f52bc1c0db280828859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Otgaar?= Date: Mon, 15 Dec 2025 11:35:56 +0100 Subject: [PATCH] fix: change the address to the config, update some logic, seperate the api endpoint, renaming things. yes, the tests don't work right now- this shouldn't be merged yet. ref: N25B-334 --- .../agents/actuation/robot_gesture_agent.py | 7 +-- .../agents/actuation/robot_speech_agent.py | 2 +- src/control_backend/api/v1/endpoints/robot.py | 60 +++++++++++++------ src/control_backend/core/config.py | 1 + 4 files changed, 45 insertions(+), 25 deletions(-) diff --git a/src/control_backend/agents/actuation/robot_gesture_agent.py b/src/control_backend/agents/actuation/robot_gesture_agent.py index 6830874..cd195c1 100644 --- a/src/control_backend/agents/actuation/robot_gesture_agent.py +++ b/src/control_backend/agents/actuation/robot_gesture_agent.py @@ -36,10 +36,7 @@ class RobotGestureAgent(BaseAgent): bind=False, gesture_data=None, ): - if gesture_data is None: - self.gesture_data = [] - else: - self.gesture_data = gesture_data + self.gesture_data = gesture_data or [] super().__init__(name) self.address = address self.bind = bind @@ -71,7 +68,7 @@ class RobotGestureAgent(BaseAgent): # REP socket for replying to gesture requests self.repsocket = context.socket(zmq.REP) - self.repsocket.bind("tcp://localhost:7788") + self.repsocket.bind(settings.zmq_settings.internal_gesture_rep_adress) self.add_behavior(self._zmq_command_loop()) self.add_behavior(self._fetch_gestures_loop()) diff --git a/src/control_backend/agents/actuation/robot_speech_agent.py b/src/control_backend/agents/actuation/robot_speech_agent.py index 674b270..f8e3d4c 100644 --- a/src/control_backend/agents/actuation/robot_speech_agent.py +++ b/src/control_backend/agents/actuation/robot_speech_agent.py @@ -29,7 +29,7 @@ class RobotSpeechAgent(BaseAgent): def __init__( self, name: str, - address=settings.zmq_settings.ri_command_address, + address: str, bind=False, ): super().__init__(name) diff --git a/src/control_backend/api/v1/endpoints/robot.py b/src/control_backend/api/v1/endpoints/robot.py index b34e171..517068b 100644 --- a/src/control_backend/api/v1/endpoints/robot.py +++ b/src/control_backend/api/v1/endpoints/robot.py @@ -16,14 +16,40 @@ logger = logging.getLogger(__name__) router = APIRouter() -@router.post("/command", status_code=202) -async def receive_command(command: SpeechCommand, request: Request): +@router.post("/command/speech", status_code=202) +async def receive_command_speech(command: SpeechCommand, request: Request): """ Send a direct speech command to the robot. Publishes the command to the internal 'command' topic. The :class:`~control_backend.agents.actuation.robot_speech_agent.RobotSpeechAgent` - or + will forward this to the robot. + + :param command: The speech command payload. + :param request: The FastAPI request object. + """ + # Validate and retrieve data. + try: + validated = SpeechCommand.model_validate(command) + except ValidationError as e: + raise HTTPException( + status_code=422, detail=f"Payload is not valid SpeechCommand: {e}" + ) from e + + topic = b"command" + + pub_socket: Socket = request.app.state.endpoints_pub_socket + await pub_socket.send_multipart([topic, validated.model_dump_json().encode()]) + + return {"status": "Speech command received"} + + +@router.post("/command/gesture", status_code=202) +async def receive_command_gesture(command: GestureCommand, request: Request): + """ + Send a direct gesture command to the robot. + + Publishes the command to the internal 'command' topic. The :class:`~control_backend.agents.actuation.robot_speech_agent.RobotGestureAgent` will forward this to the robot. @@ -31,23 +57,19 @@ async def receive_command(command: SpeechCommand, request: Request): :param request: The FastAPI request object. """ # Validate and retrieve data. - validated = None - valid_commands = (GestureCommand, SpeechCommand) - for command_model in valid_commands: - try: - validated = command_model.model_validate(command) - except ValidationError: - continue - - if validated is None: - raise HTTPException(status_code=422, detail="Payload is not valid for command models") + try: + validated = GestureCommand.model_validate(command) + except ValidationError as e: + raise HTTPException( + status_code=422, detail=f"Payload is not valid GestureCommand: {e}" + ) from e topic = b"command" pub_socket: Socket = request.app.state.endpoints_pub_socket await pub_socket.send_multipart([topic, validated.model_dump_json().encode()]) - return {"status": "Command received"} + return {"status": "Gesture command received"} @router.get("/ping_check") @@ -58,8 +80,8 @@ async def ping(request: Request): pass -@router.get("/get_available_gesture_tags") -async def get_available_gesture_tags(request: Request): +@router.get("/commands/gesture/tags") +async def get_available_gesture_tags(request: Request, count=0): """ Endpoint to retrieve the available gesture tags for the robot. @@ -67,10 +89,10 @@ async def get_available_gesture_tags(request: Request): :return: A list of available gesture tags. """ req_socket = Context.instance().socket(zmq.REQ) - req_socket.connect("tcp://localhost:7788") + req_socket.connect(request.app.state.gesture_rep_address) - # TODO: Implement a way to get a certain ammount from the UI, rather than everything. - amount = None + # Check to see if we've got any count given in the query parameter + amount = count or None timeout = 5 # seconds await req_socket.send(f"{amount}".encode() if amount else b"None") diff --git a/src/control_backend/core/config.py b/src/control_backend/core/config.py index 947a30d..2712d8a 100644 --- a/src/control_backend/core/config.py +++ b/src/control_backend/core/config.py @@ -17,6 +17,7 @@ class ZMQSettings(BaseModel): internal_sub_address: str = "tcp://localhost:5561" ri_command_address: str = "tcp://localhost:0000" ri_communication_address: str = "tcp://*:5555" + internal_gesture_rep_adress: str = "tcp://localhost:7788" class AgentSettings(BaseModel):