Fix aircraft markers not updating positions in real-time
Root cause: The merger was blocking position updates from the same source after the first position was established, designed for multi-source scenarios but preventing single-source position updates. Changes: - Refactor JavaScript into modular architecture (WebSocketManager, AircraftManager, MapManager, UIManager) - Add CPR coordinate validation to prevent invalid latitude/longitude values - Fix merger to allow position updates from same source for moving aircraft - Add comprehensive coordinate bounds checking in CPR decoder - Update HTML to use new modular JavaScript with cache busting - Add WebSocket debug logging to track data flow Technical details: - CPR decoder now validates coordinates within ±90° latitude, ±180° longitude - Merger allows updates when currentBest == sourceID (same source continuous updates) - JavaScript modules provide better separation of concerns and debugging - WebSocket properly transmits updated aircraft coordinates to frontend 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
ddffe1428d
commit
1de3e092ae
13 changed files with 2222 additions and 33 deletions
|
|
@ -130,6 +130,11 @@ class SkyView {
|
|||
document.getElementById('toggle-trails').addEventListener('click', () => this.toggleTrails());
|
||||
document.getElementById('toggle-range').addEventListener('click', () => this.toggleRangeCircles());
|
||||
document.getElementById('toggle-sources').addEventListener('click', () => this.toggleSources());
|
||||
|
||||
// If we already have aircraft data waiting, update markers now that map is ready
|
||||
if (this.aircraftData.size > 0) {
|
||||
this.updateMapMarkers();
|
||||
}
|
||||
}
|
||||
|
||||
async initializeCoverageMap() {
|
||||
|
|
@ -251,6 +256,11 @@ class SkyView {
|
|||
|
||||
// Map Updates
|
||||
updateMapMarkers() {
|
||||
// Check if map is initialized
|
||||
if (!this.map) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear stale aircraft markers
|
||||
const currentICAOs = new Set(this.aircraftData.keys());
|
||||
for (const [icao, marker] of this.aircraftMarkers) {
|
||||
|
|
@ -261,9 +271,10 @@ class SkyView {
|
|||
}
|
||||
}
|
||||
|
||||
// Update aircraft markers
|
||||
// Update aircraft markers - only for aircraft with valid positions
|
||||
// Note: Aircraft without positions are still shown in the table view
|
||||
for (const [icao, aircraft] of this.aircraftData) {
|
||||
if (aircraft.Latitude && aircraft.Longitude) {
|
||||
if (aircraft.Latitude && aircraft.Longitude && aircraft.Latitude !== 0 && aircraft.Longitude !== 0) {
|
||||
this.updateAircraftMarker(icao, aircraft);
|
||||
}
|
||||
}
|
||||
|
|
@ -486,10 +497,10 @@ class SkyView {
|
|||
const distance = this.calculateDistance(aircraft);
|
||||
const distanceKm = distance ? (distance * 1.852).toFixed(1) : 'N/A';
|
||||
|
||||
const sources = aircraft.Sources ? Object.keys(aircraft.Sources).map(id => {
|
||||
const sources = aircraft.sources ? Object.keys(aircraft.sources).map(id => {
|
||||
const source = this.sourcesData.get(id);
|
||||
const srcData = aircraft.Sources[id];
|
||||
return `<span class="source-badge" title="Signal: ${srcData.SignalLevel?.toFixed(1)} dBFS">
|
||||
const srcData = aircraft.sources[id];
|
||||
return `<span class="source-badge" title="Signal: ${srcData.signal_level?.toFixed(1)} dBFS">
|
||||
${source?.name || id}
|
||||
</span>`;
|
||||
}).join('') : 'N/A';
|
||||
|
|
@ -567,7 +578,7 @@ class SkyView {
|
|||
|
||||
createSourcePopupContent(source) {
|
||||
const aircraftCount = Array.from(this.aircraftData.values())
|
||||
.filter(aircraft => aircraft.Sources && aircraft.Sources[source.id]).length;
|
||||
.filter(aircraft => aircraft.sources && aircraft.sources[source.id]).length;
|
||||
|
||||
return `
|
||||
<div class="source-popup">
|
||||
|
|
@ -599,6 +610,9 @@ class SkyView {
|
|||
|
||||
// Table Management
|
||||
updateAircraftTable() {
|
||||
// Note: This table shows ALL aircraft we're tracking, including those without
|
||||
// position data. Aircraft without positions will show "No position" in the
|
||||
// location column but still provide useful info like callsign, altitude, etc.
|
||||
const tbody = document.getElementById('aircraft-tbody');
|
||||
tbody.innerHTML = '';
|
||||
|
||||
|
|
@ -618,7 +632,7 @@ class SkyView {
|
|||
|
||||
if (sourceFilter) {
|
||||
filteredData = filteredData.filter(aircraft =>
|
||||
aircraft.Sources && aircraft.Sources[sourceFilter]
|
||||
aircraft.sources && aircraft.sources[sourceFilter]
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -642,8 +656,8 @@ class SkyView {
|
|||
const icao = aircraft.ICAO24 || 'N/A';
|
||||
const altitude = aircraft.Altitude || aircraft.BaroAltitude || 0;
|
||||
const distance = this.calculateDistance(aircraft);
|
||||
const sources = aircraft.Sources ? Object.keys(aircraft.Sources).length : 0;
|
||||
const bestSignal = this.getBestSignalFromSources(aircraft.Sources);
|
||||
const sources = aircraft.sources ? Object.keys(aircraft.sources).length : 0;
|
||||
const bestSignal = this.getBestSignalFromSources(aircraft.sources);
|
||||
|
||||
const row = document.createElement('tr');
|
||||
row.innerHTML = `
|
||||
|
|
@ -677,8 +691,8 @@ class SkyView {
|
|||
if (!sources) return null;
|
||||
let bestSignal = -999;
|
||||
for (const [id, data] of Object.entries(sources)) {
|
||||
if (data.SignalLevel > bestSignal) {
|
||||
bestSignal = data.SignalLevel;
|
||||
if (data.signal_level > bestSignal) {
|
||||
bestSignal = data.signal_level;
|
||||
}
|
||||
}
|
||||
return bestSignal === -999 ? null : bestSignal;
|
||||
|
|
@ -725,7 +739,7 @@ class SkyView {
|
|||
case 'squawk':
|
||||
return (a.Squawk || '').localeCompare(b.Squawk || '');
|
||||
case 'signal':
|
||||
return (this.getBestSignalFromSources(b.Sources) || -999) - (this.getBestSignalFromSources(a.Sources) || -999);
|
||||
return (this.getBestSignalFromSources(b.sources) || -999) - (this.getBestSignalFromSources(a.sources) || -999);
|
||||
case 'age':
|
||||
return (a.Age || 0) - (b.Age || 0);
|
||||
default:
|
||||
|
|
@ -1127,9 +1141,9 @@ class SkyView {
|
|||
|
||||
// Use closest source as reference point
|
||||
let minDistance = Infinity;
|
||||
for (const [id, srcData] of Object.entries(aircraft.Sources || {})) {
|
||||
if (srcData.Distance && srcData.Distance < minDistance) {
|
||||
minDistance = srcData.Distance;
|
||||
for (const [id, srcData] of Object.entries(aircraft.sources || {})) {
|
||||
if (srcData.distance && srcData.distance < minDistance) {
|
||||
minDistance = srcData.distance;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue