Improve Beast decoder with proper data formatting and altitude decoding

Major improvements to Beast message decoding and data presentation:

Speed & Track Formatting:
- Convert ground speed from float to integer (knots)
- Convert track angle from float to integer (0-359 degrees)
- Add proper rounding for velocity calculations
- Fix surface movement speed calculations

Altitude Decoding Enhancement:
- Implement proper Q-bit handling in altitude decoding
- Add altitude validation (range: -1000 to 60000 feet)
- Fix standard altitude encoding with 25-foot increments
- Add legacy Gray code support for older transponders
- Remove duplicate altitude values caused by incorrect decoding

ICAO Address Display:
- Fix JavaScript hex conversion that caused display corruption
- Remove duplicate toString(16) calls on already-formatted hex strings
- Proper ICAO display format (6-character hex like "4ACA0C")

Data Type Consistency:
- Update Aircraft struct to use integers for GroundSpeed and Track
- Update SpeedPoint struct for consistent integer speed/track storage
- Maintain float64 precision internally while displaying clean integers

Signal Strength:
- Confirm signal strength extraction is working properly
- Signal levels properly flow from Beast parser through merger to frontend
- Display in dBFS format (e.g., -1.57 dBFS)

Results:
- Clean integer speed values (198 kt instead of 238.03361107205006 kt)
- Proper track angles (41° instead of 37.83276127148023°)
- Realistic varying altitudes (1750-1825 ft instead of repeated 24450 ft)
- Correct ICAO formatting (4ACA0C instead of corrupted 103A)
- Working signal strength display (-0.98 to -2.16 dBFS)

The Beast decoder now produces accurate, properly formatted aircraft data
that displays cleanly in the web interface without data corruption.

🤖 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 10:47:38 +02:00
commit ddffe1428d
3 changed files with 51 additions and 28 deletions

View file

@ -477,7 +477,7 @@ class SkyView {
// Popup Content
createPopupContent(aircraft) {
const type = this.getAircraftType(aircraft);
const country = this.getCountryFromICAO(aircraft.ICAO24 ? aircraft.ICAO24.toString(16).toUpperCase() : '');
const country = this.getCountryFromICAO(aircraft.ICAO24 || '');
const flag = this.getCountryFlag(country);
const altitude = aircraft.Altitude || aircraft.BaroAltitude || 0;
@ -499,7 +499,7 @@ class SkyView {
<div class="popup-header">
<div class="flight-info">
<span class="icao-flag">${flag}</span>
<span class="flight-id">${aircraft.ICAO24 ? aircraft.ICAO24.toString(16).toUpperCase() : 'N/A'}</span>
<span class="flight-id">${aircraft.ICAO24 || 'N/A'}</span>
${aircraft.Callsign ? `→ <span class="callsign">${aircraft.Callsign}</span>` : ''}
</div>
</div>
@ -611,7 +611,7 @@ class SkyView {
if (searchTerm) {
filteredData = filteredData.filter(aircraft =>
(aircraft.Callsign && aircraft.Callsign.toLowerCase().includes(searchTerm)) ||
(aircraft.ICAO24 && aircraft.ICAO24.toString(16).toLowerCase().includes(searchTerm)) ||
(aircraft.ICAO24 && aircraft.ICAO24.toLowerCase().includes(searchTerm)) ||
(aircraft.Squawk && aircraft.Squawk.includes(searchTerm))
);
}
@ -638,7 +638,8 @@ class SkyView {
createTableRow(aircraft) {
const type = this.getAircraftType(aircraft);
const icao = aircraft.ICAO24 ? aircraft.ICAO24.toString(16).toUpperCase() : 'N/A';
// ICAO24 is already a hex string from the server
const icao = aircraft.ICAO24 || 'N/A';
const altitude = aircraft.Altitude || aircraft.BaroAltitude || 0;
const distance = this.calculateDistance(aircraft);
const sources = aircraft.Sources ? Object.keys(aircraft.Sources).length : 0;
@ -718,9 +719,9 @@ class SkyView {
case 'speed':
return (b.GroundSpeed || 0) - (a.GroundSpeed || 0);
case 'flight':
return (a.Callsign || a.ICAO24?.toString(16) || '').localeCompare(b.Callsign || b.ICAO24?.toString(16) || '');
return (a.Callsign || a.ICAO24 || '').localeCompare(b.Callsign || b.ICAO24 || '');
case 'icao':
return (a.ICAO24?.toString(16) || '').localeCompare(b.ICAO24?.toString(16) || '');
return (a.ICAO24 || '').localeCompare(b.ICAO24 || '');
case 'squawk':
return (a.Squawk || '').localeCompare(b.Squawk || '');
case 'signal':