Skip to main content

WebSocket API Reference

The WebPlatform exposes two WebSocket servers and maintains one outbound WebSocket connection. All messages are JSON-encoded strings.


Ports summary​

Port (default)Env varDirectionPurpose
8001MONITOR_WS_PORTFrontend ↔ WebPlatformAdmin UI control and state updates
8080HEADSET_WS_PORTHeadset ↔ WebPlatformPlayer connection and simulation data
1000GAMA_WS_PORTWebPlatform → GAMAGAMA server protocol (outbound client)

Monitor WebSocket (MONITOR_WS_PORT)​

The admin UI (browser frontend) connects to this port. The server broadcasts state updates to all connected monitor clients and sends targeted responses to the requesting client.

Messages: Frontend → WebPlatform​

launch_experiment​

Start the currently selected simulation in GAMA.

{ "type": "launch_experiment" }

stop_experiment​

Stop the running simulation. All headsets are removed from the simulation.

{ "type": "stop_experiment" }

pause_experiment​

Pause the running simulation. Headsets stay connected.

{ "type": "pause_experiment" }

resume_experiment​

Resume a paused simulation.

{ "type": "resume_experiment" }

get_simulation_informations​

Request the full catalog of available Virtual Universes. The server responds with the catalog structure read from the learning-packages directories.

{ "type": "get_simulation_informations" }

get_simulation_by_index​

Select a specific Virtual Universe by its index in the flat model list and receive its settings.

{
"type": "get_simulation_by_index",
"simulationIndex": 0
}

simulationIndex is a 0-based integer index into the list returned by get_simulation_informations.

send_simulation​

Alternative to get_simulation_by_index. Select a simulation using the model_index field embedded in a previously received simulation object.

{
"type": "send_simulation",
"simulation": { "model_index": 2 }
}

add_player_headset​

Manually add a connected headset to the running simulation. Normally headsets are added automatically on experiment launch.

{
"type": "add_player_headset",
"id": "player-ip-or-id"
}

remove_player_headset​

Remove a headset from the simulation and disconnect it.

{
"type": "remove_player_headset",
"id": "player-id"
}

id must match the player's id field (set by the headset on connection), not the internal IP key.

screen_control​

Switch the display mode shown on all monitor clients.

{
"type": "screen_control",
"display_type": "stream"
}

try_connection​

No-op in normal mode. Sent by the frontend to check whether GAMA is reachable. The GamaConnector manages its own reconnection independently.

{ "type": "try_connection" }

Messages: WebPlatform → Frontend​

json_state​

Broadcast to all connected monitor clients whenever GAMA or player state changes.

{
"type": "json_state",
"gama": {
"connected": true,
"experiment_state": "RUNNING",
"loading": false,
"content_error": "",
"experiment_id": "abc123",
"experiment_name": "My Simulation"
},
"player": {
"PlayerA": {
"id": "PlayerA",
"ping_interval": 5000,
"is_alive": true,
"connected": true,
"in_game": true,
"date_connection": "14:32"
}
}
}

gama.experiment_state values:

ValueMeaning
NONENo experiment loaded
NOTREADYExperiment loading
RUNNINGExperiment running
PAUSEDExperiment paused

In GAMALESS mode (ENV_GAMALESS=true), gama is an empty object {}.

get_simulation_by_index​

Response to a get_simulation_by_index or send_simulation request. Sent only to the requesting client. The simulation field is the full settings.json content for the selected VU (with model_file_path resolved to an absolute path).

{
"type": "get_simulation_by_index",
"simulation": {
"type": "json_settings",
"name": "Flood Model",
"splashscreen": "./splash.png",
"model_file_path": "/absolute/path/to/model.gaml",
"experiment_name": "Launch",
"minimal_players": "1",
"maximal_players": "6",
"selected_monitoring": "gama_screen"
}
}

selected_monitoring is optional; omit it to use the default display mode.

Catalog response (to get_simulation_informations)​

The server sends the raw JSON string of the nested catalog structure. Each entry is either a json_settings leaf or a catalog node:

[
{
"type": "json_settings",
"name": "Single-player demo",
"splashscreen": "./splash.png",
"model_index": 0
},
{
"type": "catalog",
"name": "Flood scenarios",
"entries": [
{ "type": "json_settings", "name": "Quang Binh", "model_index": 1 },
{ "type": "json_settings", "name": "Mekong Delta", "model_index": 2 }
]
}
]

screen_control​

Forwarded to all monitor clients when the display mode changes.

{
"type": "screen_control",
"display_type": "stream"
}

Auto-push on monitor connect​

When a monitor client connects, the WebPlatform automatically sends two messages without any request:

  1. json_state (as documented above) — current GAMA and player state.
  2. If a VU is currently selected, the full settings.json of the active model sent without a type envelope:
{
"type": "json_settings",
"name": "My Simulation",
"splashscreen": "./splash.png",
"model_file_path": "/absolute/path/to/model.gaml",
"experiment_name": "Launch",
"minimal_players": "1",
"maximal_players": "6"
}

The frontend uses this to restore the selected simulation card when the admin UI reconnects after a reload.


Headset WebSocket (HEADSET_WS_PORT)​

VR headsets (running the Unity app) connect to this port. The server uses each headset's IP address as its internal key.

Messages: Headset → WebPlatform​

connection​

First message sent by a headset after establishing the WebSocket connection. Registers the headset in the player list.

{
"type": "connection",
"id": "PlayerA",
"heartbeat": 5000
}
FieldTypeDescription
idstringHuman-readable player identifier (set in the Unity app, typically the headset color name)
heartbeatnumberDesired ping interval in milliseconds. Defaults to 5000 if omitted.

ping​

Sent by a headset to verify its connection is alive. The WebPlatform responds with pong.

{
"type": "ping",
"id": "PlayerA"
}

pong​

Response to a heartbeat ping sent by the WebPlatform.

{ "type": "pong" }

expression​

Send a GAML expression to be evaluated in the running GAMA simulation on behalf of this player. The literal string $id in expr is replaced with the player's id before being forwarded to GAMA.

{
"type": "expression",
"expr": "do my_action(player: $id);"
}

ask​

Send a GAML ask statement to GAMA on behalf of this player.

{
"type": "ask",
"action": "my_action",
"args": "{\"key\": \"value\"}",
"agent": "unity_linker[0]"
}

disconnect_properly​

Request a clean disconnection. The WebPlatform removes the player from GAMA and closes the WebSocket with code 1000.

{ "type": "disconnect_properly" }

Messages: WebPlatform → Headset​

ping​

Heartbeat sent by the WebPlatform at the interval negotiated during connection. The headset must respond with pong. If no response is received before the next ping, the connection is considered dead and terminated.

{ "type": "ping" }

pong​

Response to a headset-initiated ping.

{
"type": "pong",
"id": "PlayerA"
}

json_state​

Sent to a headset whenever its state changes (connection, in-game status). Contains all player fields except the internal WebSocket handle and timer.

{
"type": "json_state",
"id_player": "PlayerA",
"id": "PlayerA",
"ping_interval": 5000,
"is_alive": true,
"connected": true,
"in_game": false,
"date_connection": "14:32"
}

ping_interval is the heartbeat interval negotiated at connection (milliseconds). is_alive reflects the server-side liveness flag — it will be false if the server just sent a ping and is waiting for a pong.

json_output​

Simulation data from GAMA, targeted at this specific player. The contents field is the raw payload produced by the GAML model's send_world or send_geometries actions, filtered to only include entries addressed to this player's id.

{
"type": "json_output",
"contents": [
{ "key": "value" }
]
}

GAMA WebSocket (outbound client)​

The WebPlatform connects as a WebSocket client to the GAMA server at ws://<GAMA_IP_ADDRESS>:<GAMA_WS_PORT>.

GAML model requirements​

The WebPlatform uses the expression channel to call actions in the GAMA experiment. For the connection lifecycle to work, every GAML experiment used with SIMPLE must declare at least these two actions in the experiment block:

action create_player(string id_player) {
// called when a headset connects and joins the simulation
}

action remove_player(string id_player) {
// called when a headset disconnects or is removed
}

Omitting either action causes a GAMA compilation error when the WebPlatform calls them. Additional actions (for player interactions, map control, etc.) are defined per-model. See the GAML API Reference for the full abstract species definition.

tip

Use string for all action parameters called remotely. GAMA avoids type-casting errors when the argument is serialized as a JSON string.


Messages: WebPlatform → GAMA​

Load experiment​

{
"type": "load",
"model": "/absolute/path/to/model.gaml",
"experiment": "ExperimentName"
}

Control experiment​

{
"type": "play" | "pause" | "stop",
"exp_id": "<experiment-id>"
}

Send expression​

The WebPlatform sends expressions to GAMA in two contexts, which produce slightly different payloads.

Player lifecycle (create_player / remove_player) — no content field:

{
"type": "expression",
"exp_id": "<experiment-id>",
"expr": "do create_player(\"PlayerA\");"
}

Forwarded player expression (from a headset expression message) — includes a content label:

{
"type": "expression",
"content": "Send an expression",
"exp_id": "<experiment-id>",
"expr": "do my_action(\"PlayerA\");"
}

The content field is a static label added by GamaConnector.jsonSendExpression(). GAMA ignores it; it is safe to omit in client implementations.

Messages: GAMA → WebPlatform​

typeDescription
ConnectionSuccessfulGAMA accepted the WebSocket connection
SimulationStatusExperiment state changed; content holds the new state string
SimulationOutputJSON-encoded simulation output (content field); forwarded to headsets
CommandExecutedSuccessfullyA command was accepted; command.type === "load" carries the experiment name
SimulationStatusErrorSimulation state error
SimulationErrorDialogGAMA displayed an error dialog
SimulationErrorGeneric simulation error
RuntimeErrorGAMA runtime error
GamaServerErrorGAMA server-level error
MalformedRequestSent message was not valid
UnableToExecuteRequestGAMA could not execute the request

On any error type, the WebPlatform logs the error and sets content_error in the state broadcast to the admin UI.

On abnormal socket closure, the WebPlatform waits 5 seconds and attempts to reconnect automatically.