This repository uses the REUSE Specification (https://reuse.software/) to make licensing clear and machine-checkable.
LICENSE: MIT license text for this repository.REUSE.toml: REUSE configuration (defaults to MIT for annotated files).REUSE-toolbox.txt: A lightweight checklist of file patterns and intended license ownership.REUSE.md: Explanation of the repository’s major components (and how to interpret license coverage).
Note: Third-party assets/binaries (e.g.,
de421.bsp,video/*.mp4, images inassets/) may be governed by their own licenses. Add/adjustREUSE-toolbox.txt(and eventuallyREUSE.tomlpath annotations) if you discover different terms.
This project is a desktop “Satellite Tracker” ground-station application built with PyQt5 + PyQtWebEngine.
At a high level:
- TLE catalog sync: download and cache Two-Line Element (TLE) data from multiple sources.
- Orbit prediction: compute the satellite future orbit path and the next visible pass.
- Tracking loop: poll external services (SatTrack via N2YO/other providers) and/or local hardware to drive the antenna/switch.
- Visualization: render a map (HTML/JS) and show telemetry plots (pyqtgraph).
- Hardware bridge + diagnostics: optional TCP bridge to external controllers + a diagnostics dashboard.
- Entry point for the desktop application.
- Loads environment variables (
python-dotenv). - Applies Qt high-DPI settings.
- Installs a global exception hook that logs unhandled exceptions and shows a
QMessageBox. - Creates and shows the
MainWindow.
Key behavior:
- Sets
QTWEBENGINE_CHROMIUM_FLAGSto disable GPU for stability. - Uses the dark theme defined in
src/ui/styles.py.
- Marks the
srcdirectory as a package.
BaseAPIClientprovides a sharedrequests.Sessionwith:- retry logic (
urllib3.util.retry.Retry) - common headers (browser-like
User-Agent)
- retry logic (
_get()performs JSON GET requests with consistent logging and safe failure behavior.
N2YOClientfetches real-time satellite positions/frequencies.- Includes local caching for SatNOGS transmitter frequency queries.
- Uses
BaseAPIClient.sessionfor request retries/headers.
GeocodeClientresolves user-entered cities into(lat, lng).
SpaceTrackClienthandles Space-Track login and authenticated TLE query execution.- Provides
authenticate()andget_gp_data(). - Performs query-filter validation logic before requesting results.
OrbitEngineis the mathematical “heart” of the system.- Initializes Skyfield:
self.ts = load.timescale()- attempts to load
de421.bsp(ephemeris data)
parse_tle_file(filepath):- reads TLE files line-by-line
- supports 2-line TLE pairs (
1 ...then2 ...) - supports optional 3-line format by inferring the name from the preceding line
- parses NORAD ID and epoch, returning a dict keyed by NORAD ID string
get_sun_position(dt)andget_moon_position(dt):- computes subpoint lat/lon via Skyfield.
PredictionWorkeris aQThread.run():- Builds a Skyfield
EarthSatellitefromline1/line2. - Computes ground track points for the next ~95 minutes.
- Predicts the next pass within a 2-day window using
satellite.find_events(). - Emits a dict containing:
orbit_path(list of[lat, lon])pass_details(rise/max/set times + max elevation)pass_path(ground track during the pass)
- Builds a Skyfield
- Not included in the snippets above, but this module typically:
- polls satellite position / link metrics
- computes and/or forwards telemetry
- emits
data_readyanderror_occurredsignals
DataManagerowns local persistence:satellite_data/directory for telemetry JSONtle_data/directory for cached TLE text files
- Provides:
_get_telemetry_path(satellite_name)sanitizationsave_satellite_telemetry()(thread-safe viaLock)load_satellite_telemetry()get_tle_path(filename)list_downloaded_tles()
TleSyncManagerdownloads and caches TLE sources.- Uses:
_is_cache_fresh()based onmtimeandcache_days_download_url()with retries and streamed downloads_download_spacetrack_source()for authenticated sources
download_sources(selected_sources)returns saved file paths for synced sources.
ApiKeyManager: stores/retrieves API keys via system keyring.CredentialManager: stores/retrieves Space-Track username/password securely.
- Provides background setup for UI dialogs.
- Used by dialogs (e.g.
SourceSelectionDialog) to render a video/visual background.
- Not shown in full above, but it is responsible for:
- connecting to Arduino/ESP32 boards over serial
- selecting RF coupler channels
- sending antenna telemetry (az/el)
- maintaining
connection_changedsignals and anarduino_data_receivedsignal
- Provides TCP bridge server/client capabilities.
- Used by:
- main UI for networked hardware control
- diagnostics dashboard for remote telemetry
- The primary Qt window.
- Constructs:
- left command panel: satellite search, ground station config, hardware interface config, and source selection.
- center split view: map view (QWebEngineView) + log panel.
- right telemetry panel.
- Integrates:
OrbitEnginefor TLE parsing and sun/moon positions.PredictionWorkerand tracking worker threads.TleSyncManagerviashow_source_dialog().
Key workflows:
-
TLE sync:
show_source_dialog()opensSourceSelectionDialog- optionally gates Space-Track login
- sync runs in a background thread calling
_run_sync() - results merged and emitted back to UI via signals
-
Start tracking:
- validates selected satellite and observer inputs
- optionally queries bridge for GPS status
- creates
PredictionWorkerand tracking worker(s) - forwards real-time telemetry to:
- map bridge
- telemetry panel
HardwareManager(local) and/or TCP bridge (remote)
SourceSelectionDialog(QDialog) shows categorized checkboxes for TLE sources.setup_ui()groups sources bygroupfield fromDEFAULT_TLE_SOURCES.- Supports “Select All” / “Deselect All”.
get_selected_sources()returns a list of selected source keys after dialog is accepted.
- A full-screen (desktop) diagnostics dashboard.
- Contains custom widgets:
CircularGaugefor critical telemetryPlatformAttitudeWidgetfor pitch/roll stabilization displayLimitSwitchesWidgetfor safety/limit statesHealthIndicatorandResourceBarUI elementsRFSignalChainWidgetfor showing the active RF switch channel
- Uses
HardwareDiagnosticsClientto receive telemetry. - Maintains deques and pyqtgraph curves for:
- tracking errors over time
- motor current requirements
- RF spectrum
Important runtime behaviors:
_on_telemetry_update():- resets waveform history when the satellite changes
- handles simulation vs direct hardware modes
- updates both gauges and plots
closeEvent()stops the client and background polling timers.
assets/map/index.htmlis rendered insideQWebEngineView.src/ui/bridge.pyexposes a JS bridge (QWebChannel) so Python can update:- observer position
- satellite position
- predicted orbit and pass paths
- Defines
DEFAULT_TLE_SOURCES. - Each TLE source includes metadata used by:
- source dialog grouping
- sync logic (URL/mirrors/auth/cache days)
- Space-Track query parameters
- Configures a global logger instance named
PySatTrack. - Uses a custom
ImmediateFlushFileHandlerto flush logs to disk after each write.
The files created for REUSE are present at repository root.
However, REUSE (strict) typically relies on per-file SPDX headers (or REUSE annotations per path). This repository currently does not automatically embed SPDX headers in every source file.
To make strict REUSE checks pass in the future, preferred options are:
- Add SPDX headers to each source file (e.g.
# SPDX-License-Identifier: MIT). - Or expand
REUSE.tomlwith[[annotations]]rules that fully cover all relevant file types and confirm the checkers accept directory-level coverage (behavior depends on the REUSE tool version).
REUSE-toolbox.txt already documents what to review (assets, third-party binaries, TLE catalogs).
This project uses external Python dependencies listed in requirements.txt:
- PyQt5 / PyQtWebEngine
- skyfield
- requests
- spacetrack
- pyserial
- python-dotenv
- keyring
- psutil
- pyqtgraph
Their licenses are separate from this repository’s MIT license. This REUSE documentation focuses on licensing for this repository’s code.
- User selects TLE sources (
SourceSelectionDialog). TleSyncManagerdownloads/cache files.OrbitEngine.parse_tle_file()loads TLEs.PredictionWorkercomputes orbit + pass.- Tracking worker repeatedly updates telemetry.
- UI renders:
- map updates through
MapBridge - plots through pyqtgraph
- hardware states through diagnostics and/or hardware managers
- map updates through