Decode US civil Mode S codes to N numbers

pull/442/head
AvSquirrel 2016-06-20 03:30:40 +00:00
rodzic a062241c7a
commit efaaa8777d
3 zmienionych plików z 137 dodań i 7 usunięć

Wyświetl plik

@ -13,6 +13,7 @@ import (
"bufio"
"encoding/hex"
"encoding/json"
"fmt"
"log"
"math"
"net"
@ -75,7 +76,8 @@ const (
type TrafficInfo struct {
Icao_addr uint32
Tail string
Reg string // Registration. Calculated from Icao_addr for civil aircraft of US registry.
Tail string // Callsign. Transmitted by aircraft.
Emitter_category uint8 // Formatted using GDL90 standard, e.g. in a Mode ES report, A7 becomes 0x07, B0 becomes 0x08, etc.
OnGround bool // Air-ground status. On-ground is "true".
Addr_type uint8 // UAT address qualifier. Used by GDL90 format, so translations for ES TIS-B/ADS-R are needed.
@ -349,6 +351,12 @@ func parseDownlinkReport(s string, signalLevel int) {
ti.Last_seen = stratuxClock.Time // need to initialize to current stratuxClock so it doesn't get cut before we have a chance to populate a position message
ti.Icao_addr = icao_addr
ti.ExtrapolatedPosition = false
thisReg, validReg := icao2faa(icao_addr)
if validReg {
ti.Reg = thisReg
ti.Tail = thisReg
}
}
ti.Addr_type = addr_type
@ -650,6 +658,12 @@ func esListen() {
ti.Icao_addr = icao
ti.ExtrapolatedPosition = false
ti.Last_source = TRAFFIC_SOURCE_1090ES
thisReg, validReg := icao2faa(icao)
if validReg {
ti.Reg = thisReg
ti.Tail = thisReg
}
}
ti.SignalLevel = 10 * math.Log10(newTi.SignalLevel)
@ -1000,6 +1014,104 @@ func updateDemoTraffic(icao uint32, tail string, relAlt float32, gs float64, off
}
}
/*
icao2faa() : Converts 24-bit Mode S addresses to N-numbers.
Input: uint32 representing the Mode S address. Valid range for
translation is 0xA00001 - 0xADF7C7, inclusive.
Values outside the range A000001-AFFFFFF are flagged as non-US.
Values between ADF7C8 - AFFFFF are allocated to the United States,
but are not used for aicraft on the civil registry. These could be
military, other public aircraft, or (future use) temporary
anonymous addresses.
Output:
string: String containing the decoded tail number (if decoding succeeded),
"NON-US" (for non-US allocation), and "MIL" for non-civil US allocation.
bool: True if the Mode S address successfully translated to an
N number. False for all other conditions.
*/
func icao2faa(icao_addr uint32) (string, bool) {
// Initialize local variables
base34alphabet := string("ABCDEFGHJKLMNPQRSTUVWXYZ0123456789")
faaOffset := uint32(0xA00001)
tail := ""
// Discard non-US ICAO codes
if (icao_addr < 0xA00001) || (icao_addr > 0xAFFFFF) {
//fmt.Printf("%X is a non-US address.\n", icao_addr)
return "NON-US", false
}
// Discard addresses that are not assigned to aircraft on the civil registry (public aircraft: USAF, USN, USMC, USCG, ANG, FBI, etc.)
if icao_addr > 0xADF7C7 {
//fmt.Printf("%X is a US aircraft, but not on the civil registry.\n", icao_addr)
return "MIL", false
}
serial := int32(icao_addr - faaOffset)
// First digit
a := (serial / 101711) + 1
// Second digit
a_remainder := serial % 101711
b := ((a_remainder + 9510) / 10111) - 1
// Third digit
b_remainder := (a_remainder + 9510) % 10111
c := ((b_remainder + 350) / 951) - 1
// This next bit is more convoluted. First, figure out if we're using the "short" method of
// decoding the last two digits (two letters, one letter and one blank, or two blanks).
// This will be the case if digit "B" or "C" are calculated as negative, or if c_remainder
// is less than 601.
c_remainder := (b_remainder + 350) % 951
var d, e int32
if (b >= 0) && (c >= 0) && (c_remainder > 600) { // alphanumeric decoding method
d = 24 + (c_remainder-601)/35
e = (c_remainder - 601) % 35
} else { // two-letter decoding method
if (b < 0) || (c < 0) {
c_remainder -= 350 // otherwise " " == 350, "A " == 351, "AA" == 352, etc.
}
d = (c_remainder - 1) / 25
e = (c_remainder - 1) % 25
if e < 0 {
d -= 1
e += 25
}
}
a_char := fmt.Sprintf("%d", a)
var b_char, c_char, d_char, e_char string
if b >= 0 {
b_char = fmt.Sprintf("%d", b)
}
if b >= 0 && c >= 0 {
c_char = fmt.Sprintf("%d", c)
}
if d > -1 {
d_char = string(base34alphabet[d])
if e > 0 {
e_char = string(base34alphabet[e-1])
}
}
tail = "N" + a_char + b_char + c_char + d_char + e_char
return tail, true
}
func initTraffic() {
traffic = make(map[uint32]TrafficInfo)
seenTraffic = make(map[uint32]bool)

Wyświetl plik

@ -59,6 +59,7 @@ function TrafficCtrl($rootScope, $scope, $state, $http, $interval) {
}
new_traffic.icao = obj.Icao_addr.toString(16).toUpperCase();
new_traffic.tail = obj.Tail;
new_traffic.reg = obj.Reg;
if (obj.Squawk == 0) {
new_traffic.squawk = "----";
} else {

Wyświetl plik

@ -9,7 +9,8 @@
<div class="panel-body traffic-page">
<div class="row">
<div class="col-sm-6">
<span class="col-xs-3"><strong>Callsign</strong></span>
<span class="col-xs-3" ng-hide="showReg"><strong>Callsign</strong></span>
<span class="col-xs-3" ng-show="showReg"><strong>Tail Num</strong></span>
<span class="col-xs-2" ng-hide="showSquawk"><strong>Code</strong></span>
<span class="col-xs-2" ng-show="showSquawk"><strong>Squawk</strong></span>
<span class="col-xs-5 text-right" ng-hide="GPS_connected && RelDist"><strong>Location</strong></span>
@ -29,11 +30,15 @@
<div class="row" ng-repeat="aircraft in data_list | orderBy: 'dist'">
<div class="separator"></div>
<div class="col-sm-6">
<span class="col-xs-3">
<span class="col-xs-3" ng-hide="showReg">
<span ng-show="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;{{aircraft.tail}}</strong></span>
<span ng-hide="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span>
<span class="col-xs-3" ng-show="showReg">
<span ng-show="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;{{aircraft.reg}}</strong></span>
<span ng-hide="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span>
<span class="col-xs-2">
<span style="font-size:80%" ng-hide="showSquawk">{{aircraft.icao}}<span style="font-size:50%">{{aircraft.addr_type == 3 ? "&nbsp;(TFID)" : ""}}</span></span>
<span ng-show="showSquawk"><span ng-show="aircraft.squawk < 1000">0</span><span ng-show="aircraft.squawk < 100">0</span><span ng-show="aircraft.squawk < 10">0</span>{{aircraft.squawk}}</span>
@ -60,19 +65,26 @@
<div class="panel-body traffic-footer">
<div class="separator"></div>
<div class="row">
<div class="col-sm-4">
<label class="control-label col-xs-6">Show Tail Number</label>
<span class="col-xs-3"><ui-switch ng-model='showReg' settings-change></ui-switch></span>
</div>
<div class="col-sm-4">
<label class="control-label col-xs-6">Show Squawk</label>
<span class="col-xs-3"><ui-switch ng-model='showSquawk' settings-change></ui-switch></span>
</div>
<div class="col-sm-4">
<label class="control-label col-xs-6">Show Distance</label>
<label class="control-label col-xs-6" ng-show="GPS_connected">Show Distance</label>
<label class="control-label text-muted col-xs-6" ng-hide="GPS_connected">Show Distance N/A</label>
<span class="col-xs-3"><ui-switch ng-model='RelDist' settings-change></ui-switch></span>
</div>
<!--
<div class="col-sm-4">
<label class="control-label col-xs-6">GPS Status</label>
<span ng-show="GPS_connected" class="label label-success col-xs-3" style="font-size:100%; display:block; height: 34px; line-height: 34px">Valid</span>
<span ng-hide="GPS_connected" class="label label-danger col-xs-3" style="font-size:100%; display:block; height: 34px; line-height: 34px">No Fix</span>
</div>
-->
</div>
</div>
</div>
@ -85,7 +97,8 @@
<div class="panel-body traffic-page">
<div class="row">
<div class="col-sm-6">
<span class="col-xs-4"><strong>Callsign</strong></span>
<span class="col-xs-4" ng-hide="showReg"><strong>Callsign</strong></span>
<span class="col-xs-4" ng-show="showReg"><strong>Tail Num</strong></span>
<span class="col-xs-3"><strong>Code</strong></span>
<span class="col-xs-3"><strong>Squawk</strong></span>
</div>
@ -102,9 +115,13 @@
<div class="row" ng-repeat="aircraft in data_list_invalid | orderBy: 'icao'">
<div class="separator"></div>
<div class="col-sm-6">
<span class="col-xs-4">
<span class="col-xs-4" ng-hide="showReg">
<span ng-show="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;{{aircraft.tail}}</strong></span>
<span ng-hide="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span>
<span class="col-xs-4" ng-show="showReg">
<span ng-show="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;{{aircraft.reg}}</strong></span>
<span ng-hide="aircraft.reg" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype">{{aircraft.addr_symb}}<strong>&nbsp;[--N/A--]</strong></span>
</span>
<span class="col-xs-3" style="font-size:80%">{{aircraft.icao}}<span style="font-size:50%">{{aircraft.addr_type == 3 ? "&nbsp;(TFID)" : ""}}</span></span>
<span class="col-xs-3"><span ng-show="aircraft.squawk < 1000">0</span><span ng-show="aircraft.squawk < 100">0</span><span ng-show="aircraft.squawk < 10">0</span>{{aircraft.squawk}}</span>