-
Notifications
You must be signed in to change notification settings - Fork 6
Protocols
since 0.2.4
This is an API to simplify the process of writing communication protocols between agents. It can be found in the uk.ac.imperial.presage2.util.protocols
package (javadoc).
There are two main components of protocols in presage2:
- Protocol - This class encapsulates an entire protocol, and an instance of this class manages all conversations of the protocol for an individual agent. There should be one instance per protocol per agent using the protocol. It is an InputHandler and will handle any and all Messages which are part of it's protocol.
- Conversation - This encapsulates a series of messages exchanged between an agent and one or more others. These are created and managed by the Protocol.
A Protocol is described as a finite state machine. It also have a unique String
name which is added as meta data to every message sent allowing it to be identified as part of a particular protocol.
You can create a protocol by creating an instance of FSMProtocol with a name and FSMDescription, or by extending FSMProtocol to embed this in a strongly typed protocol class. The protocol also requires a NetworkAdaptor to send messages over.
The FSMProtocol class expects a certain structure of fsm in order for it to properly create new conversations. Conversations can be split into two distinct categories:
- Initiated by me (I sent the first message)
- Initiated by someone else (someone else sent the first message)
You can represent both of these types of conversation in the same state machine, or just one of them. The type is defined by the transition from the start state. A conversation initiated by someone else is started with a Message event, while one initiated by oneself gets a special ConversationSpawnEvent which passes a list of recipients to start the conversation with. From that point onwards all events will be messages received.
Spawn transitions are triggered by a ConversationSpawnEvent and a SpawnAction will extract the recipients and add them to the conversation. Your transition should look something like this:
description.addTransition("spawn", new EventTypeCondition(ConversationSpawnEvent.class),
startState, nextState, new SpawnAction() {
@Override
public void processSpawn(ConversationSpawnEvent event, FSMConversation conv,
Transition trans) {
// start talking to people
List<NetworkAddress> recipients = conv.recipients;
}
});
All other transitions will be from received messages. A ConversationCondition and MessageTypeCondition can be used to ensure that the message is of the correct conversation and type respectively. MessageAction wraps Action to make it more convenient for dealing with messages, and InitialiseConversationAction is a special case for the initial transition which initialises the recipient and conversation key. These can be used as follows:
// transition from start state from a 'Greet' message
description.addTransition("startFromMessage", new MessageTypeCondition("Greet"),
startState, replyState, new InitialiseConversationAction() {
@Override
public void processInitialMessage(Message<?> message, FSMConversation conv, Transition trans) {
// reply to greeting
}
});
// example mid conversation transition
description.addTransition("receiveBid", new AndCondition(new MessageTypeCondition("Bid"),
new ConversationCondition()), state1, state2, new MessageAction() {
@Override
public void processMessage(Message<?> message, FSMConversation conv, Transition transition) {
// do something here
}
});
The FSMConversation wraps the agent's NetworkAdaptor for your convenience. It allows you to get the NetworkAdaptor in a conversation action with conv.getNetwork()
and messages send with this adaptor will have the correct protocol and conversation key set for you.