You can replace the bundled Operator tool with your own software in any language that has an MQTT client. A terminal is a peer on the broker: it subscribes to telemetry, decodes it, and publishes commands. This page is the minimal end-to-end recipe. For the exact payloads and ciphers, use the MQTT Protocol Reference.
What you need before connecting
There is no handshake and no login. The facilitator gives you everything out of band:
- the broker address and port
- the game name, which is the
<GAME>path segment - your numeric team ID, which is the
<TEAM>path segment - your six-character team password, used as the XOR key
- the starting team key, an integer from 0 to 255, used as the Caesar key on downlink
The six-character access code a facilitator hands out is the team password.
Connecting and subscribing
- Connect to the broker. No credentials are required in the default model.
- Subscribe, before the simulation starts, to:
Zendir/SpaceRange/<GAME>/SessionZendir/SpaceRange/<GAME>/InfoZendir/SpaceRange/<GAME>/<TEAM>/DownlinkZendir/SpaceRange/<GAME>/<TEAM>/Response
- Watch
Session. Whenstateisrunning, the clock is advancing. Recordinstance; if it ever changes, the scenario reset and you must clear caches and re-run discovery.
NOTE
If you never receive a
Sessionmessage, your terminal and Studio are not on the same broker, the game name does not match, or the simulation is not running.
Verifying credentials
Publish a list_assets request and confirm a clean JSON reply on Response:
- Garbled JSON after XOR-decoding means the password is wrong.
- No reply at all means the team ID is wrong, the team is disabled, or the simulation is not running.
Decoding downlink
For every message on the team Downlink topic:
- XOR-decrypt the whole payload with the team password.
- Read the format byte and the four-byte little-endian team ID.
- Caesar-decrypt the remaining bytes with the team key.
- Branch on the format byte:
1is a CCSDS packet parsed with the cached schema,2is media,3is an uplink intercept,4is a detector frame.
# Language-neutral pseudocode. See the Protocol Reference for the ciphers.
raw = xor(team_password, payload)
if len(raw) < 5:
return
fmt = raw[0]
team_id = int_from_little_endian(raw[1:5])
body = caesar_decrypt(team_key, raw[5:])
handle(fmt, body)Parse CCSDS packets with the schema from get_packet_schemas. The Ping packet on APID 100 is the heartbeat and reports state, memory, battery, and recently executed commands.
Encoding uplink
Build the command envelope, serialize it to JSON, XOR-encrypt it with the team password, and publish to Zendir/SpaceRange/<GAME>/<TEAM>/Uplink. There is no Caesar layer on uplink.
{
"Asset": "A3F2C014",
"Command": "guidance",
"Time": 0,
"Args": { "pointing": "nadir" }
}Assetis the eight-character hex spacecraft ID. The uplink topic is shared by the team, so only the spacecraft whose ID matches executes the command; others drop it silently.Commandis a command name, case-insensitive.Timeis the simulation second to execute. Zero or any past value runs immediately; a future value schedules the command.Argsis the command-specific argument object.
Bootstrapping with ground requests
Ground requests use the team Request and Response topics and are XOR-only. Each request is { "type": ..., "req_id": ..., "args": {...} }; each reply echoes req_id and adds success and error. On connect, run:
list_assetsfor the spacecraft IDs.list_stationsfor the ground station names.list_entityper spacecraft for component names used in command arguments.get_packet_schemasto parse telemetry. Cache this perinstance.get_telemetryfor the current frequency and the Caesar key you need to decode downlink.
Always demultiplex Response by type, because it also carries unsolicited pushes such as event_triggered, objective_completed, and score_updated.
Command catalog
Commands are published on Uplink and target one spacecraft by Asset:
| Command | Purpose |
|---|---|
guidance | set the attitude pointing mode |
thrust | fire a thruster for a duration |
rendezvous | hold a relative position near another craft |
docking | dock with or undock from another craft |
camera | configure a camera or imager |
capture | take and store an image |
downlink | flush the on-board cache to the ground |
power_bus | set switch, fuse, limiter, regulator, or load values |
fuel_bus | set valve and pump values |
reset | power-cycle a component |
telemetry | change radio frequency, key, or bandwidth through the ground |
encryption | rotate the key and frequency from the spacecraft, with the password |
jammer | activate or deactivate the jammer payload |
get_schedule | request the queued command list |
get_configuration | request session-mutable operator configuration |
remove_command | cancel a scheduled command |
update_command | change a scheduled command’s time or arguments |
Ground request catalog
Requests are published on Request and scoped to your team:
| Request | Purpose |
|---|---|
list_assets | your spacecraft and any shared targets |
list_entity | components and jammer status for one craft |
list_stations | ground stations available to the team |
get_packet_schemas | the field layout for every telemetry packet |
get_telemetry | current frequency, key, bandwidth, and link budgets |
set_telemetry | change your frequency, key, or bandwidth |
transmit_bytes | send arbitrary bytes from the ground transmitter |
list_questions, submit_answer | scenario questions |
list_objectives | operational objectives and completion state |
chat_query | the mission assistant, when the scenario enables it |
Admin request catalog
Admin requests use the Admin/Request topic and the admin password:
| Request | Purpose |
|---|---|
admin_list_entities | every team and station |
admin_list_team | full configuration of one team |
admin_query_data | historical telemetry snapshots |
admin_query_events | historical tracking events |
admin_get_simulation, admin_set_simulation | read or control run state and speed |
admin_set_telemetry | force a team’s radio settings, for lockout recovery |
admin_get_scenario_events | list scripted events |
Robustness
- Key each request by
req_idand apply a timeout and retry. Delivery is best-effort on QoS 0. - Re-run discovery whenever
instancechanges. - Keep your Caesar key in sync. If the team rotates the key with
encryptionorset_telemetry, update the value you use to decode downlink, or recover with the adminadmin_set_telemetry.
This completes the integration path. To host the broker these clients connect to, see Running Your Own MQTT Broker. For payload details, see the MQTT Protocol Reference.