Example #1
0
/*
	stopFlightLog() - called every time the system shifts from "flying" state to "taxiing"
	state (or directly to stopped, though that should not happen). Updates the end values
	for the startup record. Appends the stop point airport to the 'route' list, so if
	the aircraft makes multiple stops without powering off the system this will indicate
	all of them.
*/
func stopFlightLog(fullstop bool) {

	// gps coordinates at startup
	flightlog.end_lat = float64(mySituation.Lat)
	flightlog.end_lng = float64(mySituation.Lng)

	// time, timezone, localtime
	flightlog.end_timestamp = stratuxClock.RealTime.Unix()
	flightlog.end_tz = latlong.LookupZoneName(float64(mySituation.Lat), float64(mySituation.Lng))
	loc, err := time.LoadLocation(flightlog.end_tz)
	if err == nil {
		flightlog.end_localtime = mySituation.GPSTime.In(loc).String()
	}

	// airport code and name
	apt, err := findAirport(float64(mySituation.Lat), float64(mySituation.Lng))
	if err == nil {
		flightlog.end_airport_id = apt.faaId
		flightlog.end_airport_name = apt.name
		flightlog.route = flightlog.route + " => " + apt.faaId
		if fullstop == false {
			flightlog.route = flightlog.route + " (t/g)"
		}
	}

	//create a landing record in the event log table
	if fullstop == false {
		addFlightEvent("Landing (T/G)")
	} else {
		addFlightEvent("Landing")
	}

	// update the database entry
	dataUpdateChan <- true
}
Example #2
0
/*
	startFlightLog() - called once per startup when the GPS has a valid timestamp and
	position to tag the beginning of the 'session'. Updates the startup record with
	the initial place / time values.
*/
func startFlightLog() {

	// gps coordinates at startup
	flightlog.start_lat = float64(mySituation.Lat)
	flightlog.start_lng = float64(mySituation.Lng)
	flightlog.start_alt = mySituation.Alt
	flightlog.max_alt = mySituation.Alt

	// time, timezone, localtime
	flightlog.start_timestamp = (stratuxClock.RealTime.UnixNano() / 1000000)
	flightlog.start_tz = latlong.LookupZoneName(float64(mySituation.Lat), float64(mySituation.Lng))
	loc, err := time.LoadLocation(flightlog.start_tz)
	if err == nil {
		flightlog.start_localtime = stratuxClock.RealTime.In(loc).String()
	}

	// airport code and name
	apt, err := findAirport(float64(mySituation.Lat), float64(mySituation.Lng))
	if err == nil {
		flightlog.start_airport_id = apt.faaId
		flightlog.start_airport_name = apt.name
		flightlog.route = apt.faaId
	}

	// update the database entry
	dataUpdateChan <- true
}
Example #3
0
// FileTime returns the best guess of the file's creation time (or modtime).
// If the file doesn't have its own metadata indication the creation time (such as in EXIF),
// FileTime uses the modification time from the file system.
// It there was a valid EXIF but an error while trying to get a date from it,
// it logs the error and tries the other methods.
func FileTime(f io.ReaderAt) (time.Time, error) {
	var ct time.Time
	defaultTime := func() (time.Time, error) {
		if osf, ok := f.(*os.File); ok {
			fi, err := osf.Stat()
			if err != nil {
				return ct, fmt.Errorf("Failed to find a modtime: stat: %v", err)
			}
			return fi.ModTime(), nil
		}
		return ct, errors.New("All methods failed to find a creation time or modtime.")
	}

	size, ok := findSize(f)
	if !ok {
		size = 256 << 10 // enough to get the EXIF
	}
	r := io.NewSectionReader(f, 0, size)
	var tiffErr error
	ex, err := exif.Decode(r)
	if err != nil {
		tiffErr = err
		if exif.IsShortReadTagValueError(err) {
			return ct, io.ErrUnexpectedEOF
		}
		if exif.IsCriticalError(err) || exif.IsExifError(err) {
			return defaultTime()
		}
	}
	ct, err = ex.DateTime()
	if err != nil {
		return defaultTime()
	}
	// If the EXIF file only had local timezone, but it did have
	// GPS, then lookup the timezone and correct the time.
	if ct.Location() == time.Local {
		if exif.IsGPSError(tiffErr) {
			log.Printf("Invalid EXIF GPS data: %v", tiffErr)
			return ct, nil
		}
		if lat, long, err := ex.LatLong(); err == nil {
			if loc := lookupLocation(latlong.LookupZoneName(lat, long)); loc != nil {
				if t, err := exifDateTimeInLocation(ex, loc); err == nil {
					return t, nil
				}
			}
		} else if !exif.IsTagNotPresentError(err) {
			log.Printf("Invalid EXIF GPS data: %v", err)
		}
	}
	return ct, nil
}
Example #4
0
func getLocalTimeZone(lat fit.Latitude, lng fit.Longitude) (*time.Location, error) {
	if lat.Invalid() || lng.Invalid() {
		return nil, errNoGeoDataAvailable
	}

	ltz := latlong.LookupZoneName(lat.Degrees(), lng.Degrees())
	if ltz == "" {
		return nil, errors.New("found no timezone for provided geographical data")
	}

	location, err := time.LoadLocation(ltz)
	if err != nil {
		return nil, fmt.Errorf("error loading location for zone name %q: %v", ltz, err)
	}

	return location, nil
}
Example #5
0
func (we *wrapperEvents) UnmarshalJSON(data []byte) error {
	var events []model.Event

	if err := json.Unmarshal(data, &events); err != nil {
		return err
	}

	if len(events) > 0 {
		// get all datetime for event within venue timezone
		for i, event := range events {
			tz := latlong.LookupZoneName(float64(event.Venue.Latitude), float64(event.Venue.Longitude))
			loc, err := time.LoadLocation(tz)
			if err != nil {
				continue
			}
			events[i].Datetime.Time = time.Date(event.Datetime.Time.Year(), event.Datetime.Time.Month(), event.Datetime.Time.Day(), event.Datetime.Time.Hour(), event.Datetime.Time.Minute(), event.Datetime.Time.Second(), event.Datetime.Time.Nanosecond(), loc)
		}
	}

	we.events = events
	return nil
}
Example #6
0
/*
	append a flight event record to the 'events' table in the database
*/
func addFlightEvent(event string) {

	var myEvent FlightEvent
	myEvent.event = event
	myEvent.lat = float64(mySituation.Lat)
	myEvent.lng = float64(mySituation.Lng)

	timezone := latlong.LookupZoneName(float64(mySituation.Lat), float64(mySituation.Lng))
	loc, err := time.LoadLocation(timezone)
	if err == nil {
		lt := stratuxClock.RealTime.In(loc)
		myEvent.localtime = lt.Format("15:04:05 MST")
	}

	apt, err := findAirport(float64(mySituation.Lat), float64(mySituation.Lng))
	if err == nil {
		myEvent.airport_id = apt.faaId
		myEvent.airport_name = apt.name
	}

	myEvent.timestamp = stratuxClock.RealTime.Unix()

	dataLogChan <- DataLogRow{tbl: "events", data: myEvent}
}
Example #7
0
func getAlbumPhotos(api flickrAPI, id string, gotPhoto chan struct{}) SetOfRefOfRemotePhoto {
	response := struct {
		flickrCall
		Photoset struct {
			Photo []struct {
				DateTaken      string      `json:"datetaken"`
				Id             string      `json:"id"`
				Title          string      `json:"title"`
				Tags           string      `json:"tags"`
				ThumbURL       string      `json:"url_t"`
				ThumbWidth     interface{} `json:"width_t"`
				ThumbHeight    interface{} `json:"height_t"`
				SmallURL       string      `json:"url_s"`
				SmallWidth     interface{} `json:"width_s"`
				SmallHeight    interface{} `json:"height_s"`
				Latitude       interface{} `json:"latitude"`
				Longitude      interface{} `json:"longitude"`
				MediumURL      string      `json:"url_m"`
				MediumWidth    interface{} `json:"width_m"`
				MediumHeight   interface{} `json:"height_m"`
				LargeURL       string      `json:"url_l"`
				LargeWidth     interface{} `json:"width_l"`
				LargeHeight    interface{} `json:"height_l"`
				OriginalURL    string      `json:"url_o"`
				OriginalWidth  interface{} `json:"width_o"`
				OriginalHeight interface{} `json:"height_o"`
			} `json:"photo"`
		} `json:"photoset"`
	}{}

	// TODO: Implement paging. This call returns a maximum of 500 pictures in each response.
	err := api.Call("flickr.photosets.getPhotos", &response, &map[string]string{
		"photoset_id": id,
		"user_id":     user.Id(),
		"extras":      "date_taken,geo,tags,url_t,url_s,url_m,url_l,url_o",
	})
	d.Chk.NoError(err)

	store := ds.Store()
	photos := NewSetOfRefOfRemotePhoto()

	for _, p := range response.Photoset.Photo {
		photo := RemotePhotoDef{
			Id:    p.Id,
			Title: p.Title,
			Tags:  getTags(p.Tags),
		}.New()

		lat, lon := deFlickr(p.Latitude), deFlickr(p.Longitude)

		// Flickr doesn't give timezone information (in fairness, neither does EXIF), so try to figure it out from the geolocation data. This is imperfect because it won't give us daylight savings. If there is no geolocation data then assume the location is PST - it's better than GMT.
		zone := "America/Los_Angeles"
		if lat != 0.0 && lon != 0.0 {
			if z := latlong.LookupZoneName(lat, lon); z != "" {
				zone = z
			}
		}
		location, err := time.LoadLocation(zone)
		d.Chk.NoError(err)

		// DateTaken is the MySQL DATETIME format.
		if t, err := time.ParseInLocation("2006-01-02 15:04:05", p.DateTaken, location); err == nil {
			photo = photo.SetDate(DateDef{t.Unix() * 1e3}.New())
		} else {
			fmt.Printf("Error parsing date \"%s\": %s\n", p.DateTaken, err)
		}

		sizes := NewMapOfSizeToString()
		sizes = addSize(sizes, p.ThumbURL, p.ThumbWidth, p.ThumbHeight)
		sizes = addSize(sizes, p.SmallURL, p.SmallWidth, p.SmallHeight)
		sizes = addSize(sizes, p.MediumURL, p.MediumWidth, p.MediumHeight)
		sizes = addSize(sizes, p.LargeURL, p.LargeWidth, p.LargeHeight)
		sizes = addSize(sizes, p.OriginalURL, p.OriginalWidth, p.OriginalHeight)
		photo = photo.SetSizes(sizes)

		if lat != 0.0 && lon != 0.0 {
			photo = photo.SetGeoposition(GeopositionDef{float32(lat), float32(lon)}.New())
		}

		// TODO: Write photos in batches.
		photos = photos.Insert(store.WriteValue(photo).(RefOfRemotePhoto))
		gotPhoto <- struct{}{}
	}

	return photos
}