From 304b13a9041f8489ee7ecedfe8df97b52c70e89d Mon Sep 17 00:00:00 2001 From: Ole-Morten Duesund Date: Sun, 24 Aug 2025 19:31:46 +0200 Subject: [PATCH] Improve transponder display and add combined signal quality indicator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Transponder Display Improvements:** - Simplified transponder capability labels to be more concise - "Level 2+ Transponder" → "Level 2+" - "Enhanced Transponder" → "Enhanced" - "Alert/Emergency Status" → "Alert/Emergency" - Removes redundant "Transponder" suffix for cleaner popup display **New Signal Quality Feature:** - Added SignalQuality field combining NACp, NACv, and SIL into human-readable assessment - Quality levels: "Excellent", "Good", "Fair", "Poor" based on aviation standards - Prioritizes surveillance integrity (SIL) then position accuracy (NACp) - Automatically calculated when operational status messages (TC 31) are received - Displayed in aircraft popup when available **Signal Quality Algorithm:** - **Excellent**: High integrity (SIL ≥ 2) with precise position (NACp ≥ 9) - **Good**: Good integrity with moderate accuracy OR very high accuracy - **Fair**: Some integrity with basic accuracy OR high accuracy without integrity - **Poor**: Low but usable quality indicators - **Empty**: No quality data available **Frontend Enhancements:** - Added "Signal Quality" row to aircraft popup - Only displays when quality data is available - Clean integration with existing popup layout - Shows alongside transponder information **Data Quality Context:** - NACp: Position accuracy (0-11, higher = more precise location) - NACv: Velocity accuracy (0-4, higher = more precise speed/heading) - SIL: Surveillance integrity (0-3, higher = more reliable data) This gives users a quick understanding of data reliability without needing to interpret technical NACp/NACv/SIL values directly. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- assets/static/js/modules/aircraft-manager.js | 4 ++ internal/merger/merger.go | 2 + internal/modes/decoder.go | 76 ++++++++++++++++++-- 3 files changed, 77 insertions(+), 5 deletions(-) diff --git a/assets/static/js/modules/aircraft-manager.js b/assets/static/js/modules/aircraft-manager.js index ac92646..1485d38 100644 --- a/assets/static/js/modules/aircraft-manager.js +++ b/assets/static/js/modules/aircraft-manager.js @@ -366,6 +366,10 @@ export class AircraftManager {
Transponder: ${aircraft.TransponderCapability}
` : ''} + ${aircraft.SignalQuality ? ` +
+ Signal Quality: ${aircraft.SignalQuality} +
` : ''}
diff --git a/internal/merger/merger.go b/internal/merger/merger.go index fdb0c52..90dce58 100644 --- a/internal/merger/merger.go +++ b/internal/merger/merger.go @@ -134,6 +134,7 @@ func (a *AircraftState) MarshalJSON() ([]byte, error) { SIL uint8 `json:"SIL"` TransponderCapability string `json:"TransponderCapability"` TransponderLevel uint8 `json:"TransponderLevel"` + SignalQuality string `json:"SignalQuality"` SelectedAltitude int `json:"SelectedAltitude"` SelectedHeading float64 `json:"SelectedHeading"` BaroSetting float64 `json:"BaroSetting"` @@ -180,6 +181,7 @@ func (a *AircraftState) MarshalJSON() ([]byte, error) { SIL: a.Aircraft.SIL, TransponderCapability: a.Aircraft.TransponderCapability, TransponderLevel: a.Aircraft.TransponderLevel, + SignalQuality: a.Aircraft.SignalQuality, SelectedAltitude: a.Aircraft.SelectedAltitude, SelectedHeading: a.Aircraft.SelectedHeading, BaroSetting: a.Aircraft.BaroSetting, diff --git a/internal/modes/decoder.go b/internal/modes/decoder.go index f2ab232..e586439 100644 --- a/internal/modes/decoder.go +++ b/internal/modes/decoder.go @@ -142,6 +142,9 @@ type Aircraft struct { TransponderCapability string // Transponder capability level (from DF11 messages) TransponderLevel uint8 // Transponder level (0-7 from capability field) + // Combined Data Quality Assessment + SignalQuality string // Combined assessment of position/velocity accuracy and integrity + // Autopilot/Flight Management SelectedAltitude int // MCP/FCU selected altitude in feet SelectedHeading float64 // MCP/FCU selected heading in degrees @@ -870,6 +873,9 @@ func (d *Decoder) decodeOperationalStatus(data []byte, aircraft *Aircraft) { aircraft.NACp = (data[7] >> 4) & 0x0F aircraft.NACv = data[7] & 0x0F aircraft.SIL = (data[8] >> 6) & 0x03 + + // Calculate combined signal quality from NACp, NACv, and SIL + d.calculateSignalQuality(aircraft) } // decodeSurfacePosition extracts position and movement data for aircraft on the ground. @@ -997,15 +1003,15 @@ func (d *Decoder) decodeAllCallReply(data []byte, aircraft *Aircraft) { aircraft.TransponderLevel = capability switch capability { case 0: - aircraft.TransponderCapability = "Level 1 Transponder" + aircraft.TransponderCapability = "Level 1" case 1: - aircraft.TransponderCapability = "Level 2 Transponder" + aircraft.TransponderCapability = "Level 2" case 2, 3: - aircraft.TransponderCapability = "Level 2+ Transponder" + aircraft.TransponderCapability = "Level 2+" case 4, 5, 6: - aircraft.TransponderCapability = "Enhanced Transponder" + aircraft.TransponderCapability = "Enhanced" case 7: - aircraft.TransponderCapability = "Alert/Emergency Status" + aircraft.TransponderCapability = "Alert/Emergency" } } @@ -1064,3 +1070,63 @@ func (d *Decoder) decodeCommD(data []byte, aircraft *Aircraft) { // // This could be extended based on specific requirements and available documentation } + +// calculateSignalQuality combines NACp, NACv, and SIL into an overall data quality assessment. +// +// This function provides a human-readable quality indicator that considers: +// - Position accuracy (NACp): How precise the aircraft's position data is +// - Velocity accuracy (NACv): How precise the speed/heading data is +// - Surveillance integrity (SIL): How reliable/trustworthy the data is +// +// The algorithm prioritizes integrity first (SIL), then position accuracy (NACp), +// then velocity accuracy (NACv) to provide a meaningful overall assessment. +// +// Quality levels: +// - "Excellent": High integrity with very precise position/velocity +// - "Good": Good integrity with reasonable precision +// - "Fair": Moderate quality suitable for tracking +// - "Poor": Low quality but still usable +// - "Unknown": No quality indicators available +// +// Parameters: +// - aircraft: Aircraft struct containing NACp, NACv, and SIL values +func (d *Decoder) calculateSignalQuality(aircraft *Aircraft) { + nacp := aircraft.NACp + nacv := aircraft.NACv + sil := aircraft.SIL + + // If no quality indicators are available + if nacp == 0 && nacv == 0 && sil == 0 { + aircraft.SignalQuality = "" + return + } + + // Excellent: High integrity (SIL >= 2) with high accuracy (NACp >= 9) + if sil >= 2 && nacp >= 9 { + aircraft.SignalQuality = "Excellent" + return + } + + // Good: Good integrity (SIL >= 2) with moderate accuracy (NACp >= 6) OR + // moderate integrity with very high accuracy + if (sil >= 2 && nacp >= 6) || (sil >= 1 && nacp >= 10) { + aircraft.SignalQuality = "Good" + return + } + + // Fair: Some integrity (SIL >= 1) with basic accuracy (NACp >= 3) OR + // high accuracy without integrity info + if (sil >= 1 && nacp >= 3) || nacp >= 8 { + aircraft.SignalQuality = "Fair" + return + } + + // Poor: Low values but still has some quality indicators + if sil > 0 || nacp > 0 || nacv > 0 { + aircraft.SignalQuality = "Poor" + return + } + + // Default fallback + aircraft.SignalQuality = "" +}