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",
"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.

{
"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",
"model_index": 0
}
}

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"
}

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",
"connected": true,
"in_game": false,
"date_connection": "14:32"
}

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>.

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 (player action or ask)

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

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.