def handle(self, message: Message, sender: str) -> None: """ Implement the reaction to a message. :param message: the message :param sender: the sender :return: None """ # convenience representations fipa_msg = cast(FIPAMessage, message) msg_performative = FIPAMessage.Performative(message.get('performative')) message_id = cast(int, message.get("message_id")) # recover dialogue dialogues = cast(Dialogues, self.context.dialogues) if dialogues.is_belonging_to_registered_dialogue(fipa_msg, sender, self.context.agent_public_key): dialogue = cast(Dialogue, dialogues.get_dialogue(fipa_msg, sender, self.context.agent_public_key)) dialogue.incoming_extend(fipa_msg) else: self._handle_unidentified_dialogue(fipa_msg, sender) return # handle message if msg_performative == FIPAMessage.Performative.PROPOSE: self._handle_propose(fipa_msg, sender, message_id, dialogue) elif msg_performative == FIPAMessage.Performative.DECLINE: self._handle_decline(fipa_msg, sender, message_id, dialogue) elif msg_performative == FIPAMessage.Performative.MATCH_ACCEPT_W_ADDRESS: self._handle_match_accept(fipa_msg, sender, message_id, dialogue) elif msg_performative == FIPAMessage.Performative.INFORM: self._handle_inform(fipa_msg, sender, message_id, dialogue)
def _message_to_percept(self, message: Message) -> Feedback: """ Transform the message received from the gym environment into observation, reward, done, info. :param: the message received as a response to the action performed in apply_action. :return: the standard feedback (observation, reward, done, info) of a gym environment. """ observation = cast(Any, message.get("observation")) reward = cast(float, message.get("reward")) done = cast(bool, message.get("done")) info = cast(dict, message.get("info")) return observation, reward, done, info
def _update_self_initiated_dialogue_label_on_second_message( self, second_message: Message ) -> None: """ Update this (self initiated) dialogue's dialogue_label with a complete dialogue reference from counterparty's first message :param second_message: The second message in the dialogue (the first by the counterparty) :return: None """ dialogue_reference = cast( Tuple[str, str], second_message.get("dialogue_reference") ) self_initiated_dialogue_reference = (dialogue_reference[0], "") self_initiated_dialogue_label = DialogueLabel( self_initiated_dialogue_reference, second_message.counterparty, self.agent_address, ) if not self.is_empty: message_id = second_message.message_id if ( self.dialogue_label == self_initiated_dialogue_label and self.last_message.message_id == 1 # type: ignore and message_id == 2 and second_message.is_incoming ): updated_dialogue_label = DialogueLabel( dialogue_reference, self_initiated_dialogue_label.dialogue_opponent_addr, self_initiated_dialogue_label.dialogue_starter_addr, ) self._dialogue_label = updated_dialogue_label
def get_dialogue(self, fipa_msg: Message, sender: Address, agent_pbk: Address) -> Dialogue: """ Retrieve dialogue. :param fipa_msg: the fipa message :param sender_pbk: the sender public key :param agent_pbk: the public key of the agent :return: the dialogue """ fipa_msg = cast(FIPAMessage, fipa_msg) dialogue_reference = cast(Tuple[str, str], fipa_msg.get("dialogue_reference")) self_initiated_dialogue_label = DialogueLabel(dialogue_reference, sender, agent_pbk) other_initiated_dialogue_label = DialogueLabel(dialogue_reference, sender, sender) if other_initiated_dialogue_label in self.dialogues: other_initiated_dialogue = cast( FIPADialogue, self.dialogues[other_initiated_dialogue_label]) if other_initiated_dialogue.is_valid_next_message(fipa_msg): result = other_initiated_dialogue if self_initiated_dialogue_label in self.dialogues: self_initiated_dialogue = cast( FIPADialogue, self.dialogues[self_initiated_dialogue_label]) if self_initiated_dialogue.is_valid_next_message(fipa_msg): result = self_initiated_dialogue if result is None: raise ValueError('Should have found dialogue.') return result
def encode(self, msg: Message) -> bytes: """ Decode the message. :param msg: the message object :return: the bytes """ performative = GymMessage.Performative(msg.get("performative")) new_body = copy.copy(msg.body) new_body["performative"] = performative.value if performative == GymMessage.Performative.ACT: action = msg.body["action"] # type: Any action_bytes = base64.b64encode( pickle.dumps(action)).decode("utf-8") new_body["action"] = action_bytes new_body["step_id"] = msg.body["step_id"] elif performative == GymMessage.Performative.PERCEPT: # observation, reward and info are gym implementation specific, done is boolean observation = msg.body["observation"] # type: Any observation_bytes = base64.b64encode( pickle.dumps(observation)).decode("utf-8") new_body["observation"] = observation_bytes reward = msg.body["reward"] # type: Any reward_bytes = base64.b64encode( pickle.dumps(reward)).decode("utf-8") new_body["reward"] = reward_bytes info = msg.body["info"] # type: Any info_bytes = base64.b64encode(pickle.dumps(info)).decode("utf-8") new_body["info"] = info_bytes new_body["step_id"] = msg.body["step_id"] gym_message_bytes = json.dumps(new_body).encode("utf-8") return gym_message_bytes
def encode(self, msg: Message) -> bytes: """ Decode the message. :param msg: the message object :return: the bytes """ oef_type = OEFMessage.Type(msg.get("type")) new_body = copy.copy(msg.body) new_body["type"] = oef_type.value if oef_type in {OEFMessage.Type.REGISTER_SERVICE, OEFMessage.Type.UNREGISTER_SERVICE}: service_description = msg.body["service_description"] # type: Description service_description_bytes = base64.b64encode(pickle.dumps(service_description)).decode("utf-8") new_body["service_description"] = service_description_bytes elif oef_type in {OEFMessage.Type.REGISTER_AGENT, OEFMessage.Type.UNREGISTER_AGENT}: agent_description = msg.body["agent_description"] # type: Description agent_description_bytes = base64.b64encode(pickle.dumps(agent_description)).decode("utf-8") new_body["agent_description"] = agent_description_bytes elif oef_type in {OEFMessage.Type.SEARCH_SERVICES, OEFMessage.Type.SEARCH_AGENTS}: query = msg.body["query"] # type: Query query_bytes = base64.b64encode(pickle.dumps(query)).decode("utf-8") new_body["query"] = query_bytes elif oef_type in {OEFMessage.Type.SEARCH_RESULT}: # we need this cast because the "agents" field might contains # the Protobuf type "RepeatedScalarContainer", which is not JSON serializable. new_body["agents"] = list(msg.body["agents"]) elif oef_type in {OEFMessage.Type.OEF_ERROR}: operation = msg.body["operation"] new_body["operation"] = str(operation) oef_message_bytes = json.dumps(new_body).encode("utf-8") return oef_message_bytes
def _get_dialogue(self, message: Message) -> Optional[Dialogue]: """ Retrieve the dialogue 'message' belongs to. :param message: a message :return: the dialogue, or None in case such a dialogue does not exist """ dialogue_reference = cast(Tuple[str, str], message.get("dialogue_reference")) counterparty = message.counterparty self_initiated_dialogue_label = DialogueLabel( dialogue_reference, counterparty, self.agent_address ) other_initiated_dialogue_label = DialogueLabel( dialogue_reference, counterparty, counterparty ) if other_initiated_dialogue_label in self.dialogues: result = self.dialogues[ other_initiated_dialogue_label ] # type: Optional[Dialogue] elif self_initiated_dialogue_label in self.dialogues: result = self.dialogues[self_initiated_dialogue_label] else: result = None return result
def handle(self, message: Message) -> None: """ Implement the reaction to a message. :param message: the message :return: None """ # convenience representations fipa_msg = cast(FipaMessage, message) msg_performative = FipaMessage.Performative( message.get("performative")) # recover dialogue dialogues = cast(Dialogues, self.context.dialogues) if dialogues.is_belonging_to_registered_dialogue( fipa_msg, self.context.agent_address): dialogue = cast( Dialogue, dialogues.get_dialogue(fipa_msg, self.context.agent_address)) dialogue.incoming_extend(fipa_msg) else: self._handle_unidentified_dialogue(fipa_msg) return # handle message if msg_performative == FipaMessage.Performative.PROPOSE: self._handle_propose(fipa_msg, dialogue) elif msg_performative == FipaMessage.Performative.DECLINE: self._handle_decline(fipa_msg, dialogue) elif msg_performative == FipaMessage.Performative.MATCH_ACCEPT_W_INFORM: self._handle_match_accept(fipa_msg, dialogue) elif msg_performative == FipaMessage.Performative.INFORM: self._handle_inform(fipa_msg, dialogue)
def _update_self_initiated_dialogue_label_on_second_message( self, second_message: Message ) -> None: """ Update a self initiated dialogue label with a complete dialogue reference from counterparty's first message :param second_message: The second message in the dialogue (the first by the counterparty in a self initiated dialogue) :return: None """ dialogue_reference = cast( Tuple[str, str], second_message.get("dialogue_reference") ) self_initiated_dialogue_reference = (dialogue_reference[0], "") self_initiated_dialogue_label = DialogueLabel( self_initiated_dialogue_reference, second_message.counterparty, self.agent_address, ) if self_initiated_dialogue_label in self.dialogues: self_initiated_dialogue = self.dialogues[self_initiated_dialogue_label] self.dialogues.pop(self_initiated_dialogue_label) final_dialogue_label = DialogueLabel( dialogue_reference, self_initiated_dialogue_label.dialogue_opponent_addr, self_initiated_dialogue_label.dialogue_starter_addr, ) self_initiated_dialogue._dialogue_label = final_dialogue_label assert self_initiated_dialogue.dialogue_label not in self.dialogues self.dialogues.update( {self_initiated_dialogue.dialogue_label: self_initiated_dialogue} )
def encode(self, msg: Message) -> bytes: """Encode a 'default' message into bytes.""" body = {} # Dict[str, Any] msg_type = DefaultMessage.Type(msg.get("type")) body["type"] = str(msg_type.value) if msg_type == DefaultMessage.Type.BYTES: content = cast(bytes, msg.get("content")) body["content"] = base64.b64encode(content).decode("utf-8") elif msg_type == DefaultMessage.Type.ERROR: body["error_code"] = cast(str, msg.get("error_code")) body["error_msg"] = cast(str, msg.get("error_msg")) body["error_data"] = cast(str, msg.get("error_data")) else: raise ValueError("Type not recognized.") bytes_msg = json.dumps(body).encode("utf-8") return bytes_msg
def get_dialogue(self, fipa_msg: Message, sender: Address, agent_pbk: Address) -> Dialogue: """ Retrieve dialogue. :param fipa_msg: the fipa message :param sender_pbk: the sender public key :param agent_pbk: the public key of the agent :return: the dialogue """ dialogue_id = cast(int, fipa_msg.get("dialogue_id")) opponent = sender target = cast(int, fipa_msg.get("target")) performative = fipa_msg.get("performative") self_initiated_dialogue_label = DialogueLabel(dialogue_id, opponent, agent_pbk) other_initiated_dialogue_label = DialogueLabel(dialogue_id, opponent, opponent) if performative == FIPAMessage.Performative.PROPOSE and target == PROPOSE_TARGET and self_initiated_dialogue_label in self.dialogues: dialogue = self.dialogues[self_initiated_dialogue_label] elif performative == FIPAMessage.Performative.ACCEPT: if target == ACCEPT_TARGET and other_initiated_dialogue_label in self.dialogues: dialogue = self.dialogues[other_initiated_dialogue_label] else: raise ValueError('Should have found dialogue.') elif performative == FIPAMessage.Performative.MATCH_ACCEPT: if target == MATCH_ACCEPT_TARGET and self_initiated_dialogue_label in self.dialogues: dialogue = self.dialogues[self_initiated_dialogue_label] else: raise ValueError('Should have found dialogue.') elif performative == FIPAMessage.Performative.DECLINE: if target == DECLINED_CFP_TARGET and self_initiated_dialogue_label in self.dialogues: dialogue = self.dialogues[self_initiated_dialogue_label] elif target == DECLINED_PROPOSE_TARGET and other_initiated_dialogue_label in self.dialogues: dialogue = self.dialogues[other_initiated_dialogue_label] elif target == DECLINED_ACCEPT_TARGET and self_initiated_dialogue_label in self.dialogues: dialogue = self.dialogues[self_initiated_dialogue_label] else: raise ValueError('Should have found dialogue.') else: raise ValueError('Should have found dialogue.') dialogue = cast(Dialogue, dialogue) return dialogue
def is_belonging_to_registered_dialogue(self, fipa_msg: Message, sender: Address, agent_pbk: Address) -> bool: """ Check whether an agent message is part of a registered dialogue. :param fipa_msg: the fipa message :param sender: the sender :param agent_pbk: the public key of the agent :return: boolean indicating whether the message belongs to a registered dialogue """ dialogue_id = cast(int, fipa_msg.get("dialogue_id")) opponent = sender target = cast(int, fipa_msg.get("target")) performative = fipa_msg.get("performative") self_initiated_dialogue_label = DialogueLabel(dialogue_id, opponent, agent_pbk) other_initiated_dialogue_label = DialogueLabel(dialogue_id, opponent, opponent) result = False if performative == FIPAMessage.Performative.PROPOSE and target == PROPOSE_TARGET and self_initiated_dialogue_label in self.dialogues: self_initiated_dialogue = cast(Dialogue, self.dialogues[self_initiated_dialogue_label]) result = self_initiated_dialogue.is_expecting_propose() elif performative == FIPAMessage.Performative.ACCEPT: if target == ACCEPT_TARGET and other_initiated_dialogue_label in self.dialogues: other_initiated_dialogue = cast(Dialogue, self.dialogues[other_initiated_dialogue_label]) result = other_initiated_dialogue.is_expecting_initial_accept() elif performative == FIPAMessage.Performative.MATCH_ACCEPT: if target == MATCH_ACCEPT_TARGET and self_initiated_dialogue_label in self.dialogues: self_initiated_dialogue = cast(Dialogue, self.dialogues[self_initiated_dialogue_label]) result = self_initiated_dialogue.is_expecting_matching_accept() elif performative == FIPAMessage.Performative.DECLINE: if target == DECLINED_CFP_TARGET and self_initiated_dialogue_label in self.dialogues: self_initiated_dialogue = cast(Dialogue, self.dialogues[self_initiated_dialogue_label]) result = self_initiated_dialogue.is_expecting_cfp_decline() elif target == DECLINED_PROPOSE_TARGET and other_initiated_dialogue_label in self.dialogues: other_initiated_dialogue = cast(Dialogue, self.dialogues[other_initiated_dialogue_label]) result = other_initiated_dialogue.is_expecting_propose_decline() elif target == DECLINED_ACCEPT_TARGET and self_initiated_dialogue_label in self.dialogues: self_initiated_dialogue = cast(Dialogue, self.dialogues[self_initiated_dialogue_label]) result = self_initiated_dialogue.is_expecting_accept_decline() return result
def is_permitted_for_new_dialogue(self, fipa_msg: Message, sender: Address) -> bool: """ Check whether a fipa message is permitted for a new dialogue. That is, the message has to - be a CFP, and - have the correct msg id and message target. :param message: the fipa message :param sender: the sender :return: a boolean indicating whether the message is permitted for a new dialogue """ fipa_msg = cast(FIPAMessage, fipa_msg) msg_id = fipa_msg.get("id") target = fipa_msg.get("target") performative = fipa_msg.get("performative") result = performative == FIPAMessage.Performative.CFP \ and msg_id == STARTING_MESSAGE_ID \ and target == STARTING_MESSAGE_TARGET return result
def _basic_rules(self, message: Message) -> bool: """ Check whether 'message' is a valid next message in the dialogue, according to basic rules. These rules are designed to be fundamental to all dialogues, and enforce the following: - message ids are consistent - targets are consistent - message targets are according to the reply structure of performatives :param message: the message to be validated :return: True if valid, False otherwise. """ message_id = message.message_id target = cast(int, message.get("target")) performative = cast(Enum, message.get("performative")) if self.is_empty: result = ( message_id == Dialogue.STARTING_MESSAGE_ID and target == Dialogue.STARTING_TARGET and performative == self.initial_performative() ) else: last_message_id = self.last_message.message_id # type: ignore target_message = self.get_message(target) if target_message is not None: target_performative = cast(Enum, target_message.get("performative")) result = ( message_id == last_message_id + 1 and 1 <= target <= last_message_id and performative in self.get_replies(target_performative) ) else: result = False return result
def is_belonging_to_registered_dialogue(self, fipa_msg: Message, sender: Address, agent_pbk: Address) -> bool: """ Check whether an agent message is part of a registered dialogue. :param fipa_msg: the fipa message :param sender: the sender :param agent_pbk: the public key of the agent :return: boolean indicating whether the message belongs to a registered dialogue """ fipa_msg = cast(FIPAMessage, fipa_msg) dialogue_reference = cast(Tuple[str, str], fipa_msg.get("dialogue_reference")) alt_dialogue_reference = (dialogue_reference[0], '') self_initiated_dialogue_label = DialogueLabel(dialogue_reference, sender, agent_pbk) alt_self_initiated_dialogue_label = DialogueLabel( alt_dialogue_reference, sender, agent_pbk) other_initiated_dialogue_label = DialogueLabel(dialogue_reference, sender, sender) result = False if other_initiated_dialogue_label in self.dialogues: other_initiated_dialogue = cast( FIPADialogue, self.dialogues[other_initiated_dialogue_label]) result = other_initiated_dialogue.is_valid_next_message(fipa_msg) if self_initiated_dialogue_label in self.dialogues: self_initiated_dialogue = cast( FIPADialogue, self.dialogues[self_initiated_dialogue_label]) result = self_initiated_dialogue.is_valid_next_message(fipa_msg) if alt_self_initiated_dialogue_label in self._initiated_dialogues: self_initiated_dialogue = cast( FIPADialogue, self._initiated_dialogues[alt_self_initiated_dialogue_label]) result = self_initiated_dialogue.is_valid_next_message(fipa_msg) if result: self._initiated_dialogues.pop( alt_self_initiated_dialogue_label) final_dialogue_label = DialogueLabel( dialogue_reference, alt_self_initiated_dialogue_label.dialogue_opponent_pbk, alt_self_initiated_dialogue_label.dialogue_starter_pbk) self_initiated_dialogue.assign_final_dialogue_label( final_dialogue_label) self._add(self_initiated_dialogue) return result
def update(self, message: Message) -> Optional[Dialogue]: """ Update the state of dialogues with a new message. If the message is for a new dialogue, a new dialogue is created with 'message' as its first message and returned. If the message is addressed to an existing dialogue, the dialogue is retrieved, extended with this message and returned. If there are any errors, e.g. the message dialogue reference does not exists or the message is invalid w.r.t. the dialogue, return None. :param message: a new message :return: the new or existing dialogue the message is intended for, or None in case of any errors. """ dialogue_reference = cast(Tuple[str, str], message.get("dialogue_reference")) if ( # new dialogue by other dialogue_reference[0] != "" and dialogue_reference[1] == "" and message.is_incoming ): dialogue = self._create_opponent_initiated( dialogue_opponent_addr=message.counterparty, dialogue_reference=dialogue_reference, role=self.role_from_first_message(message), ) # type: Optional[Dialogue] elif ( # new dialogue by self dialogue_reference[0] != "" and dialogue_reference[1] == "" and not message.is_incoming ): assert ( message.counterparty is not None ), "The message counter-party field is not set {}".format(message) dialogue = self._create_self_initiated( dialogue_opponent_addr=message.counterparty, role=self.role_from_first_message(message), ) else: # existing dialogue self._update_self_initiated_dialogue_label_on_second_message(message) dialogue = self._get_dialogue(message) if dialogue is not None: dialogue.update(message) result = dialogue # type: Optional[Dialogue] else: # couldn't find the dialogue result = None return result
def _additional_rules(self, message: Message) -> bool: """ Check whether 'message' is a valid next message in the dialogue, according to additional rules. These rules are designed to be less fundamental than basic rules and subject to change. Currently the following is enforced: - A message targets the message strictly before it in the dialogue :param message: the message to be validated :return: True if valid, False otherwise. """ if self.is_empty: result = True else: target = cast(int, message.get("target")) last_target = self.last_message.target # type: ignore result = target == last_target + 1 return result
def encode(self, msg: Message) -> bytes: """Encode a FIPA message into bytes.""" fipa_msg = fipa_pb2.FIPAMessage() fipa_msg.message_id = msg.get("id") fipa_msg.dialogue_id = msg.get("dialogue_id") fipa_msg.target = msg.get("target") performative_id = FIPAMessage.Performative(msg.get("performative")) if performative_id == FIPAMessage.Performative.CFP: performative = fipa_pb2.FIPAMessage.CFP() # type: ignore query = msg.get("query") if query is None or query == b"": nothing = fipa_pb2.FIPAMessage.CFP.Nothing() # type: ignore performative.nothing.CopyFrom(nothing) elif type(query) == Query: query = pickle.dumps(query) performative.query_bytes = query elif type(query) == bytes: performative.bytes = query else: raise ValueError("Query type not supported: {}".format( type(query))) fipa_msg.cfp.CopyFrom(performative) elif performative_id == FIPAMessage.Performative.PROPOSE: performative = fipa_pb2.FIPAMessage.Propose() # type: ignore proposal = cast(Description, msg.get("proposal")) p_array_bytes = [pickle.dumps(p) for p in proposal] performative.proposal.extend(p_array_bytes) fipa_msg.propose.CopyFrom(performative) elif performative_id == FIPAMessage.Performative.ACCEPT: performative = fipa_pb2.FIPAMessage.Accept() # type: ignore fipa_msg.accept.CopyFrom(performative) elif performative_id == FIPAMessage.Performative.MATCH_ACCEPT: performative = fipa_pb2.FIPAMessage.MatchAccept() # type: ignore fipa_msg.match_accept.CopyFrom(performative) elif performative_id == FIPAMessage.Performative.DECLINE: performative = fipa_pb2.FIPAMessage.Decline() # type: ignore fipa_msg.decline.CopyFrom(performative) else: raise ValueError( "Performative not valid: {}".format(performative_id)) fipa_bytes = fipa_msg.SerializeToString() return fipa_bytes
def encode(self, msg: Message) -> bytes: """Encode a FIPA message into bytes.""" fipa_msg = fipa_pb2.FIPAMessage() fipa_msg.message_id = msg.get("message_id") dialogue_reference = cast(Tuple[str, str], msg.get("dialogue_reference")) fipa_msg.dialogue_starter_reference = dialogue_reference[0] fipa_msg.dialogue_responder_reference = dialogue_reference[1] fipa_msg.target = msg.get("target") performative_id = FIPAMessage.Performative(msg.get("performative")) if performative_id == FIPAMessage.Performative.CFP: performative = fipa_pb2.FIPAMessage.CFP() # type: ignore query = msg.get("query") if query is None or query == b"": nothing = fipa_pb2.FIPAMessage.CFP.Nothing() # type: ignore performative.nothing.CopyFrom(nothing) elif type(query) == Query: query = pickle.dumps(query) performative.query_bytes = query elif type(query) == bytes: performative.bytes = query else: raise ValueError("Query type not supported: {}".format(type(query))) fipa_msg.cfp.CopyFrom(performative) elif performative_id == FIPAMessage.Performative.PROPOSE: performative = fipa_pb2.FIPAMessage.Propose() # type: ignore proposal = cast(Description, msg.get("proposal")) p_array_bytes = [pickle.dumps(p) for p in proposal] performative.proposal.extend(p_array_bytes) fipa_msg.propose.CopyFrom(performative) elif performative_id == FIPAMessage.Performative.ACCEPT: performative = fipa_pb2.FIPAMessage.Accept() # type: ignore fipa_msg.accept.CopyFrom(performative) elif performative_id == FIPAMessage.Performative.MATCH_ACCEPT: performative = fipa_pb2.FIPAMessage.MatchAccept() # type: ignore fipa_msg.match_accept.CopyFrom(performative) elif performative_id == FIPAMessage.Performative.ACCEPT_W_ADDRESS: performative = fipa_pb2.FIPAMessage.AcceptWAddress() # type: ignore address = msg.get("address") if type(address) == str: performative.address = address fipa_msg.accept_w_address.CopyFrom(performative) elif performative_id == FIPAMessage.Performative.MATCH_ACCEPT_W_ADDRESS: performative = fipa_pb2.FIPAMessage.MatchAcceptWAddress() # type: ignore address = msg.get("address") if type(address) == str: performative.address = address fipa_msg.match_accept_w_address.CopyFrom(performative) elif performative_id == FIPAMessage.Performative.DECLINE: performative = fipa_pb2.FIPAMessage.Decline() # type: ignore fipa_msg.decline.CopyFrom(performative) elif performative_id == FIPAMessage.Performative.INFORM: performative = fipa_pb2.FIPAMessage.Inform() # type: ignore data = msg.get("json_data") data_bytes = json.dumps(data).encode("utf-8") performative.bytes = data_bytes fipa_msg.inform.CopyFrom(performative) else: raise ValueError("Performative not valid: {}".format(performative_id)) fipa_bytes = fipa_msg.SerializeToString() return fipa_bytes
def encode(self, msg: Message) -> bytes: """ Decode the message. :param msg: the message object :return: the bytes """ tac_type = TACMessage.Type(msg.get("type")) tac_container = tac_pb2.TACMessage() if tac_type == TACMessage.Type.REGISTER: agent_name = msg.get("agent_name") tac_msg = tac_pb2.TACAgent.Register() # type: ignore tac_msg.agent_name = agent_name tac_container.register.CopyFrom(tac_msg) elif tac_type == TACMessage.Type.UNREGISTER: tac_msg = tac_pb2.TACAgent.Unregister() # type: ignore tac_container.unregister.CopyFrom(tac_msg) elif tac_type == TACMessage.Type.TRANSACTION: tac_msg = tac_pb2.TACAgent.Transaction() # type: ignore tac_msg.transaction_id = msg.get("transaction_id") tac_msg.is_sender_buyer = msg.get("is_sender_buyer") tac_msg.counterparty = msg.get("counterparty") tac_msg.amount = msg.get("amount") tac_msg.quantities.extend( _from_dict_to_pairs(msg.get("quantities_by_good_pbk"))) tac_container.transaction.CopyFrom(tac_msg) elif tac_type == TACMessage.Type.GET_STATE_UPDATE: tac_msg = tac_pb2.TACAgent.GetStateUpdate() # type: ignore tac_container.get_state_update.CopyFrom(tac_msg) elif tac_type == TACMessage.Type.CANCELLED: tac_msg = tac_pb2.TACController.Cancelled() # type: ignore tac_container.cancelled.CopyFrom(tac_msg) elif tac_type == TACMessage.Type.GAME_DATA: tac_msg = tac_pb2.TACController.GameData() # type: ignore tac_msg.money = msg.get("money") tac_msg.endowment.extend(msg.get("endowment")) tac_msg.utility_params.extend(msg.get("utility_params")) tac_msg.nb_agents = msg.get("nb_agents") tac_msg.nb_goods = msg.get("nb_goods") tac_msg.tx_fee = msg.get("tx_fee") tac_msg.agent_pbk_to_name.extend( _from_dict_to_pairs(msg.get("agent_pbk_to_name"))) tac_msg.good_pbk_to_name.extend( _from_dict_to_pairs(msg.get("good_pbk_to_name"))) tac_container.game_data.CopyFrom(tac_msg) elif tac_type == TACMessage.Type.TRANSACTION_CONFIRMATION: tac_msg = tac_pb2.TACController.TransactionConfirmation( ) # type: ignore tac_msg.transaction_id = msg.get("transaction_id") tac_container.transaction_confirmation.CopyFrom(tac_msg) elif tac_type == TACMessage.Type.STATE_UPDATE: tac_msg = tac_pb2.TACController.StateUpdate() # type: ignore game_data_json = msg.get("initial_state") game_data = tac_pb2.TACController.GameData() # type: ignore game_data.money = game_data_json["money"] # type: ignore game_data.endowment.extend( game_data_json["endowment"]) # type: ignore game_data.utility_params.extend( game_data_json["utility_params"]) # type: ignore game_data.nb_agents = game_data_json["nb_agents"] # type: ignore game_data.nb_goods = game_data_json["nb_goods"] # type: ignore game_data.tx_fee = game_data_json["tx_fee"] # type: ignore game_data.agent_pbk_to_name.extend( _from_dict_to_pairs( cast(Dict[str, str], game_data_json["agent_pbk_to_name"]))) # type: ignore game_data.good_pbk_to_name.extend( _from_dict_to_pairs( cast(Dict[str, str], game_data_json["good_pbk_to_name"]))) # type: ignore tac_msg.initial_state.CopyFrom(game_data) transactions = [] msg_transactions = cast(List[Any], msg.get("transactions")) for t in msg_transactions: tx = tac_pb2.TACAgent.Transaction() # type: ignore tx.transaction_id = t.get("transaction_id") tx.is_sender_buyer = t.get("is_sender_buyer") tx.counterparty = t.get("counterparty") tx.amount = t.get("amount") tx.quantities.extend( _from_dict_to_pairs(t.get("quantities_by_good_pbk"))) transactions.append(tx) tac_msg.txs.extend(transactions) tac_container.state_update.CopyFrom(tac_msg) elif tac_type == TACMessage.Type.TAC_ERROR: tac_msg = tac_pb2.TACController.Error() # type: ignore tac_msg.error_code = TACMessage.ErrorCode( msg.get("error_code")).value if msg.is_set("error_msg"): tac_msg.error_msg = msg.get("error_msg") if msg.is_set("details"): tac_msg.details.update(msg.get("details")) tac_container.error.CopyFrom(tac_msg) else: raise ValueError("Type not recognized: {}.".format(tac_type)) tac_message_bytes = tac_container.SerializeToString() return tac_message_bytes