v0.11.0: new celestrak_tle adapter + CENTRAL_SAT satellite-tracking stream (#100)

This commit is contained in:
malice 2026-06-09 00:54:19 -06:00 committed by GitHub
commit 621148ac46
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 1067 additions and 4 deletions

View file

@ -135,6 +135,7 @@ Central's archive.
| `CENTRAL_TRAFFIC_FLOW` | `central.traffic_flow.>` | 7 | 1 GiB | ✓ | ✓ |
| `CENTRAL_TRAFFIC_CAMERAS` | `central.traffic_cameras.>` | 7 | 1 GiB | ✓ | ✓ |
| `CENTRAL_AVY` | `central.avy.>` | 7 | 1 GiB | ✓ | ✓ |
| `CENTRAL_SAT` | `central.sat.>` | 7 | 1 GiB | ✓ | ✓ |
| `CENTRAL_META` | `central.meta.>` | 1 | 1 GiB | — | ✓ |
Retention and storage caps are migration-seeded defaults visible in `config.streams`;
@ -1831,6 +1832,44 @@ at parameter `00060`, gage height (ft) at `00065`, water temperature (°C) at
\
---
### celestrak_tle — CelesTrak satellite TLEs (v0.11.0)
- **Source:** `https://celestrak.org/NORAD/elements/gp.php?GROUP=<group>&FORMAT=TLE`
per configured group (defaults: `stations`, `weather`, `amateur`), plus
per-CATNR endpoint for operator-pinned `extra_norad_ids`. 4h cadence
(CelesTrak refreshes ~8h).
- **Stream:** `CENTRAL_SAT` (`central.sat.>`)
- **Subject:** `central.sat.tle.<norad_id>` — one subject per satellite,
globally. No state coord (orbital state is universal). Consumers
compute passes locally with their own observer geolocation
(e.g. satellite.js + `navigator.geolocation`).
- **Dedup key shape:** `<norad_id>:<epoch_iso>` — re-fetching the same TLE
is swallowed; CelesTrak issues a new epoch every ~8h and that produces
a fresh dedup key, naturally triggering a republish.
- **Severity:** `1` (informational; no alerting).
- **Geo:** intentionally empty (`Geo()`). TLEs are global orbital state,
not a surface point — consumers propagate the orbit at observe time.
- **Event.data fields:**
| Field | Type | Notes |
|---|---|---|
| `norad_id` | int | Satellite catalog number (e.g. 25544 for ISS) |
| `satellite_name` | string | Upstream display name |
| `tle_line1`, `tle_line2` | string | Raw 69-char TLE strings; pass to satellite-js verbatim |
| `epoch` | string | ISO datetime decoded from Line 1 cols 19-32 (YYDDD.DDDDDDDD; Y2K rule 00-56 = 2000s, 57-99 = 1957-1999) |
| `classification` | string | `U` / `C` / `S` (almost always U) |
| `intl_designator` | string | International designator e.g. `1998-067A` (ISS) — but in the packed TLE form (`98067A`) |
| `source_url` | string | The exact URL the TLE was fetched from |
- **`_enriched.orbit`:** parsed straight from Line 2 columns when valid:
`inclination_deg`, `mean_motion_rev_per_day`, `eccentricity` (the
implicit-leading-0. is reconstructed). Absent if Line 2 fails to parse.
- **Group/extras dedup:** if a satellite appears in two configured groups
or in both a group and `extra_norad_ids`, it's fetched **once** (first
occurrence wins).
\
---
## 7. Fall-off / removal semantics
Central adapters fall into three buckets for handling upstream events that

View file

@ -362,7 +362,7 @@ central.<domain>.<subtype>[.<dimensions>...]
```
- `<domain>` is one of `wx`, `fire`, `quake`, `space`, `disaster`, `hydro`,
`traffic`, `traffic_flow`, `traffic_cameras`, `avy`, `meta` (the current set — see [§8](#8-the-streamentry-registry) for adding
`traffic`, `traffic_flow`, `traffic_cameras`, `avy`, `sat`, `meta` (the current set — see [§8](#8-the-streamentry-registry) for adding
one). Operators MUST be able to subscribe to all of one domain with
`central.<domain>.>`.
- `<subtype>` is adapter-driven and identifies the event category within the
@ -554,6 +554,7 @@ STREAMS: list[StreamEntry] = [
StreamEntry("CENTRAL_TRAFFIC_FLOW", "central.traffic_flow.>"),
StreamEntry("CENTRAL_TRAFFIC_CAMERAS", "central.traffic_cameras.>"),
StreamEntry("CENTRAL_AVY", "central.avy.>"),
StreamEntry("CENTRAL_SAT", "central.sat.>"),
StreamEntry("CENTRAL_META", "central.meta.>", event_bearing=False),
]
```