termradar 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- termradar-0.3.0/.gitignore +34 -0
- termradar-0.3.0/CHANGELOG.md +79 -0
- termradar-0.3.0/LICENSE +21 -0
- termradar-0.3.0/PKG-INFO +144 -0
- termradar-0.3.0/README.md +110 -0
- termradar-0.3.0/docs/ARCHITECTURE.md +147 -0
- termradar-0.3.0/docs/DATA_PROVIDERS.md +188 -0
- termradar-0.3.0/docs/DEVELOPMENT.md +126 -0
- termradar-0.3.0/docs/ROADMAP.md +574 -0
- termradar-0.3.0/docs/assets/demo-quick.gif +0 -0
- termradar-0.3.0/docs/assets/demo-quick.tape +17 -0
- termradar-0.3.0/pyproject.toml +77 -0
- termradar-0.3.0/src/termradar/__init__.py +3 -0
- termradar-0.3.0/src/termradar/__main__.py +6 -0
- termradar-0.3.0/src/termradar/cli.py +285 -0
- termradar-0.3.0/src/termradar/config/__init__.py +23 -0
- termradar-0.3.0/src/termradar/config/storage.py +207 -0
- termradar-0.3.0/src/termradar/core/__init__.py +13 -0
- termradar-0.3.0/src/termradar/core/airline.py +36 -0
- termradar-0.3.0/src/termradar/core/bearing.py +25 -0
- termradar-0.3.0/src/termradar/core/distance.py +24 -0
- termradar-0.3.0/src/termradar/core/engine.py +154 -0
- termradar-0.3.0/src/termradar/core/limits.py +14 -0
- termradar-0.3.0/src/termradar/core/location.py +18 -0
- termradar-0.3.0/src/termradar/core/models.py +73 -0
- termradar-0.3.0/src/termradar/core/rate_limit.py +35 -0
- termradar-0.3.0/src/termradar/core/timezone.py +23 -0
- termradar-0.3.0/src/termradar/providers/__init__.py +15 -0
- termradar-0.3.0/src/termradar/providers/adsbdb.py +158 -0
- termradar-0.3.0/src/termradar/providers/aircraft.py +293 -0
- termradar-0.3.0/src/termradar/providers/base.py +36 -0
- termradar-0.3.0/src/termradar/providers/geocoding.py +137 -0
- termradar-0.3.0/src/termradar/providers/routes.py +225 -0
- termradar-0.3.0/src/termradar/renderers/__init__.py +7 -0
- termradar-0.3.0/src/termradar/renderers/bearing_display.py +36 -0
- termradar-0.3.0/src/termradar/renderers/formatting.py +73 -0
- termradar-0.3.0/src/termradar/renderers/location_display.py +68 -0
- termradar-0.3.0/src/termradar/renderers/radar_canvas.py +209 -0
- termradar-0.3.0/src/termradar/renderers/radar_coords.py +65 -0
- termradar-0.3.0/src/termradar/renderers/terminal.py +27 -0
- termradar-0.3.0/src/termradar/renderers/terminal_ui.py +232 -0
- termradar-0.3.0/src/termradar/renderers/terminal_view.py +35 -0
- termradar-0.3.0/src/termradar/renderers/time_display.py +33 -0
- termradar-0.3.0/src/termradar/session.py +132 -0
- termradar-0.3.0/tests/conftest.py +1 -0
- termradar-0.3.0/tests/fakes.py +54 -0
- termradar-0.3.0/tests/test_adsbdb.py +169 -0
- termradar-0.3.0/tests/test_aircraft.py +185 -0
- termradar-0.3.0/tests/test_airline.py +76 -0
- termradar-0.3.0/tests/test_bearing.py +37 -0
- termradar-0.3.0/tests/test_bearing_display.py +15 -0
- termradar-0.3.0/tests/test_cli.py +61 -0
- termradar-0.3.0/tests/test_config.py +126 -0
- termradar-0.3.0/tests/test_distance.py +34 -0
- termradar-0.3.0/tests/test_engine.py +157 -0
- termradar-0.3.0/tests/test_formatting.py +82 -0
- termradar-0.3.0/tests/test_geocoding.py +116 -0
- termradar-0.3.0/tests/test_location_display.py +19 -0
- termradar-0.3.0/tests/test_models.py +37 -0
- termradar-0.3.0/tests/test_radar_canvas.py +134 -0
- termradar-0.3.0/tests/test_radar_coords.py +65 -0
- termradar-0.3.0/tests/test_rate_limit.py +18 -0
- termradar-0.3.0/tests/test_renderer.py +39 -0
- termradar-0.3.0/tests/test_routes.py +155 -0
- termradar-0.3.0/tests/test_session.py +112 -0
- termradar-0.3.0/tests/test_terminal_ui.py +155 -0
- termradar-0.3.0/tests/test_time_display.py +22 -0
- termradar-0.3.0/tests/test_timezone.py +21 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Byte-compiled / cache
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
|
|
7
|
+
# Virtual environments
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
env/
|
|
11
|
+
|
|
12
|
+
# Distribution / packaging
|
|
13
|
+
dist/
|
|
14
|
+
build/
|
|
15
|
+
*.egg-info/
|
|
16
|
+
.eggs/
|
|
17
|
+
|
|
18
|
+
# Testing
|
|
19
|
+
.pytest_cache/
|
|
20
|
+
.coverage
|
|
21
|
+
htmlcov/
|
|
22
|
+
|
|
23
|
+
# Tooling
|
|
24
|
+
.ruff_cache/
|
|
25
|
+
.mypy_cache/
|
|
26
|
+
|
|
27
|
+
# IDE
|
|
28
|
+
.idea/
|
|
29
|
+
.vscode/
|
|
30
|
+
*.swp
|
|
31
|
+
*.swo
|
|
32
|
+
|
|
33
|
+
# User configuration (never commit)
|
|
34
|
+
config.toml
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.3.0] - 2026-07-05
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- adsb.lol v2 as default live aircraft provider (`--aircraft-provider opensky` for OpenSky)
|
|
15
|
+
- ADSBDB enrichment for routes and airlines (replaces adsb.lol routeset in CLI)
|
|
16
|
+
- ICAO callsign prefix airline inference when enrichment has no airline
|
|
17
|
+
- Top-five nearby aircraft list with numbered radar markers (`1`–`5`)
|
|
18
|
+
- Rate limits: 5 s min / 5 s default refresh, 30 ADSBDB req/min, enrichment TTL cache
|
|
19
|
+
- Nominatim 1 req/s throttle; legacy `refresh_seconds < 5` auto-upgraded on load
|
|
20
|
+
- Local time display via `timezonefinder` and optional `timezone` in config
|
|
21
|
+
- README demo GIF and VHS tape (`docs/assets/demo-quick.*`)
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Right panel: **CLOSEST** detail + **NEARBY** compact list (title: NEARBY AIRCRAFT)
|
|
26
|
+
- Radar marker collision handling (offsets when on ring dots or overlapping)
|
|
27
|
+
- Airline display shortens trailing ` Airlines` / ` Air Lines`
|
|
28
|
+
- Documentation overhaul for providers, internal limits, and usage
|
|
29
|
+
- README quick start includes `pip install termradar`
|
|
30
|
+
- Provider User-Agent strings track package `__version__`
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- OpenSky HTTP 429 at aggressive refresh (adsb.lol default + minimum 5 s refresh)
|
|
35
|
+
- ADSBDB HTTP 404 logged as debug, not terminal warning
|
|
36
|
+
- ADSBDB route lookup falls back to callsign endpoint when aircraft hex lookup misses
|
|
37
|
+
- Aircraft markers skipped on ring dots
|
|
38
|
+
|
|
39
|
+
### Dependencies
|
|
40
|
+
|
|
41
|
+
- Added `timezonefinder` for coordinate → timezone lookup
|
|
42
|
+
|
|
43
|
+
## [0.2.0] - 2026-07-05
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- Live terminal UI with Rich panels, radar visualization, and nearest-aircraft panel
|
|
48
|
+
- `RadarSession` live refresh loop with configurable interval
|
|
49
|
+
- CLI overrides: `--location`, `--radius` / `--radius-km`, `--refresh` (current run only)
|
|
50
|
+
- Testable `radar_to_grid()` coordinate mapping and ASCII radar canvas
|
|
51
|
+
- Graceful handling of missing aircraft metadata in the UI
|
|
52
|
+
- Stale snapshot display when aircraft provider temporarily fails
|
|
53
|
+
- PyPI-ready project metadata and local wheel build validation
|
|
54
|
+
|
|
55
|
+
### Changed
|
|
56
|
+
|
|
57
|
+
- `termradar` runs a live refresh loop instead of a single scan
|
|
58
|
+
- Route provider accepts HTTP 201 responses from adsb.lol
|
|
59
|
+
- Improved first-run onboarding with refresh interval prompt
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- Empty adsb.lol route responses (HTTP 201, no body) no longer log false "malformed" warnings
|
|
64
|
+
- Terminal display clears screen before Live render to avoid duplicate headers
|
|
65
|
+
|
|
66
|
+
### Dependencies
|
|
67
|
+
|
|
68
|
+
- Added `rich` for terminal layout and live display
|
|
69
|
+
|
|
70
|
+
## [0.1.0] - 2026-07-05
|
|
71
|
+
|
|
72
|
+
### Added
|
|
73
|
+
|
|
74
|
+
- Core radar engine, providers, config storage, CLI, and tests
|
|
75
|
+
|
|
76
|
+
[Unreleased]: https://github.com/rusty3699/termradar/compare/v0.3.0...HEAD
|
|
77
|
+
[0.3.0]: https://github.com/rusty3699/termradar/compare/v0.2.0...v0.3.0
|
|
78
|
+
[0.2.0]: https://github.com/rusty3699/termradar/compare/v0.1.0...v0.2.0
|
|
79
|
+
[0.1.0]: https://github.com/rusty3699/termradar/releases/tag/v0.1.0
|
termradar-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TermRadar Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
termradar-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: termradar
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: See what's flying above you - live aircraft radar for your terminal
|
|
5
|
+
Project-URL: Homepage, https://github.com/rusty3699/termradar
|
|
6
|
+
Project-URL: Repository, https://github.com/rusty3699/termradar
|
|
7
|
+
Project-URL: Documentation, https://github.com/rusty3699/termradar/tree/main/docs
|
|
8
|
+
Project-URL: Issues, https://github.com/rusty3699/termradar/issues
|
|
9
|
+
Author: Anish Tipnis
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ads-b,aircraft,aviation,cli,flight-tracking,radar,terminal
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Requires-Dist: httpx>=0.27
|
|
24
|
+
Requires-Dist: platformdirs>=4.0
|
|
25
|
+
Requires-Dist: rich>=13.7
|
|
26
|
+
Requires-Dist: timezonefinder>=6.5
|
|
27
|
+
Requires-Dist: tomli-w>=1.0
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: build>=1.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.8; extra == 'dev'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# TermRadar
|
|
36
|
+
|
|
37
|
+
**See what's flying above you - without leaving your terminal.**
|
|
38
|
+
|
|
39
|
+

|
|
40
|
+
|
|
41
|
+
TermRadar is a lightweight live aircraft radar for developers, programmers, and aviation enthusiasts.
|
|
42
|
+
|
|
43
|
+
You're coding, you hear an aircraft overhead, or spot something from the window. Instead of opening a browser or reaching for a flight-tracking app, open a terminal and run:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
termradar
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
You get a live radar centered on your location: nearby callsigns, distance, bearing, speed, altitude, and route info when available. Use it for the quick answer, then jump to another tracker when you want deeper details.
|
|
50
|
+
|
|
51
|
+
> **One radar engine. Multiple displays.**
|
|
52
|
+
|
|
53
|
+
The core is display-agnostic. Today: a polished terminal UI. Planned: Raspberry Pi fullscreen and small displays.
|
|
54
|
+
|
|
55
|
+
## Quick start
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install termradar
|
|
59
|
+
termradar
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
From source:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
git clone https://github.com/rusty3699/termradar.git
|
|
66
|
+
cd termradar
|
|
67
|
+
python3 -m venv .venv
|
|
68
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
69
|
+
pip install -e .
|
|
70
|
+
termradar
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
First run: enter a location, pick a geocoding result, set radius and refresh. Later runs reuse saved settings. Press **Ctrl+C** to exit.
|
|
74
|
+
|
|
75
|
+
Config: `~/.config/termradar/config.toml` on Linux (platformdirs on macOS and Windows — see [ARCHITECTURE.md](docs/ARCHITECTURE.md)).
|
|
76
|
+
|
|
77
|
+
## What you get
|
|
78
|
+
|
|
79
|
+
| Available now | Planned |
|
|
80
|
+
|---------------|---------|
|
|
81
|
+
| Live terminal radar (default 5 s refresh) | Raspberry Pi fullscreen display |
|
|
82
|
+
| Numbered radar markers + top-five nearby list | OLED / e-paper displays |
|
|
83
|
+
| Closest-aircraft detail panel | Local ADS-B receivers |
|
|
84
|
+
| adsb.lol live aircraft (default) | Alerts and notifications |
|
|
85
|
+
| ADSBDB route/airline enrichment | Web UI |
|
|
86
|
+
| Nominatim geocoding, local timezone | |
|
|
87
|
+
| OpenSky via `--aircraft-provider opensky` | |
|
|
88
|
+
|
|
89
|
+
**Requirements:** Python 3.11+, network access. Works on Linux, macOS, Windows, and Raspberry Pi.
|
|
90
|
+
|
|
91
|
+
## Usage
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
termradar --location "Andheri, Mumbai" # temporary location (this run only)
|
|
95
|
+
termradar --radius 25 # search radius in km
|
|
96
|
+
termradar --refresh 10 # refresh interval (min 5 s)
|
|
97
|
+
termradar --aircraft-provider opensky # OpenSky instead of adsb.lol
|
|
98
|
+
termradar --enrichment-limit 10 # max aircraft to enrich per scan
|
|
99
|
+
termradar --reset-location # re-run setup
|
|
100
|
+
termradar --version
|
|
101
|
+
termradar --help
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
| Setting | Default | Allowed |
|
|
105
|
+
|---------|---------|---------|
|
|
106
|
+
| Refresh | 5 s | 5-300 s |
|
|
107
|
+
| Radius | 15 km | 1-250 km |
|
|
108
|
+
| Aircraft source | adsb.lol | `adsblol` or `opensky` |
|
|
109
|
+
| Enrichment | 10 nearest | `--enrichment-limit` |
|
|
110
|
+
|
|
111
|
+
Provider details and internal limits: [docs/DATA_PROVIDERS.md](docs/DATA_PROVIDERS.md)
|
|
112
|
+
|
|
113
|
+
## How it works
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
each refresh (every 5 s by default):
|
|
117
|
+
1. Fetch aircraft near you → adsb.lol
|
|
118
|
+
2. Distance and bearing from you
|
|
119
|
+
3. Enrich nearest (cache miss only) → ADSBDB
|
|
120
|
+
4. Draw radar + aircraft panels
|
|
121
|
+
|
|
122
|
+
setup only (not each refresh):
|
|
123
|
+
Geocoding → Nominatim
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Data sources:** [adsb.lol](https://adsb.lol) (aircraft), [ADSBDB](https://adsbdb.com) (routes/airlines), [Nominatim](https://www.openstreetmap.org) (geocoding)
|
|
127
|
+
|
|
128
|
+
## Documentation
|
|
129
|
+
|
|
130
|
+
| Doc | What it covers |
|
|
131
|
+
|-----|----------------|
|
|
132
|
+
| [CHANGELOG.md](CHANGELOG.md) | Release history |
|
|
133
|
+
| [ARCHITECTURE.md](docs/ARCHITECTURE.md) | Design, UI layout, code boundaries |
|
|
134
|
+
| [DATA_PROVIDERS.md](docs/DATA_PROVIDERS.md) | APIs, internal limits, caching |
|
|
135
|
+
| [ROADMAP.md](docs/ROADMAP.md) | What's next |
|
|
136
|
+
| [DEVELOPMENT.md](docs/DEVELOPMENT.md) | Tests, lint, packaging |
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
MIT - see [LICENSE](LICENSE).
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
Made with <3 Anish
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# TermRadar
|
|
2
|
+
|
|
3
|
+
**See what's flying above you - without leaving your terminal.**
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
TermRadar is a lightweight live aircraft radar for developers, programmers, and aviation enthusiasts.
|
|
8
|
+
|
|
9
|
+
You're coding, you hear an aircraft overhead, or spot something from the window. Instead of opening a browser or reaching for a flight-tracking app, open a terminal and run:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
termradar
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
You get a live radar centered on your location: nearby callsigns, distance, bearing, speed, altitude, and route info when available. Use it for the quick answer, then jump to another tracker when you want deeper details.
|
|
16
|
+
|
|
17
|
+
> **One radar engine. Multiple displays.**
|
|
18
|
+
|
|
19
|
+
The core is display-agnostic. Today: a polished terminal UI. Planned: Raspberry Pi fullscreen and small displays.
|
|
20
|
+
|
|
21
|
+
## Quick start
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install termradar
|
|
25
|
+
termradar
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
From source:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/rusty3699/termradar.git
|
|
32
|
+
cd termradar
|
|
33
|
+
python3 -m venv .venv
|
|
34
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
35
|
+
pip install -e .
|
|
36
|
+
termradar
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
First run: enter a location, pick a geocoding result, set radius and refresh. Later runs reuse saved settings. Press **Ctrl+C** to exit.
|
|
40
|
+
|
|
41
|
+
Config: `~/.config/termradar/config.toml` on Linux (platformdirs on macOS and Windows — see [ARCHITECTURE.md](docs/ARCHITECTURE.md)).
|
|
42
|
+
|
|
43
|
+
## What you get
|
|
44
|
+
|
|
45
|
+
| Available now | Planned |
|
|
46
|
+
|---------------|---------|
|
|
47
|
+
| Live terminal radar (default 5 s refresh) | Raspberry Pi fullscreen display |
|
|
48
|
+
| Numbered radar markers + top-five nearby list | OLED / e-paper displays |
|
|
49
|
+
| Closest-aircraft detail panel | Local ADS-B receivers |
|
|
50
|
+
| adsb.lol live aircraft (default) | Alerts and notifications |
|
|
51
|
+
| ADSBDB route/airline enrichment | Web UI |
|
|
52
|
+
| Nominatim geocoding, local timezone | |
|
|
53
|
+
| OpenSky via `--aircraft-provider opensky` | |
|
|
54
|
+
|
|
55
|
+
**Requirements:** Python 3.11+, network access. Works on Linux, macOS, Windows, and Raspberry Pi.
|
|
56
|
+
|
|
57
|
+
## Usage
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
termradar --location "Andheri, Mumbai" # temporary location (this run only)
|
|
61
|
+
termradar --radius 25 # search radius in km
|
|
62
|
+
termradar --refresh 10 # refresh interval (min 5 s)
|
|
63
|
+
termradar --aircraft-provider opensky # OpenSky instead of adsb.lol
|
|
64
|
+
termradar --enrichment-limit 10 # max aircraft to enrich per scan
|
|
65
|
+
termradar --reset-location # re-run setup
|
|
66
|
+
termradar --version
|
|
67
|
+
termradar --help
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
| Setting | Default | Allowed |
|
|
71
|
+
|---------|---------|---------|
|
|
72
|
+
| Refresh | 5 s | 5-300 s |
|
|
73
|
+
| Radius | 15 km | 1-250 km |
|
|
74
|
+
| Aircraft source | adsb.lol | `adsblol` or `opensky` |
|
|
75
|
+
| Enrichment | 10 nearest | `--enrichment-limit` |
|
|
76
|
+
|
|
77
|
+
Provider details and internal limits: [docs/DATA_PROVIDERS.md](docs/DATA_PROVIDERS.md)
|
|
78
|
+
|
|
79
|
+
## How it works
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
each refresh (every 5 s by default):
|
|
83
|
+
1. Fetch aircraft near you → adsb.lol
|
|
84
|
+
2. Distance and bearing from you
|
|
85
|
+
3. Enrich nearest (cache miss only) → ADSBDB
|
|
86
|
+
4. Draw radar + aircraft panels
|
|
87
|
+
|
|
88
|
+
setup only (not each refresh):
|
|
89
|
+
Geocoding → Nominatim
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Data sources:** [adsb.lol](https://adsb.lol) (aircraft), [ADSBDB](https://adsbdb.com) (routes/airlines), [Nominatim](https://www.openstreetmap.org) (geocoding)
|
|
93
|
+
|
|
94
|
+
## Documentation
|
|
95
|
+
|
|
96
|
+
| Doc | What it covers |
|
|
97
|
+
|-----|----------------|
|
|
98
|
+
| [CHANGELOG.md](CHANGELOG.md) | Release history |
|
|
99
|
+
| [ARCHITECTURE.md](docs/ARCHITECTURE.md) | Design, UI layout, code boundaries |
|
|
100
|
+
| [DATA_PROVIDERS.md](docs/DATA_PROVIDERS.md) | APIs, internal limits, caching |
|
|
101
|
+
| [ROADMAP.md](docs/ROADMAP.md) | What's next |
|
|
102
|
+
| [DEVELOPMENT.md](docs/DEVELOPMENT.md) | Tests, lint, packaging |
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
MIT - see [LICENSE](LICENSE).
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
Made with <3 Anish
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
> **One radar engine. Multiple displays.**
|
|
4
|
+
|
|
5
|
+
The core produces a `RadarSnapshot` on each scan. Renderers draw it; they never fetch data or call external APIs.
|
|
6
|
+
|
|
7
|
+
## Data flow
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
GeocodingProvider (setup / location override only)
|
|
11
|
+
↓
|
|
12
|
+
Location (+ timezone)
|
|
13
|
+
↓
|
|
14
|
+
AircraftProvider (every scan - default: adsb.lol)
|
|
15
|
+
↓
|
|
16
|
+
RadarEngine ◄──── CachedRouteProvider ──► AdsbDbRouteProvider
|
|
17
|
+
↓
|
|
18
|
+
RadarSnapshot
|
|
19
|
+
↓
|
|
20
|
+
RadarSession → TerminalView → TerminalRenderer
|
|
21
|
+
↓
|
|
22
|
+
Terminal output (Rich live UI)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
A future `FullscreenRenderer` (Phase 3, Raspberry Pi) will consume the same `RadarSnapshot`.
|
|
26
|
+
|
|
27
|
+
## Scan pipeline
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
RadarEngine.scan()
|
|
31
|
+
→ fetch aircraft (AdsblolAircraftProvider by default)
|
|
32
|
+
→ distance_km() + bearing_deg() from radar center
|
|
33
|
+
→ filter by radius, sort nearest-first
|
|
34
|
+
→ enrich nearest N aircraft (ADSBDB with callsign fallback, cached, rate-limited)
|
|
35
|
+
→ infer airline from ICAO callsign prefix when still unknown
|
|
36
|
+
→ RadarSnapshot
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Geocoding and timezone resolution run only during onboarding, `--reset-location`, or `--location` - **not** on refresh.
|
|
40
|
+
|
|
41
|
+
## Live display loop
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
RadarSession
|
|
45
|
+
→ engine.scan()
|
|
46
|
+
→ build TerminalView (location, snapshot, errors, terminal size)
|
|
47
|
+
→ TerminalRenderer.render()
|
|
48
|
+
→ sleep(refresh_seconds) # default 5 s, minimum 5 s
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`RadarSession` owns the loop and keeps the last good snapshot when a scan fails (stale mode). `TerminalRenderer` is stateless per frame.
|
|
52
|
+
|
|
53
|
+
## Terminal UI layout
|
|
54
|
+
|
|
55
|
+
Wide terminals (≥ 72 columns): radar panel left, aircraft panel right.
|
|
56
|
+
|
|
57
|
+
**Radar panel**
|
|
58
|
+
|
|
59
|
+
| Symbol | Meaning |
|
|
60
|
+
|--------|---------|
|
|
61
|
+
| `+` | Your location (radar center) |
|
|
62
|
+
| Outer dotted ring | Search radius |
|
|
63
|
+
| Inner dotted ring | Half of search radius |
|
|
64
|
+
| `1`–`5` | Top five nearest aircraft (matches nearby list) |
|
|
65
|
+
| `✈` | Other aircraft in range |
|
|
66
|
+
| `N` `E` `S` `W` | Compass |
|
|
67
|
+
|
|
68
|
+
Markers use collision offsets when the ideal grid cell is occupied (ring dot, center, or another marker).
|
|
69
|
+
|
|
70
|
+
**Nearby aircraft panel**
|
|
71
|
+
|
|
72
|
+
- **CLOSEST** - full detail for nearest aircraft (callsign, airline, route, distance, bearing, speed, altitude)
|
|
73
|
+
- **NEARBY** - compact top-five list: rank, callsign, distance, compass direction
|
|
74
|
+
|
|
75
|
+
Narrow terminals fall back to a compact aircraft table.
|
|
76
|
+
|
|
77
|
+
## Package layout
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
src/termradar/
|
|
81
|
+
├── cli.py # Entry point, onboarding, provider wiring
|
|
82
|
+
├── session.py # Live refresh loop
|
|
83
|
+
├── core/
|
|
84
|
+
│ ├── engine.py # Scan orchestration
|
|
85
|
+
│ ├── models.py # Location, Aircraft, RadarSnapshot, …
|
|
86
|
+
│ ├── limits.py # Rate-limit constants
|
|
87
|
+
│ ├── rate_limit.py # Rolling minute limiter
|
|
88
|
+
│ ├── airline.py # ICAO prefix → airline inference
|
|
89
|
+
│ ├── distance.py / bearing.py
|
|
90
|
+
│ ├── location.py / timezone.py
|
|
91
|
+
│ └── …
|
|
92
|
+
├── providers/
|
|
93
|
+
│ ├── geocoding.py # Nominatim
|
|
94
|
+
│ ├── aircraft.py # adsb.lol + OpenSky
|
|
95
|
+
│ ├── adsbdb.py # ADSBDB enrichment
|
|
96
|
+
│ └── routes.py # CachedRouteProvider, adsb.lol routeset
|
|
97
|
+
├── config/storage.py # TOML load/save, validation
|
|
98
|
+
└── renderers/
|
|
99
|
+
├── formatting.py # Display strings
|
|
100
|
+
├── bearing_display.py # Compass labels
|
|
101
|
+
├── location_display.py # Short location header
|
|
102
|
+
├── radar_coords.py # Polar → grid
|
|
103
|
+
├── radar_canvas.py # ASCII radar + markers
|
|
104
|
+
├── terminal_ui.py # Rich layout
|
|
105
|
+
├── terminal_view.py # Per-frame view model
|
|
106
|
+
└── time_display.py # Local time in location timezone
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Boundaries
|
|
110
|
+
|
|
111
|
+
| Layer | Does | Does not |
|
|
112
|
+
|-------|------|----------|
|
|
113
|
+
| Providers | HTTP, parsing, caching, rate limiting | Display, geometry |
|
|
114
|
+
| `RadarEngine` | Fetch, filter, sort, enrich | Terminal drawing |
|
|
115
|
+
| `CachedRouteProvider` | TTL cache + 30/min cap | Aircraft positions |
|
|
116
|
+
| `TerminalRenderer` | Layout, radar, formatting | API calls |
|
|
117
|
+
| `radar_to_grid()` | Bearing/distance → grid cell | Fetch or enrich |
|
|
118
|
+
|
|
119
|
+
## Error handling
|
|
120
|
+
|
|
121
|
+
| Failure | Behaviour |
|
|
122
|
+
|---------|-----------|
|
|
123
|
+
| Aircraft provider down | Error state; last snapshot shown as stale if available |
|
|
124
|
+
| ADSBDB miss / 404 | Aircraft shown; airline may come from callsign prefix |
|
|
125
|
+
| Enrichment rate limit | Skip remaining lookups this scan; retry later |
|
|
126
|
+
| Missing altitude / route | Graceful fallbacks (`-`, `Unknown airline`, `Route unavailable`) |
|
|
127
|
+
| Ctrl+C | Clean exit |
|
|
128
|
+
|
|
129
|
+
## Configuration
|
|
130
|
+
|
|
131
|
+
Stored at `~/.config/termradar/config.toml` (platformdirs).
|
|
132
|
+
|
|
133
|
+
| Key | Default | Notes |
|
|
134
|
+
|-----|---------|-------|
|
|
135
|
+
| `location.*` | - | Set during onboarding |
|
|
136
|
+
| `radar.radius_km` | 15 | 1–250 km |
|
|
137
|
+
| `radar.refresh_seconds` | 5 | 5–300; values < 5 upgraded on load |
|
|
138
|
+
|
|
139
|
+
CLI overrides (`--location`, `--radius`, `--refresh`, `--aircraft-provider`, `--enrichment-limit`) apply to the current run only unless `--reset-location` re-saves config.
|
|
140
|
+
|
|
141
|
+
## Internal limits and caching
|
|
142
|
+
|
|
143
|
+
See [DATA_PROVIDERS.md](DATA_PROVIDERS.md) for full detail. Summary:
|
|
144
|
+
|
|
145
|
+
- **Refresh:** 5 s default and minimum → one adsb.lol request per cycle
|
|
146
|
+
- **Enrichment:** 30 ADSBDB requests/minute max, 10 nearest aircraft per scan, 12 h / 30 min cache
|
|
147
|
+
- **Geocoding:** 1 Nominatim request/second, setup only
|