func RestoreContactsTable(input *db.RecordReader, output *db.ContactDB) error { for { rec, err := input.ReadRecord() if err == io.EOF { break } else if err != nil { log.Printf("Error reading record: %s", err.Error()) return err } c := &pb.Contact{} err = proto.Unmarshal(rec, c) if err != nil { log.Printf("Error parsing record: %s", err.Error()) return err } err = output.Store(c) if err != nil { log.Printf("Error writing record: %s", err.Error()) return err } fmt.Printf(".") } fmt.Printf("\n") log.Printf("Contacts table restored.") return nil }
// Consider moving this to a completely different worker binary. func processNewIQData(contact_id string, contactdb *db.ContactDB) { log.Printf("%s: Processing IQ data", contact_id) contact, err := contactdb.Lookup(contact_id) if err != nil { log.Printf("%s: Error looking up contact: %s", contact_id, err.Error()) return } if contact == nil { log.Printf("%s: Contact not found.", contact_id) return } // Get IQParams from the contact. var iq_params *pb.IQParams for _, b := range contact.Blob { if b.Format != nil && *b.Format == pb.Contact_Blob_IQ { if b.IqParams != nil { iq_params = b.IqParams } } } if iq_params == nil { log.Printf("%s: IQ blob missing", contact_id) return } local_path := fmt.Sprintf("%s/%s", *stream_tmp_dir, contact_id) png_path := fmt.Sprintf("%s.png", local_path) demod.Spectrogram(local_path, *iq_params, png_path, demod.SpectrogramTitle(*contact, *iq_params)) if contact.SatelliteId != nil { blobs := processIQDataForSatellite( *contact.SatelliteId, local_path, *iq_params, *contact.StartTimestamp) contact.Blob = append(contact.Blob, blobs...) } log.Printf("%s: Storing updated contact: %v", contact_id, contact.Blob) // TODO: Need to be careful about locking the ContactDB record. // Currently we are the only process that modifies an existing ContactDB // record. In the future we may need to be more careful. if err := contactdb.Store(contact); err != nil { log.Printf("%s: Error storing contact: %s", contact_id, err.Error()) return } log.Printf("%s: Wrote updated contact to db.", contact_id) }
func RedecodeContact(contactdb *db.ContactDB, c *pb.Contact) { if c == nil { log.Fatalf("Contact not found") } log.Printf("Original contact:\n%s\n", proto.MarshalTextString(c)) new_blobs := make([]*pb.Contact_Blob, 0) var freeform []byte for _, b := range c.Blob { if b.Format != nil && (*b.Format == pb.Contact_Blob_DATUM || *b.Format == pb.Contact_Blob_FRAME) { // Strip out datums and frames. continue } new_blobs = append(new_blobs, b) if b.Format != nil && *b.Format == pb.Contact_Blob_FREEFORM { if freeform != nil { log.Fatalf("Contact contains multiple FREEFORM blobs.") } freeform = b.InlineData } } if freeform == nil { return } data, frames := telemetry.DecodeFreeform( *c.SatelliteId, freeform, *c.StartTimestamp) for i, _ := range frames { b := new(pb.Contact_Blob) b.Format = pb.Contact_Blob_FRAME.Enum() b.InlineData = frames[i] new_blobs = append(new_blobs, b) } for i, _ := range data { b := new(pb.Contact_Blob) b.Format = pb.Contact_Blob_DATUM.Enum() b.Datum = &data[i] new_blobs = append(new_blobs, b) } c.Blob = new_blobs log.Printf("New contact:\n%s\n", proto.MarshalTextString(c)) err := contactdb.Store(c) if err != nil { log.Fatalf("Error storing contact: %s", err.Error()) } }
// satellite_id can be empty if unknown func StartNewConsoleContact(stationdb *db.StationDB, contactdb *db.ContactDB, station_id, user_id, satellite_id string) ( id string, err error) { station, err := stationdb.Lookup(station_id) if err != nil { return "", err } if station == nil { return "", errors.New( fmt.Sprintf("Unknown station: %s", station_id)) } s, err := NewContact(station, user_id, &satellite_id) if err != nil { return "", err } if err = contactdb.Store(s); err != nil { return "", err } return *s.Id, nil }
func postPacketHandler( sdb *db.StationDB, cdb *db.ContactDB, w http.ResponseWriter, r *http.Request) { data, err := ioutil.ReadAll(r.Body) r.Body.Close() if err != nil { log.Printf("postPacketHandler: Error reading post body: %s", err.Error()) http.Error(w, "Error reading post body", http.StatusInternalServerError) return } var req PostPacketRequest if err := json.Unmarshal(data, &req); err != nil { log.Printf("postPacketHandler: JSON decode error: %s", err.Error()) http.Error(w, "Error decoding JSON data.", http.StatusBadRequest) return } log.Printf("request: %v", req) frame, err := base64.StdEncoding.DecodeString(req.FrameBase64) if err != nil { log.Printf("postPacketHandler: base64 decode error: %s", err.Error()) http.Error(w, "Error decoding base64 frame.", http.StatusBadRequest) return } if req.StationId == "" { http.Error(w, "Missing station_id", http.StatusBadRequest) return } station, err := sdb.Lookup(req.StationId) if err != nil { log.Printf("Error looking up station: %s", err.Error()) http.Error(w, "", http.StatusInternalServerError) return } contact, poperr := contacts.PopulateContact( req.SatelliteId, req.Timestamp, req.Format, frame, "", req.StationSecret, station) if poperr != nil { poperr.HttpError(w) return } log.Printf("Storing contact: %s", contact) err = cdb.Store(contact) if err != nil { log.Printf("Error storing contact: %s", err.Error()) http.Error(w, "", http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) // Do we need to set content-length? }
// blocking func capturePass( contactdb *db.ContactDB, mux_client *rpc.Client, station pb.Station, pass Prediction) error { log_label := *station.Id satellite_id := *pass.Satellite.Id duration := Duration(pass.EndTimestamp - pass.StartTimestamp) freq_hz := (int64)(*pass.CompatibleMode.channel.FrequencyHz) lateness := (float64)(time.Now().Unix()) - pass.StartTimestamp const kMotorProgramResolution = 10 points, err := PassDetails( time.Now(), duration, *station.Lat, *station.Lng, *station.Elevation, *pass.Satellite.Tle, kMotorProgramResolution) if err != nil { log.Printf("%s: Error getting pass details: %s", log_label, err.Error()) return err } motor_program := make([]mux.MotorCoordinate, len(points)) for i, p := range points { motor_program[i].Timestamp = p.Timestamp motor_program[i].AzimuthDegrees = p.AzimuthDegrees motor_program[i].AltitudeDegrees = p.AltitudeDegrees } log.Printf("%s: Starting capture: satellite %s, "+ "duration: %s, freq_hz: %d, lateness: %f [s]", log_label, satellite_id, duration, freq_hz, lateness) log.Printf("%s: motor_program: %v", log_label, motor_program) // FIXME: future: acquire lock log.Printf("%s: 1", log_label) contact, err := contacts.NewContact( &station, *station.Userid, &satellite_id) if err != nil { log.Printf("%s: Error creating contact: %s", log_label, err.Error()) return err } log_label = *station.Id + "/" + *contact.Id log.Printf("%s: Contact id: %s", log_label, *contact.Id) log.Printf("%s: 2", log_label) err = mux.StationReceiverSetFrequency(mux_client, *station.Id, freq_hz) if err != nil { log.Printf("%s: StationReceiverSetFrequency failed: %s", log_label, err.Error()) return err } log.Printf("%s: 3", log_label) err = contactdb.Store(contact) if err != nil { log.Printf("%s: Error storing contact: %s", log_label, err.Error()) return err } log.Printf("%s: 4", log_label) stream_url := GetStreamURL(*contact.Id) err = mux.StationReceiverStart(mux_client, *station.Id, stream_url) if err != nil { log.Printf("%s: StationReceiverStart failed: %s", log_label, err.Error()) //return err } // Stop the TNC in case it's already started. err = mux.StationTNCStop(mux_client, *station.Id) if err != nil { log.Printf("%s: StationTNCStop failed: %s", log_label, err.Error()) } err = mux.StationTNCStart( mux_client, *station.Id, *api_server_address, satellite_id) if err != nil { log.Printf("%s: StationTNCStart failed: %s", log_label, err.Error()) } log.Printf("%s: 5 StationMotorStart len=%d", log_label, len(motor_program)) err = mux.StationMotorStart(mux_client, *station.Id, motor_program) if err != nil { log.Printf("%s: StationMotorStart failed: %s", log_label, err.Error()) } log.Printf("%s: 6", log_label) time.Sleep(duration) log.Printf("%s: 7", log_label) err = mux.StationTNCStop(mux_client, *station.Id) if err != nil { log.Printf("%s: StationTNCStop failed: %s", log_label, err.Error()) } err = mux.StationReceiverStop(mux_client, *station.Id) if err != nil { log.Printf("%s: StationReceiverStop failed: %s", log_label, err.Error()) } err = mux.StationMotorStop(mux_client, *station.Id) if err != nil { log.Printf("%s: StationMotorStop failed: %s", log_label, err.Error()) } // FIXME: send end timestamp and update contact now := time.Now().Unix() contact.EndTimestamp = &now // FIXME: future: release lock return nil }
func satellitePostContactHandler( sdb *db.StationDB, cdb *db.ContactDB, w http.ResponseWriter, r *http.Request, user userView) { if r.Method != "POST" { http.Redirect(w, r, satelliteListUrl, http.StatusFound) return } if err := r.ParseForm(); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } log.Printf("satellitePostContactHandler form: %v\n\n", r.Form) satellite_id := r.Form.Get("satellite_id") if satellite_id == "" { http.Error(w, "Missing satellite id", http.StatusBadRequest) return } sat := db.GlobalSatelliteDB().Map[satellite_id] if sat == nil { http.Error(w, "Unknown satellite id", http.StatusBadRequest) return } timestamp, err := strconv.ParseInt(r.Form.Get("timestamp"), 10, 64) if err != nil { http.Error(w, "Can't parse timestamp.", http.StatusBadRequest) return } data := r.Form.Get("data") frame := ([]byte)(data) var station *pb.Station // There are two options: logged-in or anonymous. if user.Id == "" { // Anonymous station = nil } else { // Logged-in user station_id := r.Form.Get("station_id") if station_id == "" { http.Error( w, "Missing station id", http.StatusBadRequest) return } station, err = sdb.Lookup(station_id) if err != nil { log.Printf("Error looking up station: %s", err.Error()) http.Error(w, "", http.StatusInternalServerError) return } } contact, poperr := contacts.PopulateContact( satellite_id, timestamp, "FREEFORM", frame, user.Id, "", station) if poperr != nil { poperr.HttpError(w) return } log.Printf("Contact: %s", contact) err = cdb.Store(contact) if err != nil { log.Printf("Error storing contact: %s", err.Error()) http.Error(w, "", http.StatusInternalServerError) return } var cc contactConfirmContext cc.SatelliteUrl = satelliteViewURL(*sat.Id) cc.SatelliteName = RenderSatelliteName(sat.Name) cc.Data = data if sat.Schema != nil { t := make([]pb.TelemetryDatum, 0) for _, b := range contact.Blob { if b.Format != nil && *b.Format == pb.Contact_Blob_DATUM { t = append(t, *b.Datum) } } cc.Telemetry = fe_telemetry.RenderTelemetry( *sat.Schema, t, "en") } err = contactConfirmTemplate.Get().ExecuteTemplate( w, "contact_confirm.html", NewRenderContext(user, cc)) if err != nil { log.Printf( "Error rendering contact_confirm view: %s", err.Error()) http.Error(w, "", http.StatusInternalServerError) return } }