import json import spade.agent import zmq from spade.behaviour import CyclicBehaviour from zmq.asyncio import Context from control_backend.agents import BaseAgent from control_backend.core.config import settings from control_backend.schemas.ri_message import SpeechCommand class RICommandAgent(BaseAgent): subsocket: zmq.Socket pubsocket: zmq.Socket address = "" bind = False def __init__( self, jid: str, password: str, port: int = 5222, verify_security: bool = False, address="tcp://localhost:0000", bind=False, ): super().__init__(jid, password, port, verify_security) self.address = address self.bind = bind class SendCommandsBehaviour(CyclicBehaviour): """Behaviour for sending commands received from the UI.""" async def run(self): """ Run the command publishing loop indefinetely. """ assert self.agent is not None # Get a message internally (with topic command) topic, body = await self.agent.subsocket.recv_multipart() # Try to get body try: body = json.loads(body) message = SpeechCommand.model_validate(body) # Send to the robot. await self.agent.pubsocket.send_json(message.model_dump()) except Exception as e: self.agent.logger.error("Error processing message: %s", e) class SendPythonCommandsBehaviour(CyclicBehaviour): """Behaviour for sending commands received from other Python agents.""" async def run(self): message: spade.agent.Message = await self.receive(timeout=0.1) if message and message.to == self.agent.jid: try: speech_command = SpeechCommand.model_validate_json(message.body) await self.agent.pubsocket.send_json(speech_command.model_dump()) except Exception as e: self.agent.logger.error("Error processing message: %s", e) async def setup(self): """ Setup the command agent """ self.logger.info("Setting up %s", self.jid) context = Context.instance() # To the robot self.pubsocket = context.socket(zmq.PUB) if self.bind: self.pubsocket.bind(self.address) else: self.pubsocket.connect(self.address) # Receive internal topics regarding commands self.subsocket = context.socket(zmq.SUB) self.subsocket.connect(settings.zmq_settings.internal_sub_address) self.subsocket.setsockopt(zmq.SUBSCRIBE, b"command") # Add behaviour to our agent commands_behaviour = self.SendCommandsBehaviour() self.add_behaviour(commands_behaviour) self.add_behaviour(self.SendPythonCommandsBehaviour()) self.logger.info("Finished setting up %s", self.jid)