Clean up codebase and fix server host binding for IPv6 support

Cleanup:
- Remove unused aircraft-icon.svg (replaced by type-specific icons)
- Remove test files: beast-dump-with-heli.bin, beast.test, main, old.json, ux.png
- Remove duplicate config.json.example (kept config.example.json)
- Remove empty internal/coverage/ directory
- Move CLAUDE.md to project root
- Update assets.go documentation to reflect current icon structure
- Format all Go code with gofmt

Server Host Binding Fix:
- Fix critical bug where server host configuration was ignored
- Add host parameter to Server struct and NewWebServer constructor
- Rename NewServer to NewWebServer for better clarity
- Fix IPv6 address formatting in server binding (wrap in brackets)
- Update startup message to show correct bind address format
- Support localhost-only, IPv4, IPv6, and interface-specific binding

This resolves the "too many colons in address" error for IPv6 hosts like ::1
and enables proper localhost-only deployment as configured.

Closes #15

🤖 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-24 18:36:14 +02:00
commit 0d60592b9f
16 changed files with 266 additions and 289 deletions

View file

@ -56,16 +56,16 @@ func validateModeSCRC(data []byte) bool {
if len(data) < 4 {
return false
}
// Calculate CRC for all bytes except the last 3 (which contain the CRC)
crc := uint32(0)
for i := 0; i < len(data)-3; i++ {
crc = ((crc << 8) ^ crcTable[((crc>>16)^uint32(data[i]))&0xFF]) & 0xFFFFFF
}
// Extract transmitted CRC from last 3 bytes
transmittedCRC := uint32(data[len(data)-3])<<16 | uint32(data[len(data)-2])<<8 | uint32(data[len(data)-1])
return crc == transmittedCRC
}
@ -107,37 +107,37 @@ const (
// depending on the messages received and aircraft capabilities.
type Aircraft struct {
// Core Identification
ICAO24 uint32 // 24-bit ICAO aircraft address (unique identifier)
Callsign string // 8-character flight callsign (from identification messages)
ICAO24 uint32 // 24-bit ICAO aircraft address (unique identifier)
Callsign string // 8-character flight callsign (from identification messages)
// Position and Navigation
Latitude float64 // Position latitude in decimal degrees
Longitude float64 // Position longitude in decimal degrees
Altitude int // Altitude in feet (barometric or geometric)
BaroAltitude int // Barometric altitude in feet (QNH corrected)
GeomAltitude int // Geometric altitude in feet (GNSS height)
Latitude float64 // Position latitude in decimal degrees
Longitude float64 // Position longitude in decimal degrees
Altitude int // Altitude in feet (barometric or geometric)
BaroAltitude int // Barometric altitude in feet (QNH corrected)
GeomAltitude int // Geometric altitude in feet (GNSS height)
// Motion and Dynamics
VerticalRate int // Vertical rate in feet per minute (climb/descent)
GroundSpeed int // Ground speed in knots (integer)
Track int // Track angle in degrees (0-359, integer)
Heading int // Aircraft heading in degrees (magnetic, integer)
VerticalRate int // Vertical rate in feet per minute (climb/descent)
GroundSpeed int // Ground speed in knots (integer)
Track int // Track angle in degrees (0-359, integer)
Heading int // Aircraft heading in degrees (magnetic, integer)
// Aircraft Information
Category string // Aircraft category (size, type, performance)
Squawk string // 4-digit transponder squawk code (octal)
Category string // Aircraft category (size, type, performance)
Squawk string // 4-digit transponder squawk code (octal)
// Status and Alerts
Emergency string // Emergency/priority status description
OnGround bool // Aircraft is on ground (surface movement)
Alert bool // Alert flag (ATC attention required)
SPI bool // Special Position Identification (pilot activated)
Emergency string // Emergency/priority status description
OnGround bool // Aircraft is on ground (surface movement)
Alert bool // Alert flag (ATC attention required)
SPI bool // Special Position Identification (pilot activated)
// Data Quality Indicators
NACp uint8 // Navigation Accuracy Category - Position (0-11)
NACv uint8 // Navigation Accuracy Category - Velocity (0-4)
SIL uint8 // Surveillance Integrity Level (0-3)
NACp uint8 // Navigation Accuracy Category - Position (0-11)
NACv uint8 // Navigation Accuracy Category - Velocity (0-4)
SIL uint8 // Surveillance Integrity Level (0-3)
// Autopilot/Flight Management
SelectedAltitude int // MCP/FCU selected altitude in feet
SelectedHeading float64 // MCP/FCU selected heading in degrees
@ -163,11 +163,11 @@ type Decoder struct {
cprOddLon map[uint32]float64 // Odd message longitude encoding (ICAO24 -> normalized lon)
cprEvenTime map[uint32]int64 // Timestamp of even message (for freshness comparison)
cprOddTime map[uint32]int64 // Timestamp of odd message (for freshness comparison)
// Reference position for CPR zone ambiguity resolution (receiver location)
refLatitude float64 // Receiver latitude in decimal degrees
refLongitude float64 // Receiver longitude in decimal degrees
// Mutex to protect concurrent access to CPR maps
mu sync.RWMutex
}
@ -199,10 +199,10 @@ func NewDecoder(refLat, refLon float64) *Decoder {
// Decode processes a Mode S message and extracts all available aircraft information.
//
// This is the main entry point for message decoding. The method:
// 1. Validates message length and extracts the Downlink Format (DF)
// 2. Extracts the ICAO24 aircraft address
// 3. Routes to appropriate decoder based on message type
// 4. Returns populated Aircraft struct with available data
// 1. Validates message length and extracts the Downlink Format (DF)
// 2. Extracts the ICAO24 aircraft address
// 3. Routes to appropriate decoder based on message type
// 4. Returns populated Aircraft struct with available data
//
// Different message types provide different information:
// - DF4/20: Altitude only
@ -369,10 +369,10 @@ func (d *Decoder) decodeIdentification(data []byte, aircraft *Aircraft) {
// - Even/odd flag for CPR decoding
//
// CPR (Compact Position Reporting) Process:
// 1. Extract the even/odd flag and CPR lat/lon values
// 2. Normalize CPR values to 0-1 range (divide by 2^17)
// 3. Store values for this aircraft's ICAO address
// 4. Attempt position decoding if both even and odd messages are available
// 1. Extract the even/odd flag and CPR lat/lon values
// 2. Normalize CPR values to 0-1 range (divide by 2^17)
// 3. Store values for this aircraft's ICAO address
// 4. Attempt position decoding if both even and odd messages are available
//
// The actual position calculation requires both even and odd messages to
// resolve the ambiguity inherent in the compressed encoding format.
@ -456,7 +456,7 @@ func (d *Decoder) decodeCPRPosition(aircraft *Aircraft) {
} else if latEven < -90 {
latEven = -180 - latEven
}
if latOdd > 90 {
latOdd = 180 - latOdd
} else if latOdd < -90 {
@ -473,7 +473,7 @@ func (d *Decoder) decodeCPRPosition(aircraft *Aircraft) {
// Calculate which decoded latitude is closer to the receiver
distToEven := math.Abs(latEven - d.refLatitude)
distToOdd := math.Abs(latOdd - d.refLatitude)
// Choose the latitude solution that's closer to the receiver position
if distToOdd < distToEven {
aircraft.Latitude = latOdd
@ -501,7 +501,7 @@ func (d *Decoder) decodeCPRPosition(aircraft *Aircraft) {
}
aircraft.Longitude = lon
// CPR decoding completed successfully
}
@ -576,13 +576,13 @@ func (d *Decoder) decodeVelocity(data []byte, aircraft *Aircraft) {
// Calculate ground speed in knots (rounded to integer)
speedKnots := math.Sqrt(ewVel*ewVel + nsVel*nsVel)
// Validate speed range (0-600 knots for civilian aircraft)
if speedKnots > 600 {
speedKnots = 600 // Cap at reasonable maximum
}
aircraft.GroundSpeed = int(math.Round(speedKnots))
// Calculate track in degrees (0-359)
trackDeg := math.Atan2(ewVel, nsVel) * 180 / math.Pi
if trackDeg < 0 {
@ -641,20 +641,20 @@ func (d *Decoder) decodeAltitudeBits(altCode uint16, tc uint8) int {
// Standard altitude encoding with 25 ft increments
// Check Q-bit (bit 4) for encoding type
qBit := (altCode >> 4) & 1
if qBit == 1 {
// Standard altitude with Q-bit set
// Remove Q-bit and reassemble 11-bit altitude code
n := ((altCode & 0x1F80) >> 2) | ((altCode & 0x0020) >> 1) | (altCode & 0x000F)
alt := int(n)*25 - 1000
// Validate altitude range
if alt < -1000 || alt > 60000 {
return 0
}
return alt
}
// Gray code altitude (100 ft increments) - legacy encoding
// Convert from Gray code to binary
n := altCode
@ -662,7 +662,7 @@ func (d *Decoder) decodeAltitudeBits(altCode uint16, tc uint8) int {
n ^= n >> 4
n ^= n >> 2
n ^= n >> 1
// Convert to altitude in feet
alt := int(n&0x7FF) * 100
if alt < 0 || alt > 60000 {
@ -835,7 +835,7 @@ func (d *Decoder) decodeTargetState(data []byte, aircraft *Aircraft) {
//
// Operational status messages (TC 31) contain:
// - Navigation Accuracy Category for Position (NACp): Position accuracy
// - Navigation Accuracy Category for Velocity (NACv): Velocity accuracy
// - Navigation Accuracy Category for Velocity (NACv): Velocity accuracy
// - Surveillance Integrity Level (SIL): System integrity confidence
//
// These parameters help receiving systems assess data quality and determine