Exemple #1
0
// We tart it up with airframe and schedule data, trim out stale entries, and trim to fit box
func getAirspaceForDisplay(c context.Context, bbox geo.LatlongBox) (airspace.Airspace, error) {
	a := airspace.NewAirspace()
	if err := a.JustAircraftFromMemcache(c); err != nil {
		return a, err
	}

	airframes := ref.NewAirframeCache(c)
	schedules := ref.NewScheduleCache(c)
	for k, aircraft := range a.Aircraft {
		age := time.Since(a.Aircraft[k].Msg.GeneratedTimestampUTC)
		if age > kMaxStaleDuration {
			delete(a.Aircraft, k)
			continue
		}
		if !bbox.SW.IsNil() && !bbox.Contains(aircraft.Msg.Position) {
			delete(a.Aircraft, k)
			continue
		}
		if af := airframes.Get(string(k)); af != nil {
			// Update entry in map to include the airframe data we just found
			aircraft.Airframe = *af
			a.Aircraft[k] = aircraft
		}

		if schedules != nil && time.Since(schedules.LastUpdated) < kMaxStaleScheduleDuration {
			if fs := schedules.Get(string(k)); fs != nil {
				aircraft.Schedule = fs.Identity.Schedule
				a.Aircraft[k] = aircraft
			}
		}
	}

	return a, nil
}
Exemple #2
0
// For clients, fetching from a pi/frontend via JSON
func Fetch(client *http.Client, host string, bbox geo.LatlongBox) (*Airspace, error) {
	as := Airspace{}
	if host == "" {
		host = "fdb.serfr1.org"
	}

	url := fmt.Sprintf("http://%s/?json=1&%s", host, bbox.ToCGIArgs("box"))

	if resp, err := client.Get(url); err != nil {
		return nil, err
	} else if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("Bad status: %v", resp.Status)
	} else if err := json.NewDecoder(resp.Body).Decode(&as); err != nil {
		return nil, err
	}

	return &as, nil
}
Exemple #3
0
func (t Track) TimesInBox(b geo.LatlongBox) (s, e time.Time) {
	inside := false

	for _, tp := range t {
		if tp.AltitudeFeet == 0 || tp.SpeedKnots == 0 {
			continue
		}
		if !inside && b.Contains(tp.Latlong) {
			s = tp.TimestampUTC
			inside = true

		} else if inside {
			e = tp.TimestampUTC // keep overwriting e until we're outside (or we've landed)
			if !b.Contains(tp.Latlong) {
				break
			}
		}
	}
	return
}
Exemple #4
0
// WARNING: If we find something, we will annotate the track in-place
func (track Track) LevelFlightAcrossBox(maxAbsDelta float64, box geo.LatlongBox, name string) *LevelFlightEvent {

	iStart, iEnd := 0, 0
	for i, tp := range track {
		if iStart == 0 {
			if box.Contains(tp.Latlong) {
				iStart = i
			}
		} else {
			if !box.Contains(tp.Latlong) {
				iEnd = i - 1
				break
			}
		}
	}
	if iStart == 0 || iEnd == 0 || iStart == iEnd {
		return nil
	}

	ev := LevelFlightEvent{
		Start: track[iStart],
		End:   track[iEnd],
		I:     iStart,
		J:     iEnd,
	}

	if math.Abs(ev.End.AltitudeFeet-ev.Start.AltitudeFeet) > maxAbsDelta {
		return nil
	}

	for i := iStart; i <= iEnd; i++ {
		track[i].X_Annotation = fmt.Sprintf("\n** LEVEL FLIGHT across %s", name)
		track[i].X_MapIcon = "red"
	}

	return &ev
}