Reduce SQLite traffic to 1/sec. Backend improvements from gpsattitude branch

pull/390/head
AvSquirrel 2016-04-13 03:41:08 +00:00
rodzic c8ad41c8bc
commit d407c513c9
1 zmienionych plików z 112 dodań i 27 usunięć

Wyświetl plik

@ -81,6 +81,7 @@ type TrafficInfo struct {
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
SignalLevel float64 // Signal level, dB RSSI.
Squawk int // Squawk code
Position_valid bool // set when position report received. Unset after n seconds? (To-do)
Lat float32 // decimal degrees, north positive
Lng float32 // decimal degrees, east positive
@ -98,7 +99,8 @@ type TrafficInfo struct {
// Parameters starting at 'Age' are calculated after message receipt.
// Mode S transmits position and track in separate messages, and altitude can also be
// received from interrogations.
Age float64 // seconds ago traffic last seen
Age float64 // Age of last valid position fix, seconds ago.
AgeLastAlt float64 // Age of last altitude message, seconds ago.
Last_seen time.Time // time of last position update, relative to Stratux startup. Used for timing out expired data.
Last_alt time.Time // time of last altitude update, relative to Stratux startup
Last_GnssDiff time.Time // time of last GnssDiffFromBaroAlt update, relative to Stratux startup
@ -158,6 +160,17 @@ func sendTrafficUpdates() {
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.
/*
if isGPSValid() {
// func distRect(lat1, lon1, lat2, lon2 float64) (dist, bearing, distN, distE float64) {
dist, bearing := distance(float64(mySituation.Lat), float64(mySituation.Lng), float64(ti.Lat), float64(ti.Lng))
ti.Distance = dist
ti.Bearing = bearing
}
*/
ti.Age = stratuxClock.Since(ti.Last_seen).Seconds()
ti.AgeLastAlt = stratuxClock.Since(ti.Last_alt).Seconds()
logTraffic(ti)
// DEBUG: Print the list of all tracked targets (with data) to the log every 15 seconds if "DEBUG" option is enabled
if globalSettings.DEBUG && (stratuxClock.Time.Second()%15) == 0 {
@ -169,8 +182,7 @@ func sendTrafficUpdates() {
}
// end of debug block
}
ti.Age = stratuxClock.Since(ti.Last_seen).Seconds()
traffic[icao] = ti
traffic[icao] = ti // write the updated ti back to the map
//log.Printf("Traffic age of %X is %f seconds\n",icao,ti.Age)
if ti.Age > 2 { // if nothing polls an inactive ti, it won't push to the webUI, and its Age won't update.
tiJSON, _ := json.Marshal(&ti)
@ -188,11 +200,12 @@ func sendTrafficUpdates() {
// Send update to attached JSON client.
func registerTrafficUpdate(ti TrafficInfo) {
logTraffic(ti)
if !ti.Position_valid { // Don't send unless a valid position exists.
return
}
//logTraffic(ti)
/*
if !ti.Position_valid { // Don't send unless a valid position exists.
return
}
*/ // Send all traffic to the websocket and let JS sort it out. This will provide user indication of why they see 1000 ES messages and no traffic.
tiJSON, _ := json.Marshal(&ti)
trafficUpdate.Send(tiJSON)
}
@ -289,7 +302,7 @@ func makeTrafficReportMsg(ti TrafficInfo) []byte {
// msg[19] to msg[26] are "call sign" (tail).
for i := 0; i < len(ti.Tail) && i < 8; i++ {
c := byte(ti.Tail[i])
if c != 20 && !((c >= 48) && (c <= 57)) && !((c >= 65) && (c <= 90)) && c != 'e' && c != 'u' { // See p.24, FAA ref.
if c != 20 && !((c >= 48) && (c <= 57)) && !((c >= 65) && (c <= 90)) && c != 'e' && c != 'u' && c != 'a' && c != 'r' && c != 't' { // See p.24, FAA ref.
c = byte(20)
}
msg[19+i] = c
@ -347,13 +360,6 @@ func parseDownlinkReport(s string, signalLevel int) {
ti.Tail = tail
}
if globalSettings.DEBUG {
// This is a hack to show the source of the traffic in ForeFlight.
if len(ti.Tail) == 0 || (len(ti.Tail) != 0 && len(ti.Tail) < 8 && ti.Tail[0] != 'U') {
ti.Tail = "u" + ti.Tail
}
}
// Extract emitter category.
if msg_type == 1 || msg_type == 3 {
v := (uint16(frame[17]) << 8) | (uint16(frame[18]))
@ -388,6 +394,28 @@ func parseDownlinkReport(s string, signalLevel int) {
}
}
// This is a hack to show the source of the traffic on moving maps.
if globalSettings.DEBUG {
type_code := " "
switch ti.TargetType {
case TARGET_TYPE_ADSB:
type_code = "a"
case TARGET_TYPE_ADSR, TARGET_TYPE_TISB_S:
type_code = "r"
case TARGET_TYPE_TISB:
type_code = "t"
}
if len(ti.Tail) == 0 {
ti.Tail = "u" + type_code
} else if len(ti.Tail) < 7 && ti.Tail[0] != 'e' && ti.Tail[0] != 'u' {
ti.Tail = "u" + type_code + ti.Tail
} else if len(ti.Tail) == 7 && ti.Tail[0] != 'e' && ti.Tail[0] != 'u' {
ti.Tail = "u" + type_code + ti.Tail[1:]
} else if len(ti.Tail) > 1 { // bounds checking
ti.Tail = "u" + type_code + ti.Tail[2:]
}
}
raw_lat := (uint32(frame[4]) << 15) | (uint32(frame[5]) << 7) | (uint32(frame[6]) >> 1)
raw_lon := ((uint32(frame[6]) & 0x01) << 23) | (uint32(frame[7]) << 15) | (uint32(frame[8]) << 7) | (uint32(frame[9]) >> 1)
@ -406,10 +434,15 @@ func parseDownlinkReport(s string, signalLevel int) {
lng = lng - 360
}
}
ti.Lat = lat
ti.Lng = lng
ti.Position_valid = position_valid
if ti.Position_valid {
ti.Lat = lat
ti.Lng = lng
/*
if isGPSValid() {
ti.Distance, ti.Bearing = distance(float64(mySituation.Lat), float64(mySituation.Lng), float64(ti.Lat), float64(ti.Lng))
}
*/ // to-do
ti.Last_seen = stratuxClock.Time
ti.ExtrapolatedPosition = false
}
@ -572,11 +605,17 @@ func esListen() {
continue
}
if globalSettings.DEBUG && (newTi.Icao_addr&0xFF000000) != 0 { //24-bit overflow is used to signal heartbeat
if globalSettings.DEBUG && (newTi.Icao_addr == 0x07FFFFFF) { // used to signal heartbeat
log.Printf("No traffic last 60 seconds. Heartbeat message from dump1090: %s\n", buf)
continue
}
if (newTi.Icao_addr & 0x01000000) != 0 { // bit 25 used by dump1090 to signal non-ICAO address
newTi.Icao_addr = newTi.Icao_addr & 0x00FFFFFF
if globalSettings.DEBUG {
log.Printf("Non-ICAO address %X sent by dump1090. This is typical for TIS-B.\n", newTi.Icao_addr)
}
}
icao := uint32(newTi.Icao_addr)
var ti TrafficInfo
@ -589,8 +628,10 @@ func esListen() {
} else {
//log.Printf("New target %X created for ES update\n",newTi.Icao_addr)
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.Last_alt = stratuxClock.Time // ditto.
ti.Icao_addr = icao
ti.ExtrapolatedPosition = false
ti.Last_source = TRAFFIC_SOURCE_1090ES
}
ti.SignalLevel = 10 * math.Log10(newTi.SignalLevel)
@ -666,6 +707,11 @@ func esListen() {
if valid_position {
ti.Lat = lat
ti.Lng = lng
/*
if isGPSValid() {
ti.Distance, ti.Bearing = distance(float64(mySituation.Lat), float64(mySituation.Lng), float64(ti.Lat), float64(ti.Lng))
}
*/ // todo
ti.Position_valid = true
ti.ExtrapolatedPosition = false
ti.Last_seen = stratuxClock.Time // only update "last seen" data on position updates
@ -754,6 +800,9 @@ func esListen() {
ti.Emitter_category = uint8(*newTi.Emitter_category) // validate dump1090 on live traffic
}
if newTi.Squawk != nil {
ti.Squawk = int(*newTi.Squawk) // only provided by Mode S messages, so we don't do this in parseUAT.
}
// Set the target type. DF=18 messages are sent by ground station, so we look at CA
// (repurposed to Control Field in DF18) to determine if it's ADS-R or TIS-B.
if newTi.DF == 17 {
@ -776,19 +825,41 @@ func esListen() {
ti.OnGround = bool(*newTi.OnGround)
}
if newTi.Tail != nil { // DF=17 or DF=18, Type Code 1-4
if (newTi.Tail != nil) && ((newTi.DF == 17) || (newTi.DF == 18)) { // DF=17 or DF=18, Type Code 1-4
ti.Tail = *newTi.Tail
// This is a hack to show the source of the traffic in ForeFlight.
ti.Tail = strings.Trim(ti.Tail, " ")
if globalSettings.DEBUG {
if len(ti.Tail) == 0 || (len(ti.Tail) != 0 && len(ti.Tail) < 8 && ti.Tail[0] != 'E') {
ti.Tail = "e" + ti.Tail
}
ti.Tail = strings.Trim(ti.Tail, " ") // remove extraneous spaces
}
// This is a hack to show the source of the traffic on moving maps.
if globalSettings.DEBUG {
type_code := " "
switch ti.TargetType {
case TARGET_TYPE_ADSB:
type_code = "a"
case TARGET_TYPE_ADSR:
type_code = "r"
case TARGET_TYPE_TISB:
type_code = "t"
}
if len(ti.Tail) == 0 {
ti.Tail = "e" + type_code
} else if len(ti.Tail) < 7 && ti.Tail[0] != 'e' && ti.Tail[0] != 'u' {
ti.Tail = "e" + type_code + ti.Tail
} else if len(ti.Tail) == 7 && ti.Tail[0] != 'e' && ti.Tail[0] != 'u' {
ti.Tail = "e" + type_code + ti.Tail[1:]
} else if len(ti.Tail) > 1 { // bounds checking
ti.Tail = "e" + type_code + ti.Tail[2:]
}
}
if newTi.DF == 17 || newTi.DF == 18 {
ti.Last_source = TRAFFIC_SOURCE_1090ES // only update traffic source on ADS-B messages. Prevents source on UAT ADS-B targets with Mode S transponders from "flickering" every time we get an altitude or DF11 update.
}
ti.Timestamp = newTi.Timestamp // only update "last seen" data on position updates
ti.Last_source = TRAFFIC_SOURCE_1090ES
/*
s_out, err := json.Marshal(ti)
if err != nil {
@ -824,6 +895,16 @@ 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) {
var ti TrafficInfo
// Retrieve previous information on this ICAO code.
if val, ok := traffic[icao]; ok { // if we've already seen it, copy it in to do updates
ti = val
//log.Printf("Existing target %X imported for ES update\n", icao)
} else {
//log.Printf("New target %X created for ES update\n",newTi.Icao_addr)
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
ti.ExtrapolatedPosition = false
}
hdg := float64((int32(stratuxClock.Milliseconds/1000)+offset)%720) / 2
// gs := float64(220) // knots
radius := gs * 0.2 / (2 * math.Pi)
@ -862,6 +943,10 @@ func updateDemoTraffic(icao uint32, tail string, relAlt float32, gs float64, off
ti.Emitter_category = 1
ti.Lat = float32(lat + traffRelLat)
ti.Lng = float32(lng + traffRelLng)
/*
ti.Distance, ti.Bearing = distance(float64(lat), float64(lng), float64(ti.Lat), float64(ti.Lng))
*/ // todo
ti.Position_valid = true
ti.ExtrapolatedPosition = false
ti.Alt = int32(mySituation.Alt + relAlt)