Fix issue #21 and add aircraft position tracking indicators

- Fix Debian package upgrade issue by separating upgrade vs remove behavior in prerm script
- Add aircraft position tracking statistics in merger GetStatistics() method
- Update frontend to display position tracking indicators in both header and stats view
- Format Go code to maintain consistency

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2025-08-31 11:25:42 +02:00
commit 66a995b4d0
8 changed files with 124 additions and 74 deletions

View file

@ -34,30 +34,30 @@ type VRSMessage struct {
// VRSAircraft represents a single aircraft in VRS JSON format
type VRSAircraft struct {
Icao string `json:"Icao"` // ICAO hex address (may have ~ prefix for non-ICAO)
Lat float64 `json:"Lat"` // Latitude
Long float64 `json:"Long"` // Longitude
Alt int `json:"Alt"` // Barometric altitude in feet
GAlt int `json:"GAlt"` // Geometric altitude in feet
Spd float64 `json:"Spd"` // Speed in knots
Trak float64 `json:"Trak"` // Track/heading in degrees
Vsi int `json:"Vsi"` // Vertical speed in feet/min
Sqk string `json:"Sqk"` // Squawk code
Call string `json:"Call"` // Callsign
Gnd bool `json:"Gnd"` // On ground flag
TAlt int `json:"TAlt"` // Target altitude
Mlat bool `json:"Mlat"` // MLAT position flag
Tisb bool `json:"Tisb"` // TIS-B flag
Sat bool `json:"Sat"` // Satellite (JAERO) position flag
Icao string `json:"Icao"` // ICAO hex address (may have ~ prefix for non-ICAO)
Lat float64 `json:"Lat"` // Latitude
Long float64 `json:"Long"` // Longitude
Alt int `json:"Alt"` // Barometric altitude in feet
GAlt int `json:"GAlt"` // Geometric altitude in feet
Spd float64 `json:"Spd"` // Speed in knots
Trak float64 `json:"Trak"` // Track/heading in degrees
Vsi int `json:"Vsi"` // Vertical speed in feet/min
Sqk string `json:"Sqk"` // Squawk code
Call string `json:"Call"` // Callsign
Gnd bool `json:"Gnd"` // On ground flag
TAlt int `json:"TAlt"` // Target altitude
Mlat bool `json:"Mlat"` // MLAT position flag
Tisb bool `json:"Tisb"` // TIS-B flag
Sat bool `json:"Sat"` // Satellite (JAERO) position flag
// Additional fields that may be present
Reg string `json:"Reg"` // Registration
Type string `json:"Type"` // Aircraft type
Mdl string `json:"Mdl"` // Model
Op string `json:"Op"` // Operator
From string `json:"From"` // Departure airport
To string `json:"To"` // Destination airport
Reg string `json:"Reg"` // Registration
Type string `json:"Type"` // Aircraft type
Mdl string `json:"Mdl"` // Model
Op string `json:"Op"` // Operator
From string `json:"From"` // Departure airport
To string `json:"To"` // Destination airport
// Timing fields
PosTime int64 `json:"PosTime"` // Position timestamp (milliseconds)
}
@ -95,21 +95,21 @@ func (p *Parser) ReadMessage() (*VRSMessage, error) {
if err != nil {
return nil, err
}
// Trim whitespace
line = strings.TrimSpace(line)
if line == "" {
// Empty line, try again
return p.ReadMessage()
}
// Parse JSON
var msg VRSMessage
if err := json.Unmarshal([]byte(line), &msg); err != nil {
// Invalid JSON, skip and continue
return p.ReadMessage()
}
return &msg, nil
}
@ -146,13 +146,13 @@ func (p *Parser) ParseStream(msgChan chan<- *VRSMessage, errChan chan<- error) {
func (a *VRSAircraft) GetICAO24() (uint32, error) {
// Remove non-ICAO prefix if present
icaoStr := strings.TrimPrefix(a.Icao, "~")
// Parse hex string
icao64, err := strconv.ParseUint(icaoStr, 16, 24)
if err != nil {
return 0, fmt.Errorf("invalid ICAO address: %s", a.Icao)
}
return uint32(icao64), nil
}
@ -195,13 +195,13 @@ func (a *VRSAircraft) GetSquawk() (uint16, error) {
if a.Sqk == "" {
return 0, fmt.Errorf("no squawk code")
}
// Parse hex squawk code
squawk64, err := strconv.ParseUint(a.Sqk, 16, 16)
if err != nil {
return 0, fmt.Errorf("invalid squawk code: %s", a.Sqk)
}
return uint16(squawk64), nil
}
@ -231,4 +231,4 @@ func (a *VRSAircraft) GetTimestamp() time.Time {
// IsOnGround returns true if the aircraft is on the ground
func (a *VRSAircraft) IsOnGround() bool {
return a.Gnd
}
}