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 {
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 = ""
+}