A native Rust desktop satellite monitor โ Hermes, messenger of the gods, now watching the heavens for you.
In Greek mythology, Hermes โ winged sandals, winged cap โ is the swift messenger of the gods, patron of travelers and the skies. Hermes Watch gives that role to your desktop: it fetches live two-line element (TLE) sets from public catalogs, propagates every orbit with SGP4, and renders the whole constellation in real time.
3D globe pane โ live SGP4 orbit on a textured Earth
- ๐ Live catalogs โ pulls TLEs from Celestrak on startup (~18 000 objects across 6 groups) and auto-refreshes every 2 hours
- ๐ฐ SGP4 propagation โ full SGP4/SDP4 model, TEME โ geodetic conversion, sub-satellite points and ground tracks (past 45 min โ future 90 min), true inertial (ECI) orbit ellipses
- ๐ฅ Native UI โ egui/eframe with the glow renderer; no web stack, no Electron. GPU-textured rotating Earth with day/night terminator
- ๐ช Split panes โ 1 / 2H / 2V / 4 independent viewports, each with its own camera and selected satellite
- ๐ Catalog sidebar โ a light panel with full-width clickable rows: full-text filter (name / NORAD id) + a color-coded category dropdown (All ยท Station ยท Weather ยท Navigation ยท Science ยท Comms ยท Military ยท Debris ยท Other), each entry showing its object count. Row names are black; satellites whose elements cannot be propagated are red. Left click points the current pane at that row; right click opens a row menu โ Add <name> to Window N (retargets that pane, replacing whatever it tracked, and flashes a short white
Added โฆnotice in the pane's top-left for a few seconds) plus Copy NORAD id / Copy TLE. - ๐บ Four view types โ 3D Globe ยท World Map ยท Ground Track ยท Detail โ switchable independently per pane
Each pane can independently render one of four views:
| View | What you see |
|---|---|
| 3D Globe | GPU-textured rotating Earth with day/night terminator, satellite markers in 3D space and the full ECI orbit ellipse of the selected satellite. Drag to orbit the camera, scroll to zoom. |
| World Map | 2D equirectangular map with all catalog satellites at their current sub-satellite points, color-coded by group. |
| Ground Track | The selected satellite's ground track โ past 45 minutes (fading) โ future 90 minutes โ plus sub-satellite point and footprint circle. |
| Detail | Live orbital elements of the selected satellite: lat/lon/alt, velocity, period, inclination, epoch age, and TLE text. |
Use the toolbar to switch the workspace between:
- 1 โ single full-area viewport
- 2H / 2V โ two panes side by side / stacked
- 4 โ quadrant layout
Every pane keeps its own view type, camera state and target satellite, so you can watch, e.g., the globe in one pane and the ground track in another simultaneously.
cargo run --releaseRequires a stable Rust toolchain (MSVC target on Windows). First build takes a few minutes; subsequent incremental builds are fast.
# Whole suite โ library + binary targets
cargo test
# Library target only
cargo test --libcargo test covers both targets. src/lib.rs declares the ui module, so cargo test --lib also builds and runs the UI tests (src/ui/views/globe3d_tests.rs). Without that declaration the UI tests would exist only in the binary target and --lib would print a passing result while silently skipping every one of them.
On startup the app immediately fetches all 6 Celestrak groups in parallel. While fetching, the status bar shows progress (sources done / total, object count). If a source fails (network blocked, timeout), the error is shown in the status bar and the remaining sources still load.
- Requests go to
celestrak.orgwith a browser-likeUser-Agent(bare clients get HTTP 403). - An HTTP(S) proxy can be configured in the toolbar settings dialog; changes take effect on the next refresh. The
SAT_PROXYenvironment variable (e.g.SAT_PROXY=http://127.0.0.1:7890) is used as a fallback when no proxy is set in the UI.
โโโโโโโโโโโโโโโ mpsc channel โโโโโโโโโโโโโโโโ
โ tokio RT โ โโโโโโโโโโโโโโโโโโโถ โ egui App โ
โ fetch svc โ FetchMsg::Done โ (UI thread) โ
โโโโโโโโฌโโโโโโโ โโโโโโโโฌโโโโโโโโ
โ HTTP (Celestrak) โ reads
โผ โผ
TLE text parse Arc<RwLock<catalog>> / Arc<RwLock<status>>
โ
โผ
SGP4 propagate per frame
(orbit.rs, cached)
main.rsโ builds a 4-worker tokio runtime, sharedArc<RwLock>state, launches eframe.data/fetch/โ source list (6 Celestrak endpoints) + TLE parsing;FetchConfigcarries the optional proxy.service.rsโ spawns one task per source; each completed source is sent to the UI as aFetchMsgand merged into the catalog.orbit.rsโ SGP4 wrapper: propagates TEME state vectors, converts to geodetic lat/lon/alt, generates ground tracks and ECI orbit polylines (results cached per epoch to keep the UI at 60 fps).ui/โapp.rsowns state, toolbar, sidebar and split layout;panes.rsdraws pane chrome;views/implements the four renderers.
src/
โโโ main.rs entry point: async runtime + eframe launch
โโโ data/
โ โโโ model.rs Sat / SatGroup types, TLE structs
โ โโโ fetch/ Celestrak sources, HTTP client, TLE parsing
โโโ orbit.rs SGP4 propagation, TEME โ geodetic conversion
โโโ service.rs background fetch service (tokio)
โโโ ui/
โโโ app.rs application state, toolbar, sidebar, split layout
โโโ panes.rs pane layout & chrome
โโโ views/
โโโ globe3d.rs 3D textured globe (+ tests)
โโโ world_map.rs 2D equirectangular map
โโโ ground_track.rs ground track renderer
โโโ detail.rs orbital element inspector
โโโ catalog.rs sidebar list & filter
| Symptom | Likely cause / fix |
|---|---|
| Source errors in status bar, few or no satellites | Celestrak unreachable from your network โ set a proxy in the toolbar settings (or SAT_PROXY) and refresh |
| HTTP 403 in errors | Client blocked โ the app already sends a browser UA; a proxy may still be needed |
| Empty globe/map but catalog sidebar populated | Propagation epoch too old โ wait for the next 2 h auto-refresh and pick a satellite with a recent epoch |
| Build fails on Linux | Install X11/Wayland dev packages (eframe x11/wayland features) |
MIT
