def search( limit=100, range_start=None, range_end=None, range_inclusive="both", satellites=None, groundstations=None, order_by="start_time", show_stale=False, ): if satellites is None: dj_sats = Satellite.objects.all() else: dj_sats = Satellite.objects.filter(hwid__in=satellites) if groundstations is None: dj_gss = GroundStation.objects.all() else: dj_gss = GroundStation.objects.filter(hwid__in=groundstations) passes = Pass.objects.filter(satellite__in=dj_sats, groundstation__in=dj_gss) # set the default time range, if no range is specified if range_start is None and range_end is None: range_start = utc("now") range_end = range_start + datetime.timedelta(days=2) # filter the start of the range if range_start is not None: range_start = utc(range_start) if range_inclusive in ["end", "neither"]: passes = passes.filter(start_time__gte=range_start) else: passes = passes.filter(end_time__gte=range_start) # filter the end of the range if range_end is not None: range_end = utc(range_end) if range_inclusive in ["start", "neither"]: passes = passes.filter(end_time__lte=range_end) else: passes = passes.filter(start_time__lte=range_end) if not show_stale: passes = passes.exclude( Q(scheduled_on_gs=False) & Q(scheduled_on_sat=False) & Q(is_desired=False)) passes = passes.all().order_by(order_by)[:limit] return [p.to_dict() for p in passes]
def search(limit=100, range_start=None, range_end=None, range_inclusive='both', satellites=None, groundstations=None, order_by='start_time', show_stale=False): if satellites is None: dj_sats = Satellite.objects.all() else: dj_sats = Satellite.objects.filter(hwid__in=satellites) if groundstations is None: dj_gss = GroundStation.objects.all() else: dj_gss = GroundStation.objects.filter(hwid__in=groundstations) passes = Pass.objects.filter( satellite__in=dj_sats, groundstation__in=dj_gss, ) # set the default time range, if no range is specified if range_start is None and range_end is None: range_start = now() range_end = add_seconds(range_start, TWO_DAYS_S) # filter the start of the range if range_start is not None: range_start = utc(range_start) if range_inclusive in ['end', 'neither']: passes = passes.filter(start_time__gte=range_start.utc_datetime()) else: passes = passes.filter(end_time__gte=range_start.utc_datetime()) # filter the end of the range if range_end is not None: range_end = utc(range_end) if range_inclusive in ['start', 'neither']: passes = passes.filter(end_time__lte=range_end.utc_datetime()) else: passes = passes.filter(start_time__lte=range_end.utc_datetime()) if not show_stale: passes = passes.exclude(Q(scheduled_on_gs=False) & Q(scheduled_on_sat=False) & Q(is_desired=False)) passes = passes.all().order_by(order_by)[:limit] return [p.to_dict() for p in passes]
def put(uuid, _pass): _pass["uuid"] = uuid try: access_id = _pass["access_id"] access = Access.from_id(access_id) sat_obj = access.satellite gs_obj = access.groundstation _pass.setdefault("start_time", utc(access.start_time)) _pass.setdefault("end_time", utc(access.end_time)) except KeyError: # user provided all required fields instead of access id sat_hwid = _pass["satellite"] sat_obj = Satellite.objects.get(hwid=sat_hwid) gs_hwid = _pass["groundstation"] gs_obj = GroundStation.objects.get(hwid=gs_hwid) try: access_id = Access.from_overlap(_pass["start_time"], _pass["end_time"], sat_obj, gs_obj).access_id except ObjectDoesNotExist: _pass["is_valid"] = False # FIXME we are creating an new Pass object to get all of the defaults # but we don't want to create the foreign keys yet, so we pop them # out, create the object, then add them back in... _pass.pop("satellite", None) _pass.pop("groundstation", None) task_stack_uuid = _pass.pop("task_stack", None) if task_stack_uuid: task_stack = TaskStack.objects.get(uuid=task_stack_uuid) else: task_stack = None po = Pass(**_pass) m = po.to_dict() m["satellite"] = sat_obj m["groundstation"] = gs_obj m["task_stack"] = task_stack m["source_tle"] = m["satellite"].tle _pass, _created = Pass.objects.update_or_create(defaults=m, uuid=uuid) status_code = 201 if _created else 200 return _pass.to_dict(), status_code
def from_time(cls, t, sat, gs, base_url=""): t = utc(t) if not Access.is_above_horizon(sat, gs, t): raise ObjectDoesNotExist( f"Access could not be found between {sat}, {gs} at {iso(t)}" ) start_time = Access.find_start(sat, gs, t) end_time = Access.find_end(sat, gs, t) max_alt = Access.find_max_alt(sat, gs, t) return cls(start_time, end_time, sat, gs, max_alt, base_url=base_url)
def decode_access_id(cls, access_id): """ complement to the above encoding algorithm """ def decrypt(ciphertext): _crypt = AES.new(AES_KEY, AES.MODE_CFB, AES_IV) return _crypt.decrypt(ciphertext) crypted = base64.urlsafe_b64decode(access_id) decoded = decrypt(crypted).decode() sat_id, gs_id, time_tuple = decoded.split("|") times = [int(c) for c in wrap(time_tuple, 2)] # we only use the 2 digit year, so add 2000 back times[0] += 2000 time = utc(tuple(times)) return int(sat_id), int(gs_id), time
def to_access(self, base_url=''): return Access(utc(self.start_time), utc(self.end_time), self.satellite, self.groundstation, self.max_alt, base_url=base_url)
def get_track(uuid): _pass = Pass.objects.get(uuid=uuid) access = _pass.access() access._start_time.tai = max(utc(_pass.start_time).tai, access.start_time.tai) access._end_time.tai = min(utc(_pass.end_time).tai, access.end_time.tai) return get_track_file(access)
def test_bad_isostring(): with pytest.raises(ValueError): d = utc("2018-05-23T00:00:00+13:00")
def test_bad_datetime(): est = pytz.timezone('US/Eastern') dt = datetime.datetime.utcnow() dt = est.localize(dt) with pytest.raises(ValueError): utc(dt)