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

  1. Connect to the broker. No credentials are required in the default model.
  2. Subscribe, before the simulation starts, to:
    • Zendir/SpaceRange/<GAME>/Session
    • Zendir/SpaceRange/<GAME>/Info
    • Zendir/SpaceRange/<GAME>/<TEAM>/Downlink
    • Zendir/SpaceRange/<GAME>/<TEAM>/Response
  3. Watch Session. When state is running, the clock is advancing. Record instance; if it ever changes, the scenario reset and you must clear caches and re-run discovery.

NOTE

If you never receive a Session message, 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.

For every message on the team Downlink topic:

  1. XOR-decrypt the whole payload with the team password.
  2. Read the format byte and the four-byte little-endian team ID.
  3. Caesar-decrypt the remaining bytes with the team key.
  4. Branch on the format byte: 1 is a CCSDS packet parsed with the cached schema, 2 is media, 3 is an uplink intercept, 4 is 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.


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" }
}
  • Asset is 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.
  • Command is a command name, case-insensitive.
  • Time is the simulation second to execute. Zero or any past value runs immediately; a future value schedules the command.
  • Args is 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:

  1. list_assets for the spacecraft IDs.
  2. list_stations for the ground station names.
  3. list_entity per spacecraft for component names used in command arguments.
  4. get_packet_schemas to parse telemetry. Cache this per instance.
  5. get_telemetry for 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:

CommandPurpose
guidanceset the attitude pointing mode
thrustfire a thruster for a duration
rendezvoushold a relative position near another craft
dockingdock with or undock from another craft
cameraconfigure a camera or imager
capturetake and store an image
downlinkflush the on-board cache to the ground
power_busset switch, fuse, limiter, regulator, or load values
fuel_busset valve and pump values
resetpower-cycle a component
telemetrychange radio frequency, key, or bandwidth through the ground
encryptionrotate the key and frequency from the spacecraft, with the password
jammeractivate or deactivate the jammer payload
get_schedulerequest the queued command list
get_configurationrequest session-mutable operator configuration
remove_commandcancel a scheduled command
update_commandchange a scheduled command’s time or arguments

Ground request catalog

Requests are published on Request and scoped to your team:

RequestPurpose
list_assetsyour spacecraft and any shared targets
list_entitycomponents and jammer status for one craft
list_stationsground stations available to the team
get_packet_schemasthe field layout for every telemetry packet
get_telemetrycurrent frequency, key, bandwidth, and link budgets
set_telemetrychange your frequency, key, or bandwidth
transmit_bytessend arbitrary bytes from the ground transmitter
list_questions, submit_answerscenario questions
list_objectivesoperational objectives and completion state
chat_querythe mission assistant, when the scenario enables it

Admin request catalog

Admin requests use the Admin/Request topic and the admin password:

RequestPurpose
admin_list_entitiesevery team and station
admin_list_teamfull configuration of one team
admin_query_datahistorical telemetry snapshots
admin_query_eventshistorical tracking events
admin_get_simulation, admin_set_simulationread or control run state and speed
admin_set_telemetryforce a team’s radio settings, for lockout recovery
admin_get_scenario_eventslist scripted events

Robustness

  • Key each request by req_id and apply a timeout and retry. Delivery is best-effort on QoS 0.
  • Re-run discovery whenever instance changes.
  • Keep your Caesar key in sync. If the team rotates the key with encryption or set_telemetry, update the value you use to decode downlink, or recover with the admin admin_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.