Messages

Messages are data containers that carry information between agents. When interacting with Java/Groovy agents, messages are mapped to Java/Groovy message classes with fields with the same name as the keys in the message.

Message types are defined using the @message macro. For example:

@message "org.arl.fjage.shell.ShellExecReq" struct ShellExecReq
  cmd::Union{String,Nothing} = nothing
  script::Union{String,Nothing} = nothing
  args::Vector{String} = String[]
  ans::Bool = false
end

defines a ShellExecReq message type that maps to a Java class with the package org.arl.fjage.shell.ShellExecReq.

All messages are mutable. The @message macro also automatically adds a few fields:

  • performative::Symbol
  • messageID::String
  • inReplyTo::String
  • sender::AgentID
  • recipient::AgentID
  • sentAt::Int64

Messages can subtype other messages:

julia> abstract type MyAbstractMessage <: Message end

julia> @message "org.arl.fjage.demo.MyConcreteMessage" struct MyConcreteMessage <: MyAbstractMessage
        a::Int
      end

julia> MyConcreteMessage(a=1)
MyConcreteMessage:INFORM[a:1]

julia> MyConcreteMessage(a=1) isa MyAbstractMessage
true

It is also possible to have a concrete message type that can also be a supertype of another message:

julia> abstract type SomeMessage <: Message end

julia> @message "org.arl.fjage.demo.SomeMessage" struct SomeMessage <: SomeMessage
        a::Int
      end

julia> @message "org.arl.fjage.demo.SomeExtMessage" struct SomeExtMessage <: SomeMessage
        a::Int
        b::Int
      end

julia> SomeMessage(a=1) isa SomeMessage
true

julia> SomeExtMessage(a=1, b=2) isa SomeMessage
true

Performatives are guessed automatically based on message classname. By default, the performative is Performative.INFORM. If a message classname ends with a Req, the default performative changes to Performative.REQUEST. Performatives may be overridden at declaration or at construction (and are mutable):

julia> @message "org.arl.fjage.demo.SomeReq" struct SomeReq end;
julia> @message "org.arl.fjage.demo.SomeRsp" Performative.AGREE struct SomeRsp end;

julia> SomeReq().performative
:REQUEST

julia> SomeRsp().performative
:AGREE

julia> SomeRsp(performative=Performative.INFORM).performative
:INFORM

When strict typing is not required, one can use the dictionary-like GenericMessage message type:

julia> msg = GenericMessage("org.arl.fjage.demo.DynamicMessage")
DynamicMessage:INFORM

julia> msg.a = 1
1

julia> msg.b = "xyz"
"xyz"

julia> msg
DynamicMessage:INFORM[a:1 b:"xyz"]

julia> classname(msg)
"org.arl.fjage.demo.DynamicMessage"

julia> msg isa GenericMessage
true

API

Fjage.GenericMessageType

Generic message type that can carry arbitrary name-value pairs as data.

Fjage.MessageType
msg = Message([perf])
msg = Message(inreplyto[, perf])

Create a message with just a performative (perf) and no data. If the performative is not specified, it defaults to INFORM. If the inreplyto is specified, the message inReplyTo and recipient fields are set accordingly.

Fjage.MessageType

Base class for messages transmitted by one agent to another.

Base.get!Method
get!(p::ParameterReq, param)

Request parameter param to be fetched.

Examples

julia> p = ParameterReq(index=1)
ParameterReq[index=1]
julia> get!(p, "modulation")
ParameterReq[index=1 modulation=?]
julia> get!(p, "fec")
ParameterReq[index=1 modulation=? ...]
Base.getMethod
get(p::ParameterRsp, param)

Extract parameter param from a parameter response message.

Fjage.classnameFunction
classname(msg::Message)

Return the fully qualified class name of a message.

Fjage.registermessagesFunction
registermessages()
registermessages(messageclasses)

Register message classes with Fjage. Usually message classes are automatically registered on creation with @message. However, when developing packages, if @message is used at the module level, the types may be precompiled and the code to register the classes may not get executed at runtime. In such cases, you may need to explicitly call registermessages() in the __init()__ function for the module.

Fjage.set!Method
set!(p::ParameterReq, param, value)

Request parameter param to be set to value.

Examples

julia> p = ParameterReq(index=1)
ParameterReq[index=1]
julia> set!(p, "modulation", "ofdm")
ParameterReq[index=1 modulation=ofdm]
julia> set!(p, "fec", 1)
ParameterReq[index=1 modulation=ofdm ...]
Fjage.@messageMacro
@message classname [performative] struct mtype [<: supertype]
  fields...
end

Create a message class from a fully qualified class name. If a performative is not specified, it is guessed based on the class name. For class names ending with "Req", the performative is assumed to be REQUEST, and for all other messages, INFORM.

Examples

julia> @message "org.arl.fjage.shell.MyShellExecReq" struct MyShellExecReq
         cmd::String
       end
julia> req = MyShellExecReq(cmd="ps")
MyShellExecReq:REQUEST[cmd:"ps"]