Esempio n. 1
0
    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)
Esempio n. 2
0
    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
Esempio n. 3
0
    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
Esempio n. 4
0
    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
Esempio n. 5
0
    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
Esempio n. 6
0
    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
Esempio n. 7
0
    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
Esempio n. 8
0
    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)
Esempio n. 9
0
    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}
            )
Esempio n. 10
0
    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
Esempio n. 11
0
    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
Esempio n. 12
0
    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
Esempio n. 13
0
    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
Esempio n. 14
0
    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
Esempio n. 15
0
    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
Esempio n. 16
0
    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
Esempio n. 17
0
    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
Esempio n. 18
0
    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
Esempio n. 19
0
    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
Esempio n. 20
0
    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