diff --git a/assets/static/css/style.css b/assets/static/css/style.css
index b34a241..9a3400d 100644
--- a/assets/static/css/style.css
+++ b/assets/static/css/style.css
@@ -268,12 +268,14 @@ body {
border: 1px solid #ffffff;
}
-.legend-icon.commercial { background: #00ff88; }
-.legend-icon.cargo { background: #ff8c00; }
-.legend-icon.helicopter { background: #00d4ff; }
-.legend-icon.military { background: #ff4444; }
-.legend-icon.ga { background: #ffff00; }
-.legend-icon.ground { background: #888888; }
+.legend-icon.light { background: #00bfff; } /* Sky blue for light aircraft */
+.legend-icon.medium { background: #00ff88; } /* Green for medium aircraft */
+.legend-icon.large { background: #ff8c00; } /* Orange for large aircraft */
+.legend-icon.heavy { background: #ff0000; } /* Red for heavy aircraft */
+.legend-icon.helicopter { background: #ff00ff; } /* Magenta for helicopters */
+.legend-icon.military { background: #ff4444; } /* Red-orange for military */
+.legend-icon.ga { background: #ffff00; } /* Yellow for general aviation */
+.legend-icon.ground { background: #888888; } /* Gray for ground vehicles */
.table-controls {
display: flex;
diff --git a/assets/static/icons/cargo.svg b/assets/static/icons/cargo.svg
index b3605b1..6d30370 100644
--- a/assets/static/icons/cargo.svg
+++ b/assets/static/icons/cargo.svg
@@ -1,9 +1,28 @@
\ No newline at end of file
diff --git a/assets/static/icons/commercial.svg b/assets/static/icons/commercial.svg
index f1f1b28..f193d6a 100644
--- a/assets/static/icons/commercial.svg
+++ b/assets/static/icons/commercial.svg
@@ -1,7 +1,21 @@
\ No newline at end of file
diff --git a/assets/static/icons/ga.svg b/assets/static/icons/ga.svg
index cfba161..2be9e7a 100644
--- a/assets/static/icons/ga.svg
+++ b/assets/static/icons/ga.svg
@@ -1,7 +1,27 @@
\ No newline at end of file
diff --git a/assets/static/icons/ground.svg b/assets/static/icons/ground.svg
index ee5af8e..96c03a3 100644
--- a/assets/static/icons/ground.svg
+++ b/assets/static/icons/ground.svg
@@ -1,10 +1,24 @@
\ No newline at end of file
diff --git a/assets/static/icons/helicopter.svg b/assets/static/icons/helicopter.svg
index 5197bea..b1c90bc 100644
--- a/assets/static/icons/helicopter.svg
+++ b/assets/static/icons/helicopter.svg
@@ -1,12 +1,29 @@
\ No newline at end of file
diff --git a/assets/static/icons/military.svg b/assets/static/icons/military.svg
index c4e58a7..931c9c8 100644
--- a/assets/static/icons/military.svg
+++ b/assets/static/icons/military.svg
@@ -1,7 +1,27 @@
\ No newline at end of file
diff --git a/assets/static/index.html b/assets/static/index.html
index 0a00509..b9f43b0 100644
--- a/assets/static/index.html
+++ b/assets/static/index.html
@@ -107,19 +107,19 @@
ADS-B Categories
-
+
Light < 7000kg
-
+
Medium 7000-34000kg
-
+
Large 34000-136000kg
-
+
Heavy > 136000kg
diff --git a/assets/static/js/modules/aircraft-manager.js b/assets/static/js/modules/aircraft-manager.js
index 1485d38..347399b 100644
--- a/assets/static/js/modules/aircraft-manager.js
+++ b/assets/static/js/modules/aircraft-manager.js
@@ -215,7 +215,7 @@ export class AircraftManager {
createAircraftIcon(aircraft) {
const iconType = this.getAircraftIconType(aircraft);
- const color = this.getAircraftColor(iconType);
+ const color = this.getAircraftColor(iconType, aircraft);
const size = aircraft.OnGround ? 12 : 16;
const rotation = aircraft.Track || 0;
@@ -277,16 +277,38 @@ export class AircraftManager {
return 'commercial';
}
- getAircraftColor(type) {
- const colors = {
- commercial: '#00ff88',
- cargo: '#ff8c00',
- military: '#ff4444',
- ga: '#ffff00',
- ground: '#888888',
- helicopter: '#ff00ff' // Magenta for helicopters
- };
- return colors[type] || colors.commercial;
+ getAircraftColor(type, aircraft) {
+ // Special colors for specific types
+ if (type === 'military') return '#ff4444';
+ if (type === 'helicopter') return '#ff00ff';
+ if (type === 'ground') return '#888888';
+ if (type === 'ga') return '#ffff00';
+
+ // For commercial and cargo types, use weight-based colors
+ if (aircraft && aircraft.Category) {
+ const cat = aircraft.Category.toLowerCase();
+
+ // Check for specific weight ranges in the category string
+ // Light aircraft (< 7000kg) - Sky blue
+ if (cat.includes('light') || cat.includes('7000kg')) {
+ return '#00bfff';
+ }
+ // Medium aircraft (7000-34000kg) - Green
+ if (cat.includes('medium 7000')) {
+ return '#00ff88';
+ }
+ // Large aircraft (34000-136000kg) - Orange
+ if (cat.includes('medium 34000') || cat.includes('large')) {
+ return '#ff8c00';
+ }
+ // Heavy aircraft (> 136000kg) - Red
+ if (cat.includes('heavy') || cat.includes('136000kg') || cat.includes('super')) {
+ return '#ff0000';
+ }
+ }
+
+ // Default to green for unknown commercial aircraft
+ return '#00ff88';
}
diff --git a/internal/modes/decoder.go b/internal/modes/decoder.go
index 397a1f9..f4a1ed7 100644
--- a/internal/modes/decoder.go
+++ b/internal/modes/decoder.go
@@ -232,6 +232,11 @@ func (d *Decoder) Decode(data []byte) (*Aircraft, error) {
df := (data[0] >> 3) & 0x1F
icao := d.extractICAO(data, df)
+
+ // Debug: Log DF types to verify we're processing new formats
+ if df == 0 || df == 11 || df == 16 || df == 19 || df == 24 {
+ fmt.Printf("DEBUG: Processing new DF%d message for ICAO %06X\n", df, icao)
+ }
aircraft := &Aircraft{
ICAO24: icao,
diff --git a/internal/server/server.go b/internal/server/server.go
index 76e89a8..2197f85 100644
--- a/internal/server/server.go
+++ b/internal/server/server.go
@@ -190,6 +190,9 @@ func (s *Server) Stop() {
func (s *Server) setupRoutes() http.Handler {
router := mux.NewRouter()
+ // Health check endpoint for load balancers/monitoring
+ router.HandleFunc("/health", s.handleHealthCheck).Methods("GET")
+
// API routes
api := router.PathPrefix("/api").Subrouter()
api.HandleFunc("/aircraft", s.handleGetAircraft).Methods("GET")
@@ -240,6 +243,63 @@ func (s *Server) isAircraftUseful(aircraft *merger.AircraftState) bool {
return hasValidPosition || hasCallsign || hasAltitude || hasSquawk
}
+// handleHealthCheck serves the /health endpoint for monitoring and load balancers.
+// Returns a simple health status with basic service information.
+//
+// Response includes:
+// - status: "healthy" or "degraded"
+// - uptime: server uptime in seconds
+// - sources: number of active sources and their connection status
+// - aircraft: current aircraft count
+//
+// The endpoint returns:
+// - 200 OK when the service is healthy
+// - 503 Service Unavailable when the service is degraded (no active sources)
+func (s *Server) handleHealthCheck(w http.ResponseWriter, r *http.Request) {
+ sources := s.merger.GetSources()
+ stats := s.merger.GetStatistics()
+ aircraft := s.merger.GetAircraft()
+
+ // Check if we have any active sources
+ activeSources := 0
+ for _, source := range sources {
+ if source.Active {
+ activeSources++
+ }
+ }
+
+ // Determine health status
+ status := "healthy"
+ statusCode := http.StatusOK
+ if activeSources == 0 && len(sources) > 0 {
+ status = "degraded"
+ statusCode = http.StatusServiceUnavailable
+ }
+
+ response := map[string]interface{}{
+ "status": status,
+ "timestamp": time.Now().Unix(),
+ "sources": map[string]interface{}{
+ "total": len(sources),
+ "active": activeSources,
+ },
+ "aircraft": map[string]interface{}{
+ "count": len(aircraft),
+ },
+ }
+
+ // Add statistics if available
+ if stats != nil {
+ if totalMessages, ok := stats["total_messages"]; ok {
+ response["messages"] = totalMessages
+ }
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(statusCode)
+ json.NewEncoder(w).Encode(response)
+}
+
// handleGetAircraft serves the /api/aircraft endpoint.
// Returns all currently tracked aircraft with their latest state information.
//