// Look for new flights that we should add to our database. Invoked by cron. func scanHandler(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) if db, err1 := fdb24.NewFlightDBFr24(urlfetch.Client(c)); err1 != nil { c.Errorf(" /mdb/scan: newdb: %v", err1) http.Error(w, err1.Error(), http.StatusInternalServerError) } else { if flights, err2 := db.LookupList(sfo.KBoxSFO120K); err2 != nil { c.Errorf(" /mdb/scan: lookup: %v", err2) http.Error(w, err2.Error(), http.StatusInternalServerError) } else { set := ftype.FIFOSet{} if err3 := loadFIFOSet(c, &set); err3 != nil { c.Errorf(" /mdb/scan: loadcache: %v", err3) http.Error(w, err3.Error(), http.StatusInternalServerError) } new := set.FindNew(flights) if err4 := saveFIFOSet(c, set); err4 != nil { c.Errorf(" /mdb/scan: savecache: %v", err4) http.Error(w, err4.Error(), http.StatusInternalServerError) } // Enqueue the new flights n := 1000 for i, fs := range new { if i >= n { break } if fsStr, err5 := fs.Base64Encode(); err5 != nil { http.Error(w, err5.Error(), http.StatusInternalServerError) return } else { url := fmt.Sprintf("/fdb/addflight?deb=%s", fs.F.UniqueIdentifier()) t := taskqueue.NewPOSTTask(url, map[string][]string{ "flightsnapshot": {fsStr}, }) // We could be smarter about this. t.Delay = time.Minute * 45 if _, err6 := taskqueue.Add(c, t, "addflight"); err6 != nil { c.Errorf(" /mdb/scan: enqueue: %v", err6) http.Error(w, err6.Error(), http.StatusInternalServerError) return } } } var params = map[string]interface{}{ "New": new, "Flights": flights, } if err7 := templates.ExecuteTemplate(w, "fdb-scan", params); err7 != nil { http.Error(w, err7.Error(), http.StatusInternalServerError) } } } }
func addflightHandler(w http.ResponseWriter, r *http.Request) { ctx := req2ctx(r) client := req2client(r) logstr := fmt.Sprintf("* addFlightHandler invoked: %s\n", time.Now().UTC()) fsStr := r.FormValue("flightsnapshot") fs := ftype.FlightSnapshot{} if err := fs.Base64Decode(fsStr); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } fr24Id := fs.F.Id.ForeignKeys["fr24"] // This is the only field we take from the logstr += fmt.Sprintf("* fr24 key: %s\n", fr24Id) db := fdb.NewDB(r) fr24db, err := fdb24.NewFlightDBFr24(client) if err != nil { log.Errorf(ctx, " /mdb/addflight: newdb: %v", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } // Be idempotent - check to see if this flight has already been recorded /* Can't do this check now; the fs.F.Id we cached might be different from the * f.Id we get back from LookupPlayback(), because fr24 reuse their keys. * if exists,err := db.FlightExists(fs.F.Id.UniqueIdentifier()); err != nil { c.Errorf(" /mdb/addflight: FlightExists check failed: %v", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } else if exists { c.Infof(" /mdb/addflight: already exists %s", fs) w.Write([]byte(fmt.Sprintf("Skipped %s\n", fs))) return } logstr += fmt.Sprintf("* FlightExists('%s') -> false\n", fs.F.Id.UniqueIdentifier()) */ // Now grab an initial flight (with track), from fr24. var f *ftype.Flight if f, err = fr24db.LookupPlayback(fr24Id); err != nil { // c.Errorf(" /mdb/addflight: lookup: %v", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } logstr += fmt.Sprintf("* the fr24/default track has %d points\n", len(f.Track)) // Kludge: fr24 keys get reused, so the flight fr24 thinks it refers to might be // different than when we cached it. So we do the uniqueness check here, to avoid // dupes in the DB. Need a better solution to this. if exists, err := db.FlightExists(f.Id.UniqueIdentifier()); err != nil { log.Errorf(ctx, " /mdb/addflight: FlightExists check failed: %v", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } else if exists { log.Infof(ctx, " /mdb/addflight: already exists %s", *f) w.Write([]byte(fmt.Sprintf("Skipped %s\n", *f))) return } logstr += fmt.Sprintf("* FlightExists('%s') -> false\n", f.Id.UniqueIdentifier()) // Fetch ADSB (and MLAT!) tracks from Skypi, via the new DB err, deb := f.GetV2ADSBTrack(client) logstr += "* fetchV2ADSB\n" + deb if err != nil { log.Errorf(ctx, "ADSB fetch err: %v", err) } // If we have any locally received ADSB fragments for this flight, add them in //if err := db.MaybeAddTrackFragmentsToFlight(f); err != nil { // c.Errorf(" /mdb/addflight: addTrackFrags(%s): %v", f.Id, err) //} f.AnalyseFlightPath() // Takes a coarse look at the flight path logstr += fmt.Sprintf("* Initial tags: %v\n", f.TagList()) // For flights on the SERFR1 or BRIXX1 approaches, fetch a flightaware track if f.HasTag(ftype.KTagSERFR1) || f.HasTag(ftype.KTagBRIXX) { u, p := kFlightawareAPIUsername, kFlightawareAPIKey if err := fdbfa.AddFlightAwareTrack(client, f, u, p); err != nil { log.Errorf(ctx, " /mdb/addflight: addflightaware: %v", err) } } f.Analyse() if err := db.PersistFlight(*f, logstr); err != nil { log.Errorf(ctx, " /mdb/addflight: persist: %v", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } // Success ! w.Write([]byte(fmt.Sprintf("Added %s\n", f))) }