MQTT telemetry bridge for Kerbal Space Program 1.12.5. A KSP 1.x companion to KSA-Bridge: the plugin publishes vessel telemetry from inside the game over MQTT so browsers, scripts, ESP32s, Grafana, or any MQTT subscriber can consume real-time flight data. Wire format matches KSA-Bridge's topic names and JSON schemas, so consoles and dashboards built for one game work against the other with only a topic-prefix change.
The bundled hard-scifi FDO console rendering live telemetry from KSP — see Browser console for how to run it.
Eighteen telemetry topics shipping — full KSA-Bridge schema parity. The hard-scifi FDO console included in this repo lights up end-to-end: vessel identification, orbital elements, state vectors, navigation readouts, attitude (with full Unity quaternion), maneuver plan, SOI encounters, performance (ΔV / TWR), and live planet rotation all populate from real game data.
v0.15 closes out the original KSA-Bridge schema backlog by adding the last five planned topics:
dynamics(5 Hz) — body-frame angular velocity (pitch/yaw/roll rates), body-frame linear acceleration, finite-differenced angular acceleration, and current g-load (sourced fromVessel.geeForceso it matches the stock G-meter exactly).resources(2 Hz) — wet/dry/resource mass plus a per-resource breakdown aggregated across every part on the vessel. One entry per resource type (LiquidFuel, Oxidizer, MonoPropellant, ElectricCharge, …) with current amount, capacity, density, and pre-computed mass.situation(1 Hz) — the eightVessel.situationenum values expanded into individual booleans (landed,splashed,prelaunch,flying,subOrbital,orbiting,escaping,docked) plus derived flags (onSurface,inAtmosphere,controllable).atmosphere(5 Hz) — atmospheric density, static and dynamic pressure, ambient and external (heated) temperature, Mach number, and parent-body atmosphere context flags.staging(1 Hz, retained) — what fires on the next staging event: parts-, engine-, and decoupler-counts plus part display titles for both the next-to-fire stage and the one after that.
Since v0.11 the bridge has also added:
- Quaternion attitude. The
attitudepayload now carriesrotationX/Y/Z/W— the vessel root transform's full Unity quaternion. External 3D renderers can pose a vessel as a rigid body without re-deriving rotation from heading/pitch/roll. - Target-vessel telemetry.
target/vehicle,target/state_vectors, andtarget/attitudemirror the active-vessel topics whenever a vessel-bearing target is selected. Schemas are byte-for-byte identical to the active-vessel versions, so consoles built for the active vessel work for the target with zero parsing changes. - Docking context.
docking/contextis a retained, 1 Hz lifecycle topic for docking scenarios. It reports controlling/target docking ports bypersistentId+ module index, plus a coarse engagement state (idle/armed/soft_dock/hard_dock/disabled). Late subscribers see the current state immediately thanks to MQTT retention.
The console is body-aware for every stock world. When the active vessel
transitions between SOIs, the globe swaps to the appropriate body's vector
layers automatically. v0.11 unified every body under one multi-contour
pipeline (scripts/build_body_contours.py):
- Tier 1 — rich-feature bodies: Kerbin, Eve, Moho, Ike, Tylo, Vall, Laythe — each gets 3–6 traced contour layers with a per-body colour ramp (deep ocean → highland peaks for Kerbin; rust basins → tan peaks for Duna; purple valleys → bright highlands for Eve; etc.).
- Tier 2 — uniform bodies: Gilly, Bop, Pol, Minmus, Eeloo, Dres — 1–4 traced layers showing their principal features.
- Special — Jool: synthetic horizontal cloud bands since it's a gas giant. No image tracing; the bands are emitted directly by the script.
- Mun, Duna: retain their original dedicated pipelines; both still use
the same
bodyLayersFromContours()renderer on the console side.
Surface sources come from the stock game plus biome maps pulled from the
JNSQ mod for Laythe and Minmus. The
Python pipeline converts every source image into a per-body *_contours.js
asset with traced polygon rings and a colour palette, then the FDO console's
BODY_REGISTRY wires each one to the globe renderer.
All KSA-Bridge schema topics now have producers. See docs/TOPICS.md for the full authoritative schema reference for every published topic.
The simplest path is to grab a built release from the GitHub Releases page rather than building from source. The release zip follows the standard KSP mod layout — extract it into your KSP install root and the plugin lands in the right place.
- Download the latest
KSPBridge-vX.Y.Z.zipfrom Releases. - Extract into your KSP install root — the folder containing
KSP_x64.exe. On a default Steam install this isC:\Program Files (x86)\Steam\steamapps\common\Kerbal Space Program\. The zip'sGameData/KSPBridge/folder will land alongside KSP's built-inGameData/Squad/(and any other mods). - Edit
GameData/KSPBridge/Settings.cfgto point at your MQTT broker. The shipped defaults (localhost:1883, topic prefixksp/telemetry) work as-is if you run Mosquitto on the same machine as KSP. For a remote broker (homelab, VM, cloud), setbroker_hostto its hostname or IP. See Configuration below. - Launch KSP. The plugin connects to the broker on startup and begins publishing as soon as you enter the flight scene.
The release zip ships with install-check.bat (and a sibling
install-check.ps1) inside GameData/KSPBridge/. Double-click
install-check.bat — it walks every prerequisite and reports
pass / warn / fail per check:
- KSP install detected
- Plugin DLLs deployed under
Plugins/ KSPBridge.versionparses (KSP-AVC compat metadata)Settings.cfgpresent with all four required fields valid- TCP socket open to
broker_host:broker_port - MQTT round-trip (publishes + subscribes a test message)
- WebSocket listener reachable (for the FDO browser console)
- FDO console HTML files present (only in source checkouts; the release zip does not bundle the browser console)
- Python on PATH (used to serve the console)
python -m http.serveractually serves the console URL
Exit code is 0 when everything required passes, 1 otherwise. Warnings (e.g. WebSocket not configured, Python missing) are non-blocking — the plugin itself only needs items 1-6.
For a manual check, KSP's own log file at <KSP root>\KSP.log
should contain [KSPBridge] lines: version banner, broker
target, and MQTT connected to <host>:<port>. From any machine
that can reach your broker:
mosquitto_sub -h <broker_host> -p <broker_port> -t 'ksp/telemetry/#' -v
In the flight scene you should see all 18 topics ticking on
their respective rates. _bridge/status is retained — even
outside the flight scene a fresh subscriber should see at
least the heartbeat.
The release zip contains both the plugin DLLs and a reference
Settings.cfg. If you're upgrading and have already customised your
broker settings, back up your Settings.cfg before extracting —
Windows extraction tools overwrite by default and will silently clobber
your edits. Alternatively, extract only the GameData/KSPBridge/Plugins/
subfolder and skip the rest of the archive.
If you're building from source instead, the dotnet build post-build
target only deploys *.dlls; your existing Settings.cfg is preserved
across rebuilds.
KSP 1.12.5 (Unity 2019.4, .NET Framework 4.7.1)
│
├── KSPBridge.dll Our plugin
│ ├── KSPBridgePlugin KSPAddon entry point, heartbeat pump
│ ├── Settings Loads GameData/KSPBridge/Settings.cfg
│ ├── Mqtt.MqttBridge ManagedMqttClient wrapper, LWT, reconnect
│ └── Telemetry.TelemetryScheduler
│ └── Producers/ One ITelemetryProducer per topic
│
├── MQTTnet.dll Third-party, MIT
└── MQTTnet.Extensions.ManagedClient.dll
│
│ TCP 1883
▼
Mosquitto 2.0 (Docker, homelab)
│ WebSocket 9002
▼
consoles/hard-scifi/*.html Browser console
(Three.js + MQTT.js)
Scheduler runs at a fixed 10 Hz tick on Unity's main thread; each producer
declares a RateDivisor so 10 Hz, 5 Hz, and 2 Hz topics all fire from a
single beat. One try/catch per producer keeps a bad payload from starving
the rest. See
src/KSPBridge/Telemetry/TelemetryScheduler.cs
for the full implementation.
KSPBridge/
src/KSPBridge/ C# plugin source (.NET Framework 4.7.1)
KSPBridge.csproj
Plugin.cs KSPAddon entry point
Settings.cs
Mqtt/
MqttBridge.cs
Telemetry/
ITelemetryProducer.cs Interface contract
TelemetryScheduler.cs 10Hz tick + rate division
VehicleTelemetry.cs POCOs per topic
OrbitTelemetry.cs
... (one per topic)
Producers/ One class per topic
VehicleProducer.cs
OrbitProducer.cs
... (one per topic)
GameData/KSPBridge/ Deployment-shaped folder
Plugins/ Build populates this
Settings.cfg Broker host/port/prefix
consoles/hard-scifi/ Browser FDO console
hardscifi-fdo-console.html
lib/ Three.js, MQTT.js, topojson-client
data/ Planet topojson/geojson assets
docs/
TOPICS.md Full schema reference
THIRD-PARTY-NOTICES.md
LICENSE (MIT)
Requires Visual Studio 2022 or 2026 with the .NET desktop development workload and the .NET Framework 4.7.1 targeting pack installed.
- Open
KSPBridge.sln. - Build → Build Solution (
Ctrl+Shift+B). - Post-build automatically deploys the built DLLs to
<KSP install>\GameData\KSPBridge\Plugins\. - On first install, also copy
GameData/KSPBridge/Settings.cfgfrom this repo to the matching folder in your KSP install. Subsequent builds will NOT overwrite it, so your edits persist.
The csproj defaults KSPRoot to
C:\Program Files (x86)\Steam\steamapps\common\Kerbal Space Program. If
your install is elsewhere, override via an env var named KSPRoot or add
a Directory.Build.props next to the sln setting the property.
Edit GameData/KSPBridge/Settings.cfg in your KSP install:
KSPBRIDGE
{
broker_host = localhost
broker_port = 1883
topic_prefix = ksp/telemetry
client_id = kspbridge
}
The defaults assume Mosquitto is running on the same machine as KSP.
For a remote broker (homelab, VM, cloud), set broker_host to the
broker's hostname or IP.
The bundled consoles/hard-scifi/hardscifi-fdo-console.html is an FDO-style
mission-control dashboard adapted from KSA-Bridge. Open it via a local HTTP
server (file:// breaks texture loads in most browsers) — connects to the
configured Mosquitto broker over WebSocket and subscribes to
ksp/telemetry/#. Three.js draws the planet and orbit; the panels pull
live data from the topics documented in docs/TOPICS.md.
The default broker URL is ws://appserv1.local:9002. To target a
different broker without editing the file, append a ?broker= query
parameter — for example
http://localhost:8000/hardscifi-fdo-console.html?broker=ws://localhost:9002.
Quick start:
cd consoles/hard-scifi
python -m http.server 8000
# then open http://localhost:8000/hardscifi-fdo-console.htmlinstall-check.bat (shipped in the release zip) can also start the
console for you: after the verification checks pass it offers an
interactive prompt to spin up python -m http.server and open the
console URL with the broker query parameter pre-filled to match your
Settings.cfg.
The globe rendering switches dynamically based on the parent_body topic.
Each body's data lives next to the console:
consoles/hard-scifi/
data/
kerbin_mask.png + kerbin_coastline.js (full coastlines + ice rings)
mun_mask.png + mun_basin.js (basin outlines)
duna_mask.png + duna_ice.js (multi-level topo contours + ice)
source/
bodies/ (raw body maps awaiting wire-up)
To add a new body's detailed map:
- Drop the equirectangular surface image into
source/bodies/<body>.{jpg,png}. - Run
python scripts/build_kerbin_topojson.py --body <body> --input ... --js-output ... --mask-png ...(Kerbin / Mun / Duna pipelines exist; new bodies typically need a small dedicated pipeline branch tuned to their palette). - Add a
<script src="...">tag to the console HTML head. - Add an entry to
BODY_REGISTRYin the console's JS.
Bodies without detailed assets render as flat-coloured spheres via
BODY_FALLBACK_COLORS (every stock body has a tuned colour).
The plugin's wire format deliberately mirrors KSA-Bridge's. Field names,
JSON shapes, unit conventions (metres / seconds / radians), and topic
suffixes match. The only structural difference is the topic prefix
(ksp/telemetry/* vs ksa/telemetry/*). Any KSA-Bridge console or
subscriber can be pointed at KSPBridge with a single string change.
KSPBridge adds two fields not present in KSA-Bridge:
id— KSPVessel.idas a Guid string, stable across save/load.persistentId— KSPVessel.persistentIdas a uint, stable within a save.
Both are emitted on every topic payload so consumers can correlate data across topics for a specific vessel (vessel names alone are not unique).
MIT. See LICENSE. Bundled third-party libraries listed in THIRD-PARTY-NOTICES.md.
