auto-sync: 2026-04-19 23:30:01
This commit is contained in:
@@ -416,6 +416,7 @@ def tracks():
|
||||
for r in rows:
|
||||
pts = r["points"] if isinstance(r["points"], list) else []
|
||||
coords = [[p["lon"], p["lat"]] for p in pts if p.get("lon") is not None]
|
||||
times = [p["ts"].isoformat() if hasattr(p.get("ts"), "isoformat") else str(p["ts"]) if p.get("ts") else None for p in pts if p.get("lon") is not None]
|
||||
if len(coords) < 2:
|
||||
continue
|
||||
features.append({
|
||||
@@ -427,6 +428,7 @@ def tracks():
|
||||
"icao24": r["icao24"],
|
||||
"callsign": r["callsign"] or r["icao24"],
|
||||
"point_count": len(coords),
|
||||
"times": times,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ function closePopup() {
|
||||
|
||||
async function refreshTracks() {
|
||||
try {
|
||||
const res = await fetch('/api/tracks?minutes=' + getMinutes());
|
||||
const res = await fetch('/api/tracks?minutes=' + getMinutes() + '&limit=200');
|
||||
if (!res.ok) return;
|
||||
const geojson = await res.json();
|
||||
let features = geojson.features || [];
|
||||
@@ -138,15 +138,32 @@ async function refreshTracks() {
|
||||
trackLayers = [];
|
||||
|
||||
for (const f of features) {
|
||||
const coords = f.geometry.coordinates.map(([lon, lat]) => [lat, lon]);
|
||||
const pts = f.geometry.coordinates; // [[lon, lat], ...]
|
||||
const times = (f.properties.times || []); // ISO strings, may be empty
|
||||
|
||||
// Split into segments where time gap > 5 min (300s)
|
||||
const segments = [];
|
||||
let seg = [];
|
||||
for (let i = 0; i < pts.length; i++) {
|
||||
if (i > 0 && times.length === pts.length) {
|
||||
const dt = (new Date(times[i]) - new Date(times[i-1])) / 1000;
|
||||
if (dt > 300) { segments.push(seg); seg = []; }
|
||||
}
|
||||
seg.push([pts[i][1], pts[i][0]]); // [lat, lon] for Leaflet
|
||||
}
|
||||
if (seg.length) segments.push(seg);
|
||||
|
||||
const callsign = f.properties.callsign || f.properties.icao24;
|
||||
const line = L.polyline(coords, {
|
||||
color: '#58a6ff',
|
||||
weight: 3,
|
||||
opacity: 0.7,
|
||||
}).addTo(map);
|
||||
line.bindPopup(callsign);
|
||||
trackLayers.push(line);
|
||||
for (const segment of segments) {
|
||||
if (segment.length < 2) continue;
|
||||
const line = L.polyline(segment, {
|
||||
color: '#58a6ff',
|
||||
weight: 3,
|
||||
opacity: 0.7,
|
||||
}).addTo(map);
|
||||
line.bindPopup(callsign);
|
||||
trackLayers.push(line);
|
||||
}
|
||||
}
|
||||
} catch (_) { /* silent — tracks are non-critical */ }
|
||||
}
|
||||
|
||||
@@ -286,6 +286,11 @@ def process_batch(conn, packets: list) -> int:
|
||||
aircraft_id = upsert_aircraft(conn, icao24, callsign, now)
|
||||
flight_id = get_or_create_flight(conn, aircraft_id, callsign, observed_at)
|
||||
|
||||
# sanity-check: skip obviously invalid coordinates
|
||||
if lat is not None and lon is not None and not (-90 <= lat <= 90 and -180 <= lon <= 180):
|
||||
log.warning("Invalid coords icao24=%s lat=%s lon=%s — skipping", icao24, lat, lon)
|
||||
lat, lon = None, None
|
||||
|
||||
if lat is not None and lon is not None:
|
||||
track_id = get_or_create_track(conn, flight_id)
|
||||
append_track_point(
|
||||
|
||||
Reference in New Issue
Block a user