Enhance aircraft details display to match dump1090 format
- Add country lookup from ICAO hex codes with flag display - Implement UTC clocks and last update time indicators - Enhance aircraft table with ICAO, squawk, and RSSI columns - Add color-coded RSSI signal strength indicators - Fix calculateDistance returning string instead of number - Accept all SBS-1 message types for complete data capture - Improve data merging to preserve country and registration 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
55710614da
commit
c8562a4f0d
5 changed files with 457 additions and 41 deletions
|
|
@ -136,6 +136,14 @@ func (c *Dump1090Client) updateExistingAircraft(existing, update *parser.Aircraf
|
|||
existing.Squawk = update.Squawk
|
||||
}
|
||||
existing.OnGround = update.OnGround
|
||||
|
||||
// Preserve country and registration
|
||||
if update.Country != "" && update.Country != "Unknown" {
|
||||
existing.Country = update.Country
|
||||
}
|
||||
if update.Registration != "" {
|
||||
existing.Registration = update.Registration
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Dump1090Client) shouldAddTrackPoint(existing, update *parser.Aircraft) bool {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ type Aircraft struct {
|
|||
LastSeen time.Time `json:"last_seen"`
|
||||
Messages int `json:"messages"`
|
||||
TrackHistory []TrackPoint `json:"track_history,omitempty"`
|
||||
RSSI float64 `json:"rssi,omitempty"`
|
||||
Country string `json:"country,omitempty"`
|
||||
Registration string `json:"registration,omitempty"`
|
||||
}
|
||||
|
||||
type AircraftData struct {
|
||||
|
|
@ -44,10 +47,10 @@ func ParseSBS1Line(line string) (*Aircraft, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
messageType := parts[1]
|
||||
if messageType != "1" && messageType != "3" && messageType != "4" {
|
||||
return nil, nil
|
||||
}
|
||||
// messageType := parts[1]
|
||||
// Accept all message types to get complete data
|
||||
// MSG types: 1=ES_IDENT_AND_CATEGORY, 2=ES_SURFACE_POS, 3=ES_AIRBORNE_POS
|
||||
// 4=ES_AIRBORNE_VEL, 5=SURVEILLANCE_ALT, 6=SURVEILLANCE_ID, 7=AIR_TO_AIR, 8=ALL_CALL_REPLY
|
||||
|
||||
aircraft := &Aircraft{
|
||||
Hex: strings.TrimSpace(parts[4]),
|
||||
|
|
@ -55,6 +58,8 @@ func ParseSBS1Line(line string) (*Aircraft, error) {
|
|||
Messages: 1,
|
||||
}
|
||||
|
||||
// Different message types contain different fields
|
||||
// Always try to extract what's available
|
||||
if parts[10] != "" {
|
||||
aircraft.Flight = strings.TrimSpace(parts[10])
|
||||
}
|
||||
|
|
@ -72,8 +77,8 @@ func ParseSBS1Line(line string) (*Aircraft, error) {
|
|||
}
|
||||
|
||||
if parts[13] != "" {
|
||||
if track, err := strconv.Atoi(parts[13]); err == nil {
|
||||
aircraft.Track = track
|
||||
if track, err := strconv.ParseFloat(parts[13], 64); err == nil {
|
||||
aircraft.Track = int(track)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,6 +105,121 @@ func ParseSBS1Line(line string) (*Aircraft, error) {
|
|||
aircraft.OnGround = parts[21] == "1"
|
||||
}
|
||||
|
||||
aircraft.Country = getCountryFromICAO(aircraft.Hex)
|
||||
aircraft.Registration = getRegistrationFromICAO(aircraft.Hex)
|
||||
|
||||
return aircraft, nil
|
||||
}
|
||||
|
||||
func getCountryFromICAO(icao string) string {
|
||||
if len(icao) < 6 {
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
prefix := icao[:1]
|
||||
|
||||
switch prefix {
|
||||
case "4":
|
||||
return getCountryFrom4xxxx(icao)
|
||||
case "A":
|
||||
return "United States"
|
||||
case "C":
|
||||
return "Canada"
|
||||
case "D":
|
||||
return "Germany"
|
||||
case "F":
|
||||
return "France"
|
||||
case "G":
|
||||
return "United Kingdom"
|
||||
case "I":
|
||||
return "Italy"
|
||||
case "J":
|
||||
return "Japan"
|
||||
case "P":
|
||||
return getPCountry(icao)
|
||||
case "S":
|
||||
return getSCountry(icao)
|
||||
case "O":
|
||||
return getOCountry(icao)
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func getCountryFrom4xxxx(icao string) string {
|
||||
if len(icao) >= 2 {
|
||||
switch icao[:2] {
|
||||
case "40":
|
||||
return "United Kingdom"
|
||||
case "44":
|
||||
return "Austria"
|
||||
case "45":
|
||||
return "Denmark"
|
||||
case "46":
|
||||
return "Germany"
|
||||
case "47":
|
||||
return "Germany"
|
||||
case "48":
|
||||
return "Netherlands"
|
||||
case "49":
|
||||
return "Netherlands"
|
||||
}
|
||||
}
|
||||
return "Europe"
|
||||
}
|
||||
|
||||
func getPCountry(icao string) string {
|
||||
if len(icao) >= 2 {
|
||||
switch icao[:2] {
|
||||
case "PH":
|
||||
return "Netherlands"
|
||||
case "PJ":
|
||||
return "Netherlands Antilles"
|
||||
}
|
||||
}
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
func getSCountry(icao string) string {
|
||||
if len(icao) >= 2 {
|
||||
switch icao[:2] {
|
||||
case "SE":
|
||||
return "Sweden"
|
||||
case "SX":
|
||||
return "Greece"
|
||||
}
|
||||
}
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
func getOCountry(icao string) string {
|
||||
if len(icao) >= 2 {
|
||||
switch icao[:2] {
|
||||
case "OO":
|
||||
return "Belgium"
|
||||
case "OH":
|
||||
return "Finland"
|
||||
}
|
||||
}
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
func getRegistrationFromICAO(icao string) string {
|
||||
// This is a simplified conversion - real registration lookup would need a database
|
||||
country := getCountryFromICAO(icao)
|
||||
switch country {
|
||||
case "Germany":
|
||||
return "D-" + icao[2:]
|
||||
case "United Kingdom":
|
||||
return "G-" + icao[2:]
|
||||
case "France":
|
||||
return "F-" + icao[2:]
|
||||
case "Netherlands":
|
||||
return "PH-" + icao[2:]
|
||||
case "Sweden":
|
||||
return "SE-" + icao[2:]
|
||||
default:
|
||||
return icao
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue