Skip to content

HeadlessServer

Baptiste Lesquoy edited this page Nov 25, 2022 · 29 revisions

Headless Server

Running a Gama Headless server:

From the release

Go to the headless directory in your Gama installation folder and run the script gama-headless.sh (or gama-headless.bat) with the argument -socket followed by the port number you want your Gama server to run on.

For example on Mac OS you could do:

cd Gama.app/Contents/headless

to move to the right directory, then run the script to listen on port 6868 with:

gama-headless.sh -socket 6868

From the command-line tool

The users who installed gama through a .deb file or aur have access to the command gama-headless and thus only need to open a terminal and run

gama-headless -socket 6868

to run a Gama server on the port 6868.

From the source code

In Eclipse, instantiate a headless server by running msi.gama.headless.id4_full with the following argument -os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -socket 6868 (you can specify any other port)

Interacting with Gama Server

Connection

To connect to gama-server as a client you just need to access the following address: ws://<ip>:<port>. For example if you try to connect to a gama-server running on your current computer and started with the command gama-headless -socket 6868, you will have to connect to ws://localhost:6868.

Once a client is connected, gama-server will send a connection object containing the socket_id, it is used to represents the current connection. It must be saved by the client and reused in every command sent to gama-server.

General description of interactions

Once connected, you can ask gama-server to execute different commands to control the execution of different simulations.

If you close your client application (or just close the socket on client-side) gama-server will destroy all running simulations of that client, so you have to keep your client alive.

For every command treated by gama-server, it will send back a json object describing if the command has been executed correctly or if there was a problem. If an unexpected exception is raised in gama-server, it will try to send the connected clients a json-object describing it. The same goes if a simulation throws an exception/error while running, the client that asked for it to run will receive it as a json-object.

In addition, the client can ask gama-server to receive (or not) the different outputs of a simulation: write statements, dialogs, status-bar changes etc. they will be sent as they come, in a specific json wrapper.

API description

Available commands

All the commands sent to gama-server must be formatted as a json object.

The available commands are:

The exit command

This command is used to kill gama-server. It is triggered by sending a json object formatted as follows to the server

{
  "type": "exit"
}
Answer from gama-server

It is the only command that won't send back a json object and do not need a socket_id.

The load command

This command is used to ask the server to initialize a specific experiment in a gaml file on the server's file-system. It is triggered by sending a json object formatted as follows to the server:

{
  "type": "load",
  "socket_id": "<socket_id>",
  "model": "<gaml_file_path>",
  "experiment": "<experiment_name>",
  "console": "<console>", //optional
  "status": "<status>", //optional
  "dialog": "<dialog>", //optional
  "parameters": "<params>", //optional
  "until": "<end_condition>" //optional
}

The model parameter indicates the path of the experiment file on the server's file-system, and experiment is the actual name of the experiment to run. The three parameters console, status and dialog are booleans used to set if the messages from respectively the console, the status-bar and the dialogs should be redirected to the client. They are optional as per default console is set to true and the two others to false. You can add an array of parameters that will be used to initialize the experiment's variables with the values you picked. The value of parameters should be formatted as follows:

[
  {
    "type": "<type of the first parameter>",
    "value": "<value of the first parameter>",
    "name": "<name of the first parameter in the gaml file>"
  },
  {
    "type": "<type of the second parameter>",
    "value": "<value of the second parameter>",
    "name": "<name of the second parameter in the gaml file>"
  },
 ...
]

You can also add an ending condition to your simulation with the parameter until, the condition must be expressed in gaml.

Answer from gama-server

The content field of the response json sent by gama-server after processing this command is formatted as follows:

"content": {"exp_id": "<the experiment id>"}

The experiment id should be used in all the other commands to refer to that specific experiment in order to control it.

The play command

This command is used to actually run an experimented already initialized. It is triggered by sending a json object formatted as follows to the server

{
  "type": "play",
  "socket_id": "<socket_id>",
  "exp_id": "<experiment_id>",
  "sync": "<synchronized>" //optional
}

The socket_id is used to identify the client, the experiment_id to identify the experiment to play, and the optional sync is a boolean used in the case where there was an end condition defined in the load command, if it is true, gama-server will not send a response to the command, but only a end of simulation message once the condition is reached, if it's false gama-server will send both the response to the command and the end-condition-reached message.

Answer from gama-server

This command has an empty content field in the response json sent by gama-server after processing it. In case where the end condition is reached, a message of type SimulationEnded is sent to the client with an empty content.

The pause command

This command is used to pause a running experiment. It is triggered by sending a json object formatted as follows to the server

{
  "type": "pause",
  "socket_id": "<socket_id>",
  "exp_id": "<experiment_id>"
}
Answer from gama-server

This command has an empty content field in the response json sent by gama-server after processing it.

The step command

This command is used to process one (or a defined number of) step(s) of a simulation that has already been loaded. It is triggered by sending a json object formatted as follows to the server

{
  "type": "step",
  "socket_id": "<socket_id>",
  "exp_id": "<experiment_id>",
  "nb_step": "<number_of_steps>", //optional
  "sync": "<synchronized>", // optional
}

As usual socket_id refers to the id given at the client's connection, and exp_id to the experiment you want to apply the command to. The nb_step parameter indicates how many steps you want to execute, if you do not give that parameter gama-server will execute one step. The sync parameter indicates whether gama-server must wait for the end of the step(s) to send back a success message (when its value is true), or just plan the step(s) and send one directly after (when its value is false), this parameter can be ignored and will be interpreted as if it were false.

Answer from gama-server

This command has an empty content field in the response json sent by gama-server after processing it.

The stepBack command

This command is used to rollback the simulation one (or a defined number of) step(s) back. This command only works on experiments of type memorize. It is triggered by sending a json object formatted as follows to the server

{
  "type": "stepBack",
  "socket_id": "<socket_id>",
  "exp_id": "<experiment_id>",
  "nb_step": "<number_of_steps>", //optional
  "sync": "<synchronized>" // optional
}

The parameters are exactly the same as in the step command.

Answer from gama-server

This command has an empty content field in the response json sent by gama-server after processing it.

The stop command

This command is used to stop (kill) a running experiment. It is triggered by sending a json object formatted as follows to the server

{
  "type": "stop",
  "socket_id": "<socket_id>",
  "exp_id": "<experiment_id>",
}
Answer from gama-server

This command has an empty content field in the response json sent by gama-server after processing it.

The reload command

This command is used to reload an experiment. The experiment will be stop and the initialization process run again. You can use this command to change the simulation parameters or the ending condition. It is triggered by sending a json object formatted as follows to the server

{
  "type": "reload",
  "socket_id": "<socket_id>",
  "exp_id": "<experiment_id>",
  "parameters": "<params>", //optional
  "until": "<end_condition>" //optional
}

Just like for the load command, the parameters and the until parameters are optional and must follow the same formatting.

Answer from gama-server

This command has an empty content field in the response json sent by gama-server after processing it.

The expression command

This command is used to ask the server to evaluate a gaml expression having an experiment as context.
It is triggered by sending a json object formatted as follows to the server

{
  "type": "expression",
  "socket_id": "<socket_id>",
  "exp_id": "<experiment_id>",
  "expr": "<expression to evaluate>"
}

For example if you want to know the number of agents of species people currently present in the simulation represented by the id 123, you could send this command to gama-server:

{
  "type": "expression",
  "socket_id": "<socket_id>",
  "exp_id": "123",
  "expr": "length(people)"
}
Answer from gama-server

If the command is executed successfully by gama-server the content field of the response json will look like this:

"content": { "result": "<value of the expression>"}

The output command

TODO

Answer from gama-server

TODO

Gama-server messages

All messages send by gama-server follow a json architecture that is formatted as follows:

{
  "type": "some string describing the type of message",
  "content": "a field containing everything additional information for the message", //It can be a string, an int or a json object
  "exp_id": "contains the experiment id (as a string) to which this message is linked to", //Optional, its presence depends on the message's type
  "command": "a json containing the original command to which gama is responding",//Optional, is only present in messages responding directly to a command sent by the client
}

Messages types:

So all messages have in common a type field that informs the client of the type of message sent. The different types possibles are:

  • ConnectionSuccessful: Used when a client connected without any problem to gama-server
  • SimulationStatus: Signals a message representing a simulation status
  • SimulationStatusInform: Signals a message representing a simulation inform status
  • SimulationStatusError: Signals a message representing a simulation error status
  • SimulationStatusNeutral: Signals a message representing a simulation neutral status
  • SimulationOutput: Signals a message as would be written in the console by a write statement in gama with an interface
  • SimulationDebug: Signals a message as would be written in the console by a debug statement in gama with an interface
  • SimulationDialog: Signals a message representing what would be a dialog in gama with an interface
  • SimulationErrorDialog: Signals a message representing what would be an dialog in gama with an interface
  • SimulationError: Signals a message representing an error raised in a running simulation
  • RuntimeError: Signals a message representing an exception raised in gama-server while trying to process a command
  • GamaServerError: Signals a message representing an unknown exception raised in gama-server (can be unrelated to any command)
  • MalformedRequest: Signals that a command sent by the client doesn't follow the expected format (lack of parameter, wrong type etc.)
  • CommandExecutedSuccessfully: Signals that a command sent by the client was executed without any problem on gama-server
  • SimulationEnded: Signals that a running simulation reached its end condition and stopped. Beware if the simulation stops for another reason, this message won't be send.
  • UnableToExecuteRequest: Signals that a command cannot be executed, though it may be formatted correctly. It mainly occurs when trying to execute a command on a simulation that is not currently running.

Connection related answers

When your client is connected correctly to gama-server, a message is sent. Its type is ConnectionSuccessful and the content field contains an integer that should be used later as socket_id by the client to identify itself. In case of problem, the client may receive a message of type GamaServerError or just get a timeout/broken connection message at the socket level.

Command answers

For every command described in the commands section, the client will received a json answer formatted as follows:

{
  "type": "some string describing the type of message",
  "content": "a field containing every additional information for the message", //It can be a string, an int or a json object, depending on the type of message, it could also be empty
  "command": "a json containing the original command to which gama is responding"
}

So for example if you send an expression command to gama, with a socket_id of value 3, an experiment_id of value 2 and you want to evaluate the expression length(people) to know the number of agent people in that simulation. You may receive an answer looking like this:

{
  "type": "CommandExecutedSuccessfully", //The type indicates that everything went normally
  "content": 102, //There are 102 agents of the species people in your simulation at the time of evaluation
  "command": //The description of the command you sent, as interpreted by gama-server and turned into a json
  {
    "type": "expression",
    "exp_id": "2",
    "socket_id": "3",
    "expr": "length(people)",
  }
}

The command field is very useful for clients that run multiple simulations and commands at the same time, as it can be used to retrace which command the message responds to. Note: The command field contains all the parameters of the command sent by the client, including those that are not useful for GAMA to treat the command, you can thus use it to store more data, like an internal id used by the client, some kind of counter etc..

In case there is an error resulting from the processing of your command, you may receive a of an error of type:

  • MalformedRequest if you forgot a mandatory parameter to execute the command or gave objects that couldn't be de-serialized. The list of required parameters will be sent as a string in the content field.
  • UnableToExecuteRequest if you are trying to execute a command on a simulation that is not currently running or some other problem of "logic". You will find more informations in the content field.
  • RuntimeError and GamaServerError if while executing your command, an exception happens, either in gaml code for RuntimeError or in gama's code for GamaServerError. The exception's description will be given in the content field, as a json object containing the error message and the stack trace.

There is no 'exp_id' field in those messages, because it is already included in all the 'command' fields that are related to an experiment.

errors and exceptions

  • SimulationStatusError: Signals a message representing a simulation error status
  • SimulationErrorDialog: Signals a message representing what would be an dialog in gama with an interface
  • SimulationError: Signals a message representing an error raised in a running simulation
  • RuntimeError: Signals a message representing an exception raised in gama-server while trying to process a command
  • GamaServerError: Signals a message representing an unknown exception raised in gama-server (can be unrelated to any command)
  • MalformedRequest: Signals that a command sent by the client doesn't follow the expected format (lack of parameter, wrong type etc.)
  • UnableToExecuteRequest:

TODO

Simulations outputs

TODO

Python wrapper

** TODO: that's the old version **

A python package is available to interact with Gama server as a client, you can find it here. It will take care of formatting the queries to the server and receiving the answers. You simply have to install the package into your python environment with the command pip install gama-client and then import gama-client into your python files and instantiate a GamaClient object to start communicating with Gama server. For more informations follow the README.md available on the package's github.

Here is an example python program using it to run a gaml file:

import time
import gama_client
import asyncio


async def main():
	MY_SERVER_URL = "localhost"
	MY_SERVER_PORT = 6868
	GAML_FILE_PATH_ON_SERVER = "/opt/gama-platform/headless/samples/predatorPrey/predatorPrey.gaml"
	EXPERIMENT_NAME = "prey_predatorExp"

	client = gama_client.GamaClient(MY_SERVER_URL, MY_SERVER_PORT)

	print("connecting to Gama server")
	await client.connect()

	print("initialize a gaml model")
	experiment_id = await client.init_experiment(GAML_FILE_PATH_ON_SERVER, EXPERIMENT_NAME)
	if experiment_id == "":
		print("error while initializing")
		return

	print("initialization successful, running the model")
	playing = await client.play(experiment_id)
	if not playing:
		print("error while trying to run the experiment", experiment_id)
		return

	print("model running, waiting a bit")
	time.sleep(3)

	print("pausing the model")
	if not await client.pause(experiment_id):
		print("unable to pause the experiment", experiment_id)
		return

	print("asking simulation the value of: cycle=", await client.expression(experiment_id, r"cycle"))
	print("asking simulation the value of: nb_preys/nb_preys_init=", await client.expression(experiment_id, r"nb_preys/nb_preys_init"))

if __name__ == "__main__":
	asyncio.run(main())

Javascript Client

The current javascript client version is being developed in this repository gama.client

Hello World Visualization in MapBox

  • Clone the repository gama.client
  • In Javascript/gama_client.js edit the following variable ABSOLUTE_PATH_TO_GAMA to your local path (e.g var ABSOLUTE_PATH_TO_GAMA = '/Users/arno/';
  • open Javascript/index.htmlin a browser

Hello World Message example

  • In chain_messages.js edit the following variable ABSOLUTE_PATH_TO_GAMA to your local path (e.g var ABSOLUTE_PATH_TO_GAMA = '/Users/arno/';
  • open Javascript/message_examplein a browser
  1. What's new (Changelog)
  1. Installation and Launching
    1. Installation
    2. Launching GAMA
    3. Updating GAMA
    4. Installing Plugins
  2. Workspace, Projects and Models
    1. Navigating in the Workspace
    2. Changing Workspace
    3. Importing Models
  3. Editing Models
    1. GAML Editor (Generalities)
    2. GAML Editor Tools
    3. Validation of Models
  4. Running Experiments
    1. Launching Experiments
    2. Experiments User interface
    3. Controls of experiments
    4. Parameters view
    5. Inspectors and monitors
    6. Displays
    7. Batch Specific UI
    8. Errors View
  5. Running Headless
    1. Headless Batch
    2. Headless Server
    3. Headless Legacy
  6. Preferences
  7. Troubleshooting
  1. Introduction
    1. Start with GAML
    2. Organization of a Model
    3. Basic programming concepts in GAML
  2. Manipulate basic Species
  3. Global Species
    1. Regular Species
    2. Defining Actions and Behaviors
    3. Interaction between Agents
    4. Attaching Skills
    5. Inheritance
  4. Defining Advanced Species
    1. Grid Species
    2. Graph Species
    3. Mirror Species
    4. Multi-Level Architecture
  5. Defining GUI Experiment
    1. Defining Parameters
    2. Defining Displays Generalities
    3. Defining 3D Displays
    4. Defining Charts
    5. Defining Monitors and Inspectors
    6. Defining Export files
    7. Defining User Interaction
  6. Exploring Models
    1. Run Several Simulations
    2. Batch Experiments
    3. Exploration Methods
  7. Optimizing Model Section
    1. Runtime Concepts
    2. Optimizing Models
  8. Multi-Paradigm Modeling
    1. Control Architecture
    2. Defining Differential Equations
  1. Manipulate OSM Data
  2. Diffusion
  3. Using Database
  4. Using FIPA ACL
  5. Using BDI with BEN
  6. Using Driving Skill
  7. Manipulate dates
  8. Manipulate lights
  9. Using comodel
  10. Save and restore Simulations
  11. Using network
  12. Headless mode
  13. Using Headless
  14. Writing Unit Tests
  15. Ensure model's reproducibility
  16. Going further with extensions
    1. Calling R
    2. Using Graphical Editor
    3. Using Git from GAMA
  1. Built-in Species
  2. Built-in Skills
  3. Built-in Architecture
  4. Statements
  5. Data Type
  6. File Type
  7. Expressions
    1. Literals
    2. Units and Constants
    3. Pseudo Variables
    4. Variables And Attributes
    5. Operators [A-A]
    6. Operators [B-C]
    7. Operators [D-H]
    8. Operators [I-M]
    9. Operators [N-R]
    10. Operators [S-Z]
  8. Exhaustive list of GAMA Keywords
  1. Installing the GIT version
  2. Developing Extensions
    1. Developing Plugins
    2. Developing Skills
    3. Developing Statements
    4. Developing Operators
    5. Developing Types
    6. Developing Species
    7. Developing Control Architectures
    8. Index of annotations
  3. Introduction to GAMA Java API
    1. Architecture of GAMA
    2. IScope
  4. Using GAMA flags
  5. Creating a release of GAMA
  6. Documentation generation

  1. Predator Prey
  2. Road Traffic
  3. 3D Tutorial
  4. Incremental Model
  5. Luneray's flu
  6. BDI Agents

  1. Team
  2. Projects using GAMA
  3. Scientific References
  4. Training Sessions

Resources

  1. Videos
  2. Conferences
  3. Code Examples
  4. Pedagogical materials
Clone this wiki locally