importjsonimportloggingfromspade.behaviourimportCyclicBehaviourfrombehaviours.HandleNegotiationBehaviourimportHandleNegotiationBehaviourfrombehaviours.HandleSvcResponseBehaviourimportHandleSvcResponseBehaviourfromlogicimportNegotiation_utils,InterAASInteractions_utilsfromutilities.AASmanagerInfoimportAASmanagerInfo_logger=logging.getLogger(__name__)# TODO analizar clase NegotiatingBehaviour de Alejandro para ver como manejaba las negociaciones entre agentes
[docs]classNegotiatingBehaviour(CyclicBehaviour):""" This class implements the behaviour that handles the negotiation requests made by other standardized AAS Managers through ACL messages in the I4.0 System. """def__init__(self,agent_object):""" The constructor method is rewritten to add the object of the agent Args: agent_object (spade.Agent): the SPADE agent object of the AAS Manager agent. """# The constructor of the inherited class is executed.super().__init__()# The SPADE agent object is stored as a variable of the behaviour classself.myagent=agent_object
[docs]asyncdefon_start(self):""" This method implements the initialization process of this behaviour. """_logger.info("NegotiationBehaviour starting...")
[docs]asyncdefrun(self):""" This method implements the logic of the behaviour. """# Wait for a message with the standard ACL template for negotiating to arrive.msg=awaitself.receive(timeout=10)# Timeout set to 10 seconds so as not to continuously execute the behavior.ifmsg:# An ACL message has been received by the agent_logger.aclinfo(" + Message received on AAS Manager Agent (NegotiatingBehaviour)")_logger.aclinfo(" |___ Message received with content: {}".format(msg.body))# The msg body will be parsed to a JSON objectmsg_json_body=json.loads(msg.body)# TODO quizas hay que comprobar que el thread no existe? Para hacer al igual que en la peticion de# servicios, utilizar el thread como identificador. Hay que pensarlo, ya que de este modo el thread# servirÃa para un unico servicio a un AAS# Depending on the performative of the message, the agent will have to perform some actions or othersmatchmsg.get_metadata('performative'):case"CallForProposal":_logger.aclinfo("The agent has received a request to start a negotiation (CFP) with thread ["+msg.thread+"]")# First, some useful information is obtained from the msgtargets_list=msg_json_body['serviceData']['serviceParams']['targets'].split(',')if'/'instr(msg.sender):# XMPP server can add a random string to differentiate the agent JIDneg_requester_jid=str(msg.sender).split('/')[0]else:neg_requester_jid=str(msg.sender)iflen(targets_list)==1:# There is only one target available (therefore, it is the only one, so it is the winner)_logger.info("The AAS has won the negotiation with thread ["+msg.thread+"]")# As the winner, it will reply to the sender with the result of the negotiationacl_response_msg=Negotiation_utils.create_neg_response_msg(receiver=neg_requester_jid,thread=msg.thread,service_id=msg_json_body['serviceID'],service_type=msg_json_body['serviceType'],winner=str(self.myagent.jid))awaitself.send(acl_response_msg)_logger.aclinfo("ACL response sent for the result of the negotiation request with thread ["+msg.thread+"]")# Finally, the data is stored in the AAS Managerneg_data_json=Negotiation_utils.create_neg_json_to_store(neg_requester_jid=neg_requester_jid,participants=msg_json_body['serviceData']['serviceParams']['targets'],neg_criteria=msg_json_body['serviceData']['serviceParams']['criteria'],is_winner=True)awaitself.myagent.save_negotiation_data(thread=msg.thread,neg_data=neg_data_json)else:# If there are more targets, a management behavior is added to the AAS Manager, which will be# in charge of this particular negotiation. To this end, some information has to be passed to# the behaviourneg_criteria=msg_json_body['serviceData']['serviceParams']['criteria']behaviour_info={'thread':msg.thread,'neg_requester_jid':neg_requester_jid,'targets':msg_json_body['serviceData']['serviceParams']['targets'],'neg_criteria':neg_criteria}# The FIPA-ACL template added to this behavior ensures that you will only receive PROPOSE# messages but also only with the thread of that specific threadhandle_neg_template=AASmanagerInfo.NEG_STANDARD_ACL_TEMPLATE_PROPOSEhandle_neg_template.thread=msg.threadhandle_neg_behav=HandleNegotiationBehaviour(self.agent,behaviour_info)self.myagent.add_behaviour(handle_neg_behav,handle_neg_template)case"Inform":_logger.aclinfo("The agent has received an Inter AAS interaction message related to a negotiation:"" Inform")ifmsg_json_body['serviceID']=='negotiationResult':_logger.aclinfo("The agent has received the result of the negotiation with thread ["+msg.thread+"].")# As the result of a negotiation is a response to a previous request, a new# HandleSvcResponseBehaviour to handle this service response will be added to the agentsvc_resp_data=InterAASInteractions_utils.create_svc_json_data_from_acl_msg(msg)svc_resp_handling_behav=HandleSvcResponseBehaviour(self.agent,'Inter AAS interaction',svc_resp_data)self.myagent.add_behaviour(svc_resp_handling_behav)else:# TODOprint('serviceID not available')# TODO pensar como se deberian gestionar este tipo de mensajes en una negociacioncase"Propose":_logger.aclinfo("The agent has received a response in a negotiation: Propose")# TODO en teoria estos mensajes nunca llegaran aqui, ya que lo recibira el behaviour encargado de# la negociacioncase"Failure":_logger.aclinfo("The agent has received a response in a negotiation: Failure")# TODO pensar como se deberian gestionar este tipo de mensajes en una negociacioncase_:_logger.error("ACL performative type not available.")else:_logger.info(" - No message received within 10 seconds on AAS Manager Agent (NegotiatingBehaviour)")