kopia lustrzana https://github.com/cyoung/stratux
Incorporate dump1090-mutability
commit
a9b631e732
2
dump1090
2
dump1090
|
@ -1 +1 @@
|
||||||
Subproject commit b360db74b99a408cb83833af802042d29cccffd9
|
Subproject commit 7eca082524fa135eb8efd78780f25739efb6a82c
|
|
@ -131,7 +131,7 @@ void make_atan2_table(void) {
|
||||||
double scaled_ang = round(32768 * ang / M_PI);
|
double scaled_ang = round(32768 * ang / M_PI);
|
||||||
|
|
||||||
double amp = sqrt(d_i * d_i + d_q * d_q);
|
double amp = sqrt(d_i * d_i + d_q * d_q);
|
||||||
uint16_t scaled_amp = amp * 1000.0 / 127.5 + .5;
|
uint16_t scaled_amp = amp * 1000.0 / 127.5;
|
||||||
|
|
||||||
u.iq[0] = i;
|
u.iq[0] = i;
|
||||||
u.iq[1] = q;
|
u.iq[1] = q;
|
||||||
|
@ -150,13 +150,13 @@ static void convert_to_phi(uint16_t *dest, uint16_t *src, int n) {
|
||||||
dest[i] = iqphase[src[i]];
|
dest[i] = iqphase[src[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void calc_power(uint16_t *samples, int len) {
|
static void calc_power(uint16_t *samples, int len) { // sets signal_strength to scaled amplitude. 0 = no signal, 1000 = saturated receiver on all samples in measurement.
|
||||||
long avg = 0;
|
long avg = 0;
|
||||||
int n = len;
|
int n = len;
|
||||||
while (n--) {
|
while (n--) {
|
||||||
avg += iqamplitude[*samples++];
|
avg += iqamplitude[*samples++];
|
||||||
}
|
}
|
||||||
signal_strength = (avg + len / 2) / len;
|
signal_strength = avg / len;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BUILD_LIB
|
#ifndef BUILD_LIB
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -110,12 +111,13 @@ var dump1090ReplayWriter WriteCloser
|
||||||
var developerMode bool
|
var developerMode bool
|
||||||
|
|
||||||
type msg struct {
|
type msg struct {
|
||||||
MessageClass uint
|
MessageClass uint
|
||||||
TimeReceived time.Time
|
TimeReceived time.Time
|
||||||
Data []byte
|
Data []byte
|
||||||
Products []uint32
|
Products []uint32
|
||||||
Signal_strength int
|
Signal_amplitude int
|
||||||
ADSBTowerID string // Index in the 'ADSBTowers' map, if this is a parseable uplink message.
|
Signal_strength float64
|
||||||
|
ADSBTowerID string // Index in the 'ADSBTowers' map, if this is a parseable uplink message.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raw inputs.
|
// Raw inputs.
|
||||||
|
@ -127,9 +129,10 @@ var timeStarted time.Time
|
||||||
type ADSBTower struct {
|
type ADSBTower struct {
|
||||||
Lat float64
|
Lat float64
|
||||||
Lng float64
|
Lng float64
|
||||||
Signal_strength_last_minute int
|
Signal_strength_now float64 // Current RSSI (dB)
|
||||||
signal_power_last_minute int64 // Over total messages.
|
Signal_strength_max float64 // all-time peak RSSI (dB) observed for this tower
|
||||||
Signal_strength_max int
|
Energy_last_minute uint64 // Summation of power observed for this tower across all messages last minute
|
||||||
|
Signal_strength_last_minute float64 // Average RSSI (dB) observed for this tower last minute
|
||||||
Messages_last_minute uint64
|
Messages_last_minute uint64
|
||||||
Messages_total uint64
|
Messages_total uint64
|
||||||
}
|
}
|
||||||
|
@ -596,7 +599,7 @@ func relayMessage(msgtype uint16, msg []byte) {
|
||||||
|
|
||||||
func heartBeatSender() {
|
func heartBeatSender() {
|
||||||
timer := time.NewTicker(1 * time.Second)
|
timer := time.NewTicker(1 * time.Second)
|
||||||
timerMessageStats := time.NewTicker(5 * time.Second)
|
timerMessageStats := time.NewTicker(2 * time.Second)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
|
@ -609,14 +612,14 @@ func heartBeatSender() {
|
||||||
// --- debug code: traffic demo ---
|
// --- debug code: traffic demo ---
|
||||||
// Uncomment and compile to display large number of artificial traffic targets
|
// Uncomment and compile to display large number of artificial traffic targets
|
||||||
/*
|
/*
|
||||||
numTargets := uint32(18)
|
numTargets := uint32(36)
|
||||||
hexCode := uint32(0xFF0000)
|
hexCode := uint32(0xFF0000)
|
||||||
|
|
||||||
for i := uint32(0); i < numTargets; i++ {
|
for i := uint32(0); i < numTargets; i++ {
|
||||||
tail := fmt.Sprintf("DEMO%d", i)
|
tail := fmt.Sprintf("DEMO%d", i)
|
||||||
alt := float32((i*117%2000)*25 + 2000)
|
alt := float32((i*117%2000)*25 + 2000)
|
||||||
hdg := int32((i * 149) % 360)
|
hdg := int32((i * 149) % 360)
|
||||||
spd := float64(50 + ((i*23)%13)*17)
|
spd := float64(50 + ((i*23)%13)*37)
|
||||||
|
|
||||||
updateDemoTraffic(i|hexCode, tail, alt, spd, hdg)
|
updateDemoTraffic(i|hexCode, tail, alt, spd, hdg)
|
||||||
|
|
||||||
|
@ -643,7 +646,7 @@ func updateMessageStats() {
|
||||||
// Clear out ADSBTowers stats.
|
// Clear out ADSBTowers stats.
|
||||||
for t, tinf := range ADSBTowers {
|
for t, tinf := range ADSBTowers {
|
||||||
tinf.Messages_last_minute = 0
|
tinf.Messages_last_minute = 0
|
||||||
tinf.Signal_strength_last_minute = 0
|
tinf.Energy_last_minute = 0
|
||||||
ADSBTowers[t] = tinf
|
ADSBTowers[t] = tinf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,8 +661,8 @@ func updateMessageStats() {
|
||||||
if len(MsgLog[i].ADSBTowerID) > 0 { // Update tower stats.
|
if len(MsgLog[i].ADSBTowerID) > 0 { // Update tower stats.
|
||||||
tid := MsgLog[i].ADSBTowerID
|
tid := MsgLog[i].ADSBTowerID
|
||||||
twr := ADSBTowers[tid]
|
twr := ADSBTowers[tid]
|
||||||
|
twr.Energy_last_minute += uint64((MsgLog[i].Signal_amplitude) * (MsgLog[i].Signal_amplitude))
|
||||||
twr.Messages_last_minute++
|
twr.Messages_last_minute++
|
||||||
twr.signal_power_last_minute += int64(MsgLog[i].Signal_strength)
|
|
||||||
if MsgLog[i].Signal_strength > twr.Signal_strength_max { // Update alltime max signal strength.
|
if MsgLog[i].Signal_strength > twr.Signal_strength_max { // Update alltime max signal strength.
|
||||||
twr.Signal_strength_max = MsgLog[i].Signal_strength
|
twr.Signal_strength_max = MsgLog[i].Signal_strength
|
||||||
}
|
}
|
||||||
|
@ -686,9 +689,9 @@ func updateMessageStats() {
|
||||||
// Update average signal strength over last minute for all ADSB towers.
|
// Update average signal strength over last minute for all ADSB towers.
|
||||||
for t, tinf := range ADSBTowers {
|
for t, tinf := range ADSBTowers {
|
||||||
if tinf.Messages_last_minute == 0 {
|
if tinf.Messages_last_minute == 0 {
|
||||||
tinf.Signal_strength_last_minute = 0
|
tinf.Signal_strength_last_minute = -99
|
||||||
} else {
|
} else {
|
||||||
tinf.Signal_strength_last_minute = int(tinf.signal_power_last_minute / int64(tinf.Messages_last_minute))
|
tinf.Signal_strength_last_minute = 10 * (math.Log10(float64((tinf.Energy_last_minute / tinf.Messages_last_minute))) - 6)
|
||||||
}
|
}
|
||||||
ADSBTowers[t] = tinf
|
ADSBTowers[t] = tinf
|
||||||
}
|
}
|
||||||
|
@ -870,7 +873,7 @@ func parseInput(buf string) ([]byte, uint16) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if s[0] == '-' {
|
if s[0] == '-' {
|
||||||
parseDownlinkReport(s, int32(thisSignalStrength))
|
parseDownlinkReport(s, int(thisSignalStrength))
|
||||||
}
|
}
|
||||||
|
|
||||||
s = s[1:]
|
s = s[1:]
|
||||||
|
@ -902,7 +905,8 @@ func parseInput(buf string) ([]byte, uint16) {
|
||||||
thisMsg.MessageClass = MSGCLASS_UAT
|
thisMsg.MessageClass = MSGCLASS_UAT
|
||||||
thisMsg.TimeReceived = stratuxClock.Time
|
thisMsg.TimeReceived = stratuxClock.Time
|
||||||
thisMsg.Data = frame
|
thisMsg.Data = frame
|
||||||
thisMsg.Signal_strength = thisSignalStrength
|
thisMsg.Signal_amplitude = thisSignalStrength
|
||||||
|
thisMsg.Signal_strength = 20 * math.Log10(float64(thisSignalStrength/1000))
|
||||||
thisMsg.Products = make([]uint32, 0)
|
thisMsg.Products = make([]uint32, 0)
|
||||||
if msgtype == MSGTYPE_UPLINK {
|
if msgtype == MSGTYPE_UPLINK {
|
||||||
// Parse the UAT message.
|
// Parse the UAT message.
|
||||||
|
@ -915,10 +919,13 @@ func parseInput(buf string) ([]byte, uint16) {
|
||||||
var newTower ADSBTower
|
var newTower ADSBTower
|
||||||
newTower.Lat = uatMsg.Lat
|
newTower.Lat = uatMsg.Lat
|
||||||
newTower.Lng = uatMsg.Lon
|
newTower.Lng = uatMsg.Lon
|
||||||
|
newTower.Signal_strength_now = thisMsg.Signal_strength
|
||||||
|
newTower.Signal_strength_max = -999 // dBmax = 0, so this needs to initialize below scale ( << -48 dB)
|
||||||
ADSBTowers[towerid] = newTower
|
ADSBTowers[towerid] = newTower
|
||||||
}
|
}
|
||||||
twr := ADSBTowers[towerid]
|
twr := ADSBTowers[towerid]
|
||||||
twr.Messages_total++
|
twr.Messages_total++
|
||||||
|
twr.Signal_strength_now = thisMsg.Signal_strength
|
||||||
ADSBTowers[towerid] = twr
|
ADSBTowers[towerid] = twr
|
||||||
// Get all of the "product ids".
|
// Get all of the "product ids".
|
||||||
for _, f := range uatMsg.Frames {
|
for _, f := range uatMsg.Frames {
|
||||||
|
|
|
@ -296,8 +296,10 @@ func messageQueueSender() {
|
||||||
averageSendableQueueSize = averageSendableQueueSize / float64(len(outSockets)) // It's a total, not an average, up until this point.
|
averageSendableQueueSize = averageSendableQueueSize / float64(len(outSockets)) // It's a total, not an average, up until this point.
|
||||||
pd = math.Max(float64(1.0/750.0), float64(1.0/(4.0*averageSendableQueueSize))) // Say 250ms is enough to get through the whole queue.
|
pd = math.Max(float64(1.0/750.0), float64(1.0/(4.0*averageSendableQueueSize))) // Say 250ms is enough to get through the whole queue.
|
||||||
} else {
|
} else {
|
||||||
pd = float64(1.0 / 0.1) // 100ms.
|
pd = float64(0.1) // 100ms.
|
||||||
}
|
}
|
||||||
|
log.Printf("Average sendable queue is %v messages. Changing queue timer to %f seconds\n", averageSendableQueueSize, pd)
|
||||||
|
|
||||||
queueTimer.Stop()
|
queueTimer.Stop()
|
||||||
queueTimer = time.NewTicker(time.Duration(pd*1000000000.0) * time.Nanosecond)
|
queueTimer = time.NewTicker(time.Duration(pd*1000000000.0) * time.Nanosecond)
|
||||||
lastQueueTimeChange = stratuxClock.Time
|
lastQueueTimeChange = stratuxClock.Time
|
||||||
|
|
|
@ -55,7 +55,7 @@ func readToChan(fp io.ReadCloser, ch chan []byte) {
|
||||||
func (e *ES) read() {
|
func (e *ES) read() {
|
||||||
defer e.wg.Done()
|
defer e.wg.Done()
|
||||||
log.Println("Entered ES read() ...")
|
log.Println("Entered ES read() ...")
|
||||||
cmd := exec.Command("/usr/bin/dump1090", "--net", "--device-index", strconv.Itoa(e.indexID), "--ppm", strconv.Itoa(e.ppm))
|
cmd := exec.Command("/usr/bin/dump1090", "--oversample", "--net", "--device-index", strconv.Itoa(e.indexID), "--ppm", strconv.Itoa(e.ppm))
|
||||||
stdout, _ := cmd.StdoutPipe()
|
stdout, _ := cmd.StdoutPipe()
|
||||||
stderr, _ := cmd.StderrPipe()
|
stderr, _ := cmd.StderrPipe()
|
||||||
|
|
||||||
|
@ -467,6 +467,7 @@ func sdrWatcher() {
|
||||||
if UATDev != nil {
|
if UATDev != nil {
|
||||||
UATDev.shutdown()
|
UATDev.shutdown()
|
||||||
UATDev = nil
|
UATDev = nil
|
||||||
|
|
||||||
}
|
}
|
||||||
if ESDev != nil {
|
if ESDev != nil {
|
||||||
ESDev.shutdown()
|
ESDev.shutdown()
|
||||||
|
@ -478,6 +479,7 @@ func sdrWatcher() {
|
||||||
prevCount = count
|
prevCount = count
|
||||||
prevUAT_Enabled = globalSettings.UAT_Enabled
|
prevUAT_Enabled = globalSettings.UAT_Enabled
|
||||||
prevES_Enabled = globalSettings.ES_Enabled
|
prevES_Enabled = globalSettings.ES_Enabled
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,11 +65,12 @@ const (
|
||||||
TARGET_TYPE_MODE_S = 0
|
TARGET_TYPE_MODE_S = 0
|
||||||
TARGET_TYPE_ADSB = 1
|
TARGET_TYPE_ADSB = 1
|
||||||
TARGET_TYPE_ADSR = 2
|
TARGET_TYPE_ADSR = 2
|
||||||
TARGET_TYPE_TISB = 3
|
|
||||||
// Assign next type to UAT messages with address qualifier == 2
|
// Assign next type to UAT messages with address qualifier == 2
|
||||||
// (code corresponds to and UAT GBT targets with Mode S addresses..
|
// (code corresponds to any UAT GBT targets with Mode S addresses.
|
||||||
// for we'll treat them as ADS-R in the UI. Might be able to assign as TYPE_ADSR if we see a proper emitter category and NIC > 7.
|
// These will be displayed with the airplane icon on the traffic UI page.
|
||||||
TARGET_TYPE_TISB_S = 4
|
// If we see a proper emitter category and NIC > 7, they'll be reassigned to TYPE_ADSR.
|
||||||
|
TARGET_TYPE_TISB_S = 3
|
||||||
|
TARGET_TYPE_TISB = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
type TrafficInfo struct {
|
type TrafficInfo struct {
|
||||||
|
@ -79,7 +80,7 @@ type TrafficInfo struct {
|
||||||
OnGround bool // Air-ground status. On-ground is "true".
|
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.
|
Addr_type uint8 // UAT address qualifier. Used by GDL90 format, so translations for ES TIS-B/ADS-R are needed.
|
||||||
TargetType uint8 // types decribed in const above
|
TargetType uint8 // types decribed in const above
|
||||||
SignalLevel int32 // Arbitrary signal level reported by dump1090 and dump978.
|
SignalLevel float64 // Signal level, dB RSSI.
|
||||||
Position_valid bool // set when position report received. Unset after n seconds? (To-do)
|
Position_valid bool // set when position report received. Unset after n seconds? (To-do)
|
||||||
Lat float32 // decimal degrees, north positive
|
Lat float32 // decimal degrees, north positive
|
||||||
Lng float32 // decimal degrees, east positive
|
Lng float32 // decimal degrees, east positive
|
||||||
|
@ -111,12 +112,12 @@ type TrafficInfo struct {
|
||||||
|
|
||||||
type dump1090Data struct {
|
type dump1090Data struct {
|
||||||
Icao_addr uint32
|
Icao_addr uint32
|
||||||
DF int // Mode S downlink format.
|
DF int // Mode S downlink format.
|
||||||
CA int // Lowest 3 bits of first byte of Mode S message (DF11 and DF17 capability; DF18 control field, zero for all other DF types)
|
CA int // Lowest 3 bits of first byte of Mode S message (DF11 and DF17 capability; DF18 control field, zero for all other DF types)
|
||||||
TypeCode int // Mode S type code
|
TypeCode int // Mode S type code
|
||||||
SubtypeCode int // Mode S subtype code
|
SubtypeCode int // Mode S subtype code
|
||||||
SBS_MsgType int // type of SBS message (used in "old" 1090 parsing)
|
SBS_MsgType int // type of SBS message (used in "old" 1090 parsing)
|
||||||
SignalLevel int // 0-255
|
SignalLevel float64 // Decimal RSSI (0-1 nominal) as reported by dump1090-mutability. Convert to dB RSSI before setting in TrafficInfo.
|
||||||
Tail *string
|
Tail *string
|
||||||
Squawk *int // 12-bit squawk code in octal format
|
Squawk *int // 12-bit squawk code in octal format
|
||||||
Emitter_category *int
|
Emitter_category *int
|
||||||
|
@ -152,14 +153,14 @@ func sendTrafficUpdates() {
|
||||||
defer trafficMutex.Unlock()
|
defer trafficMutex.Unlock()
|
||||||
cleanupOldEntries()
|
cleanupOldEntries()
|
||||||
var msg []byte
|
var msg []byte
|
||||||
if globalSettings.DEBUG && (stratuxClock.Time.Second()%10) == 0 {
|
if globalSettings.DEBUG && (stratuxClock.Time.Second()%15) == 0 {
|
||||||
log.Printf("List of all aircraft being tracked:\n")
|
log.Printf("List of all aircraft being tracked:\n")
|
||||||
log.Printf("==================================================================\n")
|
log.Printf("==================================================================\n")
|
||||||
}
|
}
|
||||||
for icao, ti := range traffic { // TO-DO: Limit number of aircraft in traffic message. ForeFlight 7.5 chokes at ~1000-2000 messages depending on iDevice RAM. Practical limit likely around ~500 aircraft without filtering.
|
for icao, ti := range traffic { // TO-DO: Limit number of aircraft in traffic message. ForeFlight 7.5 chokes at ~1000-2000 messages depending on iDevice RAM. Practical limit likely around ~500 aircraft without filtering.
|
||||||
|
|
||||||
// DEBUG: Print the list of all tracked targets (with data) to the log every ten seconds
|
// DEBUG: Print the list of all tracked targets (with data) to the log every 15 seconds if "DEBUG" option is enabled
|
||||||
if (stratuxClock.Time.Second() % 10) == 0 {
|
if globalSettings.DEBUG && (stratuxClock.Time.Second()%15) == 0 {
|
||||||
s_out, err := json.Marshal(ti)
|
s_out, err := json.Marshal(ti)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error generating output: %s\n", err.Error())
|
log.Printf("Error generating output: %s\n", err.Error())
|
||||||
|
@ -296,7 +297,7 @@ func makeTrafficReportMsg(ti TrafficInfo) []byte {
|
||||||
return prepareMessage(msg)
|
return prepareMessage(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDownlinkReport(s string, signalLevel int32) {
|
func parseDownlinkReport(s string, signalLevel int) {
|
||||||
|
|
||||||
var ti TrafficInfo
|
var ti TrafficInfo
|
||||||
s = s[1:]
|
s = s[1:]
|
||||||
|
@ -326,7 +327,7 @@ func parseDownlinkReport(s string, signalLevel int32) {
|
||||||
|
|
||||||
// Parse tail number, if available.
|
// Parse tail number, if available.
|
||||||
if msg_type == 1 || msg_type == 3 { // Need "MS" portion of message.
|
if msg_type == 1 || msg_type == 3 { // Need "MS" portion of message.
|
||||||
base40_alphabet := string("0123456789ABCDEFGHIJKLMNOPQRTSUVWXYZ ..")
|
base40_alphabet := string("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ..")
|
||||||
tail := ""
|
tail := ""
|
||||||
|
|
||||||
v := (uint16(frame[17]) << 8) | uint16(frame[18])
|
v := (uint16(frame[17]) << 8) | uint16(frame[18])
|
||||||
|
@ -367,7 +368,11 @@ func parseDownlinkReport(s string, signalLevel int32) {
|
||||||
ti.NACp = int((frame[25] >> 4) & 0x0F)
|
ti.NACp = int((frame[25] >> 4) & 0x0F)
|
||||||
}
|
}
|
||||||
|
|
||||||
ti.SignalLevel = signalLevel
|
power := 20 * (math.Log10(float64(signalLevel) / 1000)) // reported amplitude is 0-1000. Normalize to max = 1 and do amplitude dB calculation (20 dB per decade)
|
||||||
|
|
||||||
|
//log.Printf("%s (%X) seen with amplitude of %d, corresponding to normalized power of %f.2 dB\n",ti.Tail,ti.Icao_addr,signalLevel,power)
|
||||||
|
|
||||||
|
ti.SignalLevel = power
|
||||||
|
|
||||||
if ti.Addr_type == 0 {
|
if ti.Addr_type == 0 {
|
||||||
ti.TargetType = TARGET_TYPE_ADSB
|
ti.TargetType = TARGET_TYPE_ADSB
|
||||||
|
@ -377,7 +382,7 @@ func parseDownlinkReport(s string, signalLevel int32) {
|
||||||
ti.TargetType = TARGET_TYPE_ADSR
|
ti.TargetType = TARGET_TYPE_ADSR
|
||||||
} else if ti.Addr_type == 2 {
|
} else if ti.Addr_type == 2 {
|
||||||
ti.TargetType = TARGET_TYPE_TISB_S
|
ti.TargetType = TARGET_TYPE_TISB_S
|
||||||
if (ti.NIC >= 7) && (ti.Emitter_category > 0) { // If NIC is sufficiently and emitter type is transmitted, we'll assume it's ADS-R.
|
if (ti.NIC >= 7) && (ti.Emitter_category > 0) { // If NIC is sufficiently high and emitter type is transmitted, we'll assume it's ADS-R.
|
||||||
ti.TargetType = TARGET_TYPE_ADSR
|
ti.TargetType = TARGET_TYPE_ADSR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -389,7 +394,7 @@ func parseDownlinkReport(s string, signalLevel int32) {
|
||||||
lng := float32(0.0)
|
lng := float32(0.0)
|
||||||
|
|
||||||
position_valid := false
|
position_valid := false
|
||||||
if (ti.NIC != 0) && (raw_lat != 0) && (raw_lon != 0) {
|
if /*(ti.NIC != 0) && */ (raw_lat != 0) && (raw_lon != 0) { // pass all traffic, and let the display determine if it will show NIC == 0. This will allow misconfigured or uncertified / portable emitters to be seen.
|
||||||
position_valid = true
|
position_valid = true
|
||||||
lat = float32(raw_lat) * 360.0 / 16777216.0
|
lat = float32(raw_lat) * 360.0 / 16777216.0
|
||||||
if lat > 90 {
|
if lat > 90 {
|
||||||
|
@ -583,7 +588,7 @@ func esListen() {
|
||||||
ti.ExtrapolatedPosition = false
|
ti.ExtrapolatedPosition = false
|
||||||
}
|
}
|
||||||
|
|
||||||
ti.SignalLevel = int32(newTi.SignalLevel)
|
ti.SignalLevel = 10 * math.Log10(newTi.SignalLevel)
|
||||||
|
|
||||||
// generate human readable summary of message types for debug
|
// generate human readable summary of message types for debug
|
||||||
// TO-DO: Use for ES message statistics?
|
// TO-DO: Use for ES message statistics?
|
||||||
|
@ -814,9 +819,9 @@ and speed invalid flag is set for headings 135-150 to allow testing of response
|
||||||
func updateDemoTraffic(icao uint32, tail string, relAlt float32, gs float64, offset int32) {
|
func updateDemoTraffic(icao uint32, tail string, relAlt float32, gs float64, offset int32) {
|
||||||
var ti TrafficInfo
|
var ti TrafficInfo
|
||||||
|
|
||||||
hdg := float64((int32(stratuxClock.Milliseconds/1000) + offset) % 360)
|
hdg := float64((int32(stratuxClock.Milliseconds/1000)+offset)%720) / 2
|
||||||
// gs := float64(220) // knots
|
// gs := float64(220) // knots
|
||||||
radius := gs * 0.1 / (2 * math.Pi)
|
radius := gs * 0.2 / (2 * math.Pi)
|
||||||
x := radius * math.Cos(hdg*math.Pi/180.0)
|
x := radius * math.Cos(hdg*math.Pi/180.0)
|
||||||
y := radius * math.Sin(hdg*math.Pi/180.0)
|
y := radius * math.Sin(hdg*math.Pi/180.0)
|
||||||
// default traffic location is Oshkosh if GPS not detected
|
// default traffic location is Oshkosh if GPS not detected
|
||||||
|
@ -835,6 +840,17 @@ func updateDemoTraffic(icao uint32, tail string, relAlt float32, gs float64, off
|
||||||
if ti.Addr_type == 1 { //reserved value
|
if ti.Addr_type == 1 { //reserved value
|
||||||
ti.Addr_type = 0
|
ti.Addr_type = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ti.Addr_type == 0 {
|
||||||
|
ti.TargetType = TARGET_TYPE_ADSB
|
||||||
|
}
|
||||||
|
if ti.Addr_type == 2 {
|
||||||
|
ti.TargetType = TARGET_TYPE_ADSR
|
||||||
|
}
|
||||||
|
if ti.Addr_type == 3 {
|
||||||
|
ti.TargetType = TARGET_TYPE_TISB
|
||||||
|
}
|
||||||
|
|
||||||
ti.Emitter_category = 1
|
ti.Emitter_category = 1
|
||||||
ti.Lat = float32(lat + traffRelLat)
|
ti.Lat = float32(lat + traffRelLat)
|
||||||
ti.Lng = float32(lng + traffRelLng)
|
ti.Lng = float32(lng + traffRelLng)
|
||||||
|
@ -857,13 +873,12 @@ func updateDemoTraffic(icao uint32, tail string, relAlt float32, gs float64, off
|
||||||
ti.Last_seen = stratuxClock.Time
|
ti.Last_seen = stratuxClock.Time
|
||||||
ti.Last_alt = stratuxClock.Time
|
ti.Last_alt = stratuxClock.Time
|
||||||
ti.Last_speed = stratuxClock.Time
|
ti.Last_speed = stratuxClock.Time
|
||||||
ti.TargetType = TARGET_TYPE_ADSB
|
|
||||||
ti.NACp = 8
|
ti.NACp = 8
|
||||||
ti.NIC = 8
|
ti.NIC = 8
|
||||||
|
|
||||||
//ti.Age = math.Floor(ti.Age) + hdg / 1000
|
//ti.Age = math.Floor(ti.Age) + hdg / 1000
|
||||||
ti.Last_source = 1
|
ti.Last_source = 1
|
||||||
if icao%7 == 1 { // make some of the traffic look like it came from UAT
|
if icao%5 == 1 { // make some of the traffic look like it came from UAT
|
||||||
ti.Last_source = 2
|
ti.Last_source = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,7 +160,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.traffic-style12,
|
.traffic-style12,
|
||||||
.traffic-style13 {
|
.traffic-style13,
|
||||||
|
.traffic-style14 {
|
||||||
color: #000000;
|
color: #000000;
|
||||||
background-color: skyblue;
|
background-color: skyblue;
|
||||||
}
|
}
|
||||||
|
@ -174,7 +175,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.traffic-style22,
|
.traffic-style22,
|
||||||
.traffic-style23 {
|
.traffic-style23,
|
||||||
|
.traffic-style24 {
|
||||||
color: #000000;
|
color: #000000;
|
||||||
background-color: khaki
|
background-color: khaki
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,9 @@ function TowersCtrl($rootScope, $scope, $state, $http, $interval) {
|
||||||
function setTower(obj, new_tower) {
|
function setTower(obj, new_tower) {
|
||||||
new_tower.lat = dmsString(obj.Lat);
|
new_tower.lat = dmsString(obj.Lat);
|
||||||
new_tower.lon = dmsString(obj.Lng);
|
new_tower.lon = dmsString(obj.Lng);
|
||||||
new_tower.signal = obj.Signal_strength_last_minute;
|
new_tower.power = obj.Signal_strength_now.toFixed(2);
|
||||||
// Signal_strength_max int
|
new_tower.power_last_min = obj.Signal_strength_last_minute.toFixed(2);
|
||||||
|
new_tower.power_max = obj.Signal_strength_max.toFixed(2);
|
||||||
// Messages_last_minute uint64
|
// Messages_last_minute uint64
|
||||||
new_tower.messages = obj.Messages_total;
|
new_tower.messages = obj.Messages_total;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +58,7 @@ function TowersCtrl($rootScope, $scope, $state, $http, $interval) {
|
||||||
var updateTowers = $interval(function () {
|
var updateTowers = $interval(function () {
|
||||||
// refresh tower list once every 5 seconds (aka polling)
|
// refresh tower list once every 5 seconds (aka polling)
|
||||||
getTowers();
|
getTowers();
|
||||||
}, (5 * 1000), 0, false);
|
}, (2 * 1000), 0, false);
|
||||||
|
|
||||||
$state.get('towers').onEnter = function () {
|
$state.get('towers').onEnter = function () {
|
||||||
// everything gets handled correctly by the controller
|
// everything gets handled correctly by the controller
|
||||||
|
|
|
@ -35,10 +35,11 @@ function TrafficCtrl($rootScope, $scope, $state, $http, $interval) {
|
||||||
|
|
||||||
function setAircraft(obj, new_traffic) {
|
function setAircraft(obj, new_traffic) {
|
||||||
new_traffic.icao_int = obj.Icao_addr;
|
new_traffic.icao_int = obj.Icao_addr;
|
||||||
new_traffic.addr_type = obj.Addr_type;
|
new_traffic.targettype = obj.TargetType;
|
||||||
|
new_traffic.signal = obj.SignalLevel.toFixed(2);
|
||||||
new_traffic.addr_symb ='\u2708';
|
new_traffic.addr_symb ='\u2708';
|
||||||
if (new_traffic.addr_type > 1) {
|
if (new_traffic.targettype > 3) {
|
||||||
new_traffic.addr_symb ='\u{1F4E1}';
|
new_traffic.addr_symb ='\ud83d\udce1';
|
||||||
}
|
}
|
||||||
new_traffic.icao = obj.Icao_addr.toString(16).toUpperCase();
|
new_traffic.icao = obj.Icao_addr.toString(16).toUpperCase();
|
||||||
new_traffic.tail = obj.Tail;
|
new_traffic.tail = obj.Tail;
|
||||||
|
|
|
@ -7,16 +7,20 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body towers-page">
|
<div class="panel-body towers-page">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<span class="col-xs-6"><strong>Location</strong></span>
|
<span class="col-xs-3"><strong>Location</strong></span>
|
||||||
<span class="col-xs-3 text-right">Signal</span>
|
<span class="col-xs-2 text-right">Current Power (dB)</span>
|
||||||
<span class="col-xs-3 text-right">Msgs</span>
|
<span class="col-xs-2 text-right">Avg Power (dB)</span>
|
||||||
|
<span class="col-xs-2 text-right">Max Power (dB)</span>
|
||||||
|
<span class="col-xs-2 text-right">Msgs Last Minute</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row" ng-repeat="tower in data_list | orderBy: messages">
|
<div class="row" ng-repeat="tower in data_list | orderBy: messages">
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
<span class="col-xs-6">{{tower.lat}} {{tower.lon}}</span>
|
<span class="col-xs-3">{{tower.lat}} {{tower.lon}}</span>
|
||||||
<span class="col-xs-3 text-right">{{tower.signal}}</span>
|
<span class="col-xs-2 text-right">{{tower.power}}</span>
|
||||||
<span class="col-xs-3 text-right">{{tower.messages}}</span>
|
<span class="col-xs-2 text-right">{{tower.power_last_min}}</span>
|
||||||
|
<span class="col-xs-2 text-right">{{tower.power_max}}</span>
|
||||||
|
<span class="col-xs-2 text-right">{{tower.messages}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,25 +7,26 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body traffic-page">
|
<div class="panel-body traffic-page">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-5">
|
||||||
<span class="col-xs-3"><strong>Flight</strong></span>
|
<span class="col-xs-3"><strong>Flight</strong></span>
|
||||||
<span class="col-xs-3 text-right">Speed</span>
|
<span class="col-xs-3 text-right">Speed</span>
|
||||||
<span class="col-xs-3 text-right">Altitude</span><span class="col-xs-1 col-padding-shift-right"> </span>
|
<span class="col-xs-3 text-right">Altitude</span><span class="col-xs-1 col-padding-shift-right"> </span>
|
||||||
<span class="col-xs-2 text-right">Course</span>
|
<span class="col-xs-2 text-right">Course</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-7">
|
||||||
<span class="col-xs-2"> </span>
|
<span class="col-xs-2"> </span>
|
||||||
<span class="col-xs-7">Location</span>
|
<span class="col-xs-5">Location</span>
|
||||||
<span class="col-xs-3 text-right">Age</span>
|
<span class="col-xs-2">Power (dB)</span>
|
||||||
|
<span class="col-xs-2 text-right">Age</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row" ng-repeat="aircraft in data_list | orderBy: -age">
|
<div class="row" ng-repeat="aircraft in data_list | orderBy: -age">
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-5">
|
||||||
<span class="col-xs-3">
|
<span class="col-xs-3">
|
||||||
<span ng-show="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.addr_type"><strong>{{aircraft.addr_symb}} {{aircraft.tail}}</strong></span>
|
<span ng-show="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype"><strong>{{aircraft.addr_symb}} {{aircraft.tail}}</strong></span>
|
||||||
<span ng-hide="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.addr_type"><strong class="text-muted">{{aircraft.addr_symb}} {{aircraft.icao}}</strong></span>
|
<span ng-hide="aircraft.tail" ng-class="'label traffic-style'+aircraft.src+aircraft.targettype"><strong class="text-muted">{{aircraft.addr_symb}} {{aircraft.icao}}</strong></span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="col-xs-3 text-right">{{aircraft.speed}} KTS</span>
|
<span class="col-xs-3 text-right">{{aircraft.speed}} KTS</span>
|
||||||
|
@ -36,11 +37,12 @@
|
||||||
</span>
|
</span>
|
||||||
<span class="col-xs-2 text-right"><span ng-show="aircraft.heading < 10">0</span><span ng-show="aircraft.heading < 100">0</span>{{aircraft.heading}}°</span>
|
<span class="col-xs-2 text-right"><span ng-show="aircraft.heading < 10">0</span><span ng-show="aircraft.heading < 100">0</span>{{aircraft.heading}}°</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-7">
|
||||||
<span class="col-xs-2"> </span>
|
<span class="col-xs-2"> </span>
|
||||||
<span class="col-xs-7">{{aircraft.lat}} {{aircraft.lon}}</span>
|
<span class="col-xs-5">{{aircraft.lat}} {{aircraft.lon}}</span>
|
||||||
|
<span class="col-xs-2">{{aircraft.signal}}</span>
|
||||||
<!--<span class="col-xs-3 text-right">{{aircraft.time}}</span>-->
|
<!--<span class="col-xs-3 text-right">{{aircraft.time}}</span>-->
|
||||||
<span class="col-xs-3 text-right">{{aircraft.age}}s</span>
|
<span class="col-xs-2 text-right">{{aircraft.age}}s</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Ładowanie…
Reference in New Issue