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:
parent
67d0e0612a
commit
0d60592b9f
16 changed files with 266 additions and 289 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue