2018-08-22 14:35:35 -06:00
|
|
|
#!/usr/bin/env python
|
2018-11-26 09:56:30 -07:00
|
|
|
from __future__ import print_function, division
|
2018-08-22 14:35:35 -06:00
|
|
|
import json
|
|
|
|
import requests
|
|
|
|
import ephem
|
|
|
|
import math
|
|
|
|
import random
|
|
|
|
from datetime import datetime, timedelta
|
2018-11-18 14:03:16 -07:00
|
|
|
import itertools
|
|
|
|
from satellite_tle import fetch_tles
|
|
|
|
import os
|
|
|
|
import glob
|
|
|
|
import lxml.html
|
2018-11-26 09:56:30 -07:00
|
|
|
import argparse
|
2018-08-22 14:35:35 -06:00
|
|
|
|
2018-11-18 14:03:16 -07:00
|
|
|
class twolineelement:
|
|
|
|
"""TLE class"""
|
2018-08-22 14:35:35 -06:00
|
|
|
|
|
|
|
def __init__(self, tle0, tle1, tle2):
|
2018-11-18 14:03:16 -07:00
|
|
|
"""Define a TLE"""
|
2018-08-22 14:35:35 -06:00
|
|
|
|
|
|
|
self.tle0 = tle0
|
|
|
|
self.tle1 = tle1
|
|
|
|
self.tle2 = tle2
|
|
|
|
if tle0[:2]=="0 ":
|
|
|
|
self.name = tle0[2:]
|
|
|
|
else:
|
|
|
|
self.name = tle0
|
2018-11-26 09:56:30 -07:00
|
|
|
if tle1.split(" ")[1]=="":
|
|
|
|
self.id = int(tle1.split(" ")[2][:4])
|
|
|
|
else:
|
|
|
|
self.id = int(tle1.split(" ")[1][:5])
|
2018-11-18 14:03:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
class satellite:
|
|
|
|
"""Satellite class"""
|
|
|
|
|
2018-11-19 15:45:54 -07:00
|
|
|
def __init__(self, tle, transmitter, success_rate, good_count, data_count):
|
2018-11-18 14:03:16 -07:00
|
|
|
"""Define a satellite"""
|
|
|
|
|
|
|
|
self.tle0 = tle.tle0
|
|
|
|
self.tle1 = tle.tle1
|
|
|
|
self.tle2 = tle.tle2
|
|
|
|
self.id = tle.id
|
|
|
|
self.name = tle.name
|
|
|
|
self.transmitter = transmitter
|
2018-11-19 15:45:54 -07:00
|
|
|
self.success_rate = success_rate
|
|
|
|
self.good_count = good_count
|
|
|
|
self.data_count = data_count
|
2018-08-22 14:35:35 -06:00
|
|
|
|
|
|
|
def get_scheduled_passes_from_network(ground_station, tmin, tmax):
|
|
|
|
# Get first page
|
|
|
|
client = requests.session()
|
|
|
|
|
|
|
|
# Loop
|
|
|
|
start = True
|
|
|
|
scheduledpasses = []
|
|
|
|
|
|
|
|
while True:
|
|
|
|
if start:
|
|
|
|
r = client.get("https://network.satnogs.org/api/observations/?ground_station=%d"%ground_station)
|
2018-11-15 13:08:48 -07:00
|
|
|
start = False
|
2018-08-22 14:35:35 -06:00
|
|
|
else:
|
|
|
|
nextpage = r.links.get("next")
|
|
|
|
r = client.get(nextpage["url"])
|
|
|
|
|
|
|
|
# r.json() is a list of dicts
|
|
|
|
for o in r.json():
|
|
|
|
satpass = {"id": o['norad_cat_id'],
|
|
|
|
"tr": datetime.strptime(o['start'].replace("Z", ""), "%Y-%m-%dT%H:%M:%S"),
|
|
|
|
"ts": datetime.strptime(o['end'].replace("Z", ""), "%Y-%m-%dT%H:%M:%S"),
|
|
|
|
"scheduled": True}
|
|
|
|
|
|
|
|
if satpass['ts']>tmin and satpass['tr']<tmax:
|
|
|
|
scheduledpasses.append(satpass)
|
|
|
|
if satpass['ts']<tmin:
|
|
|
|
break
|
|
|
|
|
|
|
|
return scheduledpasses
|
|
|
|
|
|
|
|
def overlap(satpass, scheduledpasses):
|
|
|
|
# No overlap
|
|
|
|
overlap = False
|
|
|
|
# Loop over scheduled passes
|
|
|
|
for scheduledpass in scheduledpasses:
|
|
|
|
# Test pass falls within scheduled pass
|
|
|
|
if satpass['tr']>=scheduledpass['tr'] and satpass['ts']<scheduledpass['ts']:
|
|
|
|
overlap = True
|
|
|
|
# Scheduled pass falls within test pass
|
|
|
|
elif scheduledpass['tr']>=satpass['tr'] and scheduledpass['ts']<satpass['ts']:
|
|
|
|
overlap = True
|
|
|
|
# Pass start falls within pass
|
|
|
|
elif satpass['tr']>=scheduledpass['tr'] and satpass['tr']<scheduledpass['ts']:
|
|
|
|
overlap = True
|
|
|
|
# Pass end falls within end
|
|
|
|
elif satpass['ts']>=scheduledpass['tr'] and satpass['ts']<scheduledpass['ts']:
|
|
|
|
overlap = True
|
|
|
|
if overlap == True:
|
|
|
|
break
|
|
|
|
|
|
|
|
return overlap
|
|
|
|
|
|
|
|
def ordered_scheduler(passes, scheduledpasses):
|
|
|
|
"""Loop through a list of ordered passes and schedule each next one that fits"""
|
|
|
|
# Loop over passes
|
|
|
|
for satpass in passes:
|
|
|
|
# Schedule if there is no overlap with already scheduled passes
|
|
|
|
if overlap(satpass, scheduledpasses)==False:
|
|
|
|
scheduledpasses.append(satpass)
|
|
|
|
|
|
|
|
return scheduledpasses
|
|
|
|
|
|
|
|
def random_scheduler(passes, scheduledpasses):
|
|
|
|
"""Schedule passes based on random ordering"""
|
|
|
|
# Shuffle passes
|
|
|
|
random.shuffle(passes)
|
|
|
|
|
|
|
|
return ordered_scheduler(passes, scheduledpasses)
|
|
|
|
|
|
|
|
def efficiency(passes):
|
|
|
|
|
|
|
|
# Loop over passes
|
|
|
|
start = False
|
|
|
|
for satpass in passes:
|
|
|
|
if start==False:
|
|
|
|
dt = satpass['ts']-satpass['tr']
|
|
|
|
tmin = satpass['tr']
|
|
|
|
tmax = satpass['ts']
|
|
|
|
start = True
|
|
|
|
else:
|
|
|
|
dt += satpass['ts']-satpass['tr']
|
|
|
|
if satpass['tr']<tmin: tmin=satpass['tr']
|
|
|
|
if satpass['ts']>tmax: tmax=satpass['ts']
|
|
|
|
# Total time covered
|
|
|
|
dttot = tmax-tmin
|
|
|
|
|
|
|
|
return dt.total_seconds(),dttot.total_seconds(), dt.total_seconds()/dttot.total_seconds()
|
|
|
|
|
2018-11-15 13:08:48 -07:00
|
|
|
def find_passes(satellites, observer, tmin, tmax, minimum_altitude):
|
2018-08-22 14:35:35 -06:00
|
|
|
# Loop over satellites
|
|
|
|
passes = []
|
|
|
|
passid = 0
|
|
|
|
for satellite in satellites:
|
|
|
|
# Set start time
|
|
|
|
observer.date = ephem.date(tmin)
|
|
|
|
|
|
|
|
# Load TLE
|
|
|
|
try:
|
|
|
|
sat_ephem = ephem.readtle(str(satellite.tle0),
|
|
|
|
str(satellite.tle1),
|
|
|
|
str(satellite.tle2))
|
|
|
|
except (ValueError, AttributeError):
|
|
|
|
continue
|
|
|
|
|
|
|
|
# Loop over passes
|
|
|
|
keep_digging = True
|
|
|
|
while keep_digging:
|
|
|
|
try:
|
|
|
|
tr, azr, tt, altt, ts, azs = observer.next_pass(sat_ephem)
|
|
|
|
except ValueError:
|
|
|
|
break # there will be sats in our list that fall below horizon, skip
|
|
|
|
except TypeError:
|
|
|
|
break # if there happens to be a non-EarthSatellite object in the list
|
|
|
|
except Exception:
|
|
|
|
break
|
|
|
|
|
|
|
|
if tr is None:
|
|
|
|
break
|
|
|
|
|
|
|
|
# using the angles module convert the sexagesimal degree into
|
|
|
|
# something more easily read by a human
|
|
|
|
try:
|
|
|
|
elevation = format(math.degrees(altt), '.0f')
|
|
|
|
azimuth_r = format(math.degrees(azr), '.0f')
|
|
|
|
azimuth_s = format(math.degrees(azs), '.0f')
|
|
|
|
except TypeError:
|
|
|
|
break
|
|
|
|
passid += 1
|
|
|
|
|
|
|
|
# show only if >= configured horizon and in next 6 hours,
|
|
|
|
# and not directly overhead (tr < ts see issue 199)
|
|
|
|
if tr < ephem.date(tmax):
|
|
|
|
if (float(elevation) >= minimum_altitude and tr < ts):
|
|
|
|
valid = True
|
|
|
|
if tr < ephem.Date(datetime.now() +
|
|
|
|
timedelta(minutes=5)):
|
|
|
|
valid = False
|
|
|
|
satpass = {'passid': passid,
|
|
|
|
'mytime': str(observer.date),
|
|
|
|
'name': str(satellite.name),
|
|
|
|
'id': str(satellite.id),
|
|
|
|
'tle1': str(satellite.tle1),
|
|
|
|
'tle2': str(satellite.tle2),
|
|
|
|
'tr': tr.datetime(), # Rise time
|
|
|
|
'azr': azimuth_r, # Rise Azimuth
|
|
|
|
'tt': tt.datetime(), # Max altitude time
|
|
|
|
'altt': elevation, # Max altitude
|
|
|
|
'ts': ts.datetime(), # Set time
|
|
|
|
'azs': azimuth_s, # Set azimuth
|
|
|
|
'valid': valid,
|
2018-11-18 14:03:16 -07:00
|
|
|
'uuid': satellite.transmitter,
|
2018-11-19 15:45:54 -07:00
|
|
|
'success_rate': satellite.success_rate,
|
|
|
|
'good_count': satellite.good_count,
|
|
|
|
'data_count': satellite.data_count,
|
2018-08-22 14:35:35 -06:00
|
|
|
'scheduled': False}
|
|
|
|
passes.append(satpass)
|
|
|
|
observer.date = ephem.Date(ts).datetime() + timedelta(minutes=1)
|
|
|
|
else:
|
|
|
|
keep_digging = False
|
|
|
|
|
2018-11-15 13:08:48 -07:00
|
|
|
return passes
|
|
|
|
|
|
|
|
def get_groundstation_info(ground_station_id):
|
|
|
|
# Get first page
|
|
|
|
client = requests.session()
|
|
|
|
|
|
|
|
# Loop
|
|
|
|
start = True
|
|
|
|
found = False
|
|
|
|
while True:
|
|
|
|
if start:
|
|
|
|
r = client.get("https://network.satnogs.org/api/stations")
|
|
|
|
start = False
|
|
|
|
else:
|
|
|
|
nextpage = r.links.get("next")
|
|
|
|
try:
|
|
|
|
r = client.get(nextpage["url"])
|
|
|
|
except TypeError:
|
|
|
|
break
|
|
|
|
|
|
|
|
# Get info
|
|
|
|
for o in r.json():
|
|
|
|
if o['id'] == ground_station_id:
|
|
|
|
found = True
|
|
|
|
break
|
|
|
|
|
|
|
|
# Exit
|
|
|
|
if found:
|
|
|
|
break
|
|
|
|
if found:
|
|
|
|
return o
|
|
|
|
else:
|
|
|
|
return {}
|
|
|
|
|
2018-11-18 14:03:16 -07:00
|
|
|
def get_active_transmitter_info(fmin, fmax):
|
|
|
|
# Open session
|
|
|
|
client = requests.session()
|
|
|
|
r = client.get("https://db.satnogs.org/api/transmitters")
|
|
|
|
|
|
|
|
# Loop
|
|
|
|
transmitters = []
|
|
|
|
for o in r.json():
|
|
|
|
if o["alive"] and o["downlink_low"]>fmin and o["downlink_low"]<=fmax:
|
|
|
|
transmitter = {"norad_cat_id": o["norad_cat_id"],
|
|
|
|
"uuid": o["uuid"]}
|
|
|
|
transmitters.append(transmitter)
|
|
|
|
|
|
|
|
return transmitters
|
|
|
|
|
|
|
|
def get_last_update(fname):
|
|
|
|
try:
|
|
|
|
fp = open(fname, "r")
|
|
|
|
line = fp.readline()
|
|
|
|
fp.close()
|
|
|
|
return datetime.strptime(line.strip(), "%Y-%m-%dT%H:%M:%S")
|
|
|
|
except IOError:
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def schedule_observation(username, password, norad_cat_id, uuid, ground_station_id, starttime, endtime):
|
|
|
|
loginUrl = "https://network.satnogs.org/accounts/login/" #login URL
|
|
|
|
session = requests.session()
|
|
|
|
login = session.get(loginUrl) #Get login page for CSFR token
|
|
|
|
login_html = lxml.html.fromstring(login.text)
|
|
|
|
login_hidden_inputs = login_html.xpath(r'//form//input[@type="hidden"]') #Get CSFR token
|
|
|
|
form = {x.attrib["name"]: x.attrib["value"] for x in login_hidden_inputs}
|
|
|
|
form["login"] = username
|
|
|
|
form["password"] = password
|
|
|
|
session.post(loginUrl, data=form, headers={'referer':loginUrl}) #Login
|
|
|
|
|
|
|
|
obsURL = "https://network.satnogs.org/observations/new/" #Observation URL
|
|
|
|
obs = session.get(obsURL) #Get the observation/new/ page to get the CSFR token
|
|
|
|
obs_html = lxml.html.fromstring(obs.text)
|
|
|
|
hidden_inputs = obs_html.xpath(r'//form//input[@type="hidden"]')
|
|
|
|
form = {x.attrib["name"]: x.attrib["value"] for x in hidden_inputs}
|
|
|
|
form["satellite"] = norad_cat_id
|
|
|
|
form["transmitter"] = uuid
|
|
|
|
form["start-time"] = starttime
|
|
|
|
form["end-time"] = endtime
|
|
|
|
form["0-starting_time"] = starttime
|
|
|
|
form["0-ending_time"] = endtime
|
|
|
|
form["0-station"] = ground_station_id
|
|
|
|
form["total"] = str(1)
|
|
|
|
session.post(obsURL, data=form, headers={'referer':obsURL})
|
2018-11-19 15:45:54 -07:00
|
|
|
|
|
|
|
def get_transmitter_success_rate(norad, uuid):
|
|
|
|
transmitters = requests.get("https://network.satnogs.org/transmitters/"+str(norad)).json()["transmitters"]
|
|
|
|
success_rate = 0
|
|
|
|
good_count = 0
|
|
|
|
data_count = 0
|
|
|
|
for transmitter in transmitters:
|
|
|
|
if transmitter["uuid"]==uuid:
|
|
|
|
success_rate = transmitter["success_rate"]
|
|
|
|
good_count = transmitter["good_count"]
|
|
|
|
data_count = transmitter["data_count"]
|
|
|
|
break
|
|
|
|
|
|
|
|
return success_rate, good_count, data_count
|
2018-11-18 14:03:16 -07:00
|
|
|
|
2018-11-15 13:08:48 -07:00
|
|
|
if __name__ == "__main__":
|
2018-11-26 09:56:30 -07:00
|
|
|
# Parse arguments
|
|
|
|
parser = argparse.ArgumentParser(description="Automatically schedule observations on a SatNOGS station.")
|
|
|
|
parser.add_argument("-s", "--station", help="Ground station ID", type=int)
|
|
|
|
parser.add_argument("-t", "--starttime", help="Start time (YYYY-MM-DD HH:MM:SS) [default: now]",
|
|
|
|
default=datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S"))
|
|
|
|
parser.add_argument("-d", "--duration", help="Duration to schedule [hours]", type=int, default=1)
|
|
|
|
parser.add_argument("-u", "--username", help="SatNOGS username")
|
|
|
|
parser.add_argument("-p", "--password", help="SatNOGS password")
|
|
|
|
parser.add_argument("-n", "--dryrun", help="Dry run (do not schedule passes)", action="store_true")
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
2018-11-15 13:08:48 -07:00
|
|
|
# Settings
|
2018-11-26 09:56:30 -07:00
|
|
|
ground_station_id = args.station
|
|
|
|
length_hours = args.duration
|
2018-11-18 14:03:16 -07:00
|
|
|
data_age_hours = 24
|
|
|
|
cache_dir = "/tmp/cache"
|
2018-11-26 09:56:30 -07:00
|
|
|
username = args.username
|
|
|
|
password = args.password
|
|
|
|
schedule = not args.dryrun
|
2018-11-18 14:03:16 -07:00
|
|
|
|
|
|
|
# Set time range
|
2018-11-26 09:56:30 -07:00
|
|
|
tnow = datetime.strptime(args.starttime, "%Y-%m-%dT%H:%M:%S")
|
2018-11-18 14:03:16 -07:00
|
|
|
tmin = tnow
|
|
|
|
tmax = tnow+timedelta(hours=length_hours)
|
|
|
|
|
2018-11-15 13:08:48 -07:00
|
|
|
# Get ground station information
|
|
|
|
ground_station = get_groundstation_info(ground_station_id)
|
|
|
|
|
2018-11-18 14:03:16 -07:00
|
|
|
# Create cache
|
|
|
|
if not os.path.isdir(cache_dir):
|
|
|
|
os.mkdir(cache_dir)
|
|
|
|
|
|
|
|
# Get last update
|
|
|
|
tlast = get_last_update(os.path.join(cache_dir, "last_update_%d.txt"%ground_station_id))
|
|
|
|
|
2018-11-19 15:45:54 -07:00
|
|
|
# Update logic
|
|
|
|
update = False
|
2018-11-18 14:03:16 -07:00
|
|
|
if tlast==None or (tnow-tlast).total_seconds()>data_age_hours*3600:
|
2018-11-19 15:45:54 -07:00
|
|
|
update = True
|
|
|
|
if not os.path.isfile(os.path.join(cache_dir, "transmitters_%d.txt"%ground_station_id)):
|
|
|
|
update = True
|
|
|
|
if not os.path.isfile(os.path.join(cache_dir, "tles_%d.txt"%ground_station_id)):
|
|
|
|
update = True
|
|
|
|
|
|
|
|
# Update
|
|
|
|
if update:
|
2018-11-18 14:03:16 -07:00
|
|
|
# Store current time
|
|
|
|
with open(os.path.join(cache_dir, "last_update_%d.txt"%ground_station_id), "w") as fp:
|
|
|
|
fp.write(tnow.strftime("%Y-%m-%dT%H:%M:%S")+"\n")
|
|
|
|
|
|
|
|
# Get active transmitters in frequency range of each antenna
|
|
|
|
transmitters = []
|
|
|
|
for antenna in ground_station['antenna']:
|
|
|
|
transmitters.append(get_active_transmitter_info(antenna["frequency"], antenna["frequency_max"]))
|
|
|
|
transmitters = list(itertools.chain.from_iterable(transmitters))
|
|
|
|
|
|
|
|
# Store transmitters
|
|
|
|
fp = open(os.path.join(cache_dir, "transmitters_%d.txt"%ground_station_id), "w")
|
|
|
|
for transmitter in transmitters:
|
2018-11-19 15:45:54 -07:00
|
|
|
success_rate, good_count, data_count = get_transmitter_success_rate(
|
|
|
|
transmitter["norad_cat_id"], transmitter["uuid"])
|
|
|
|
fp.write("%05d %s %d %d %d\n"%(transmitter["norad_cat_id"], transmitter["uuid"], success_rate, good_count, data_count))
|
2018-11-18 14:03:16 -07:00
|
|
|
fp.close()
|
|
|
|
|
|
|
|
# Get NORAD IDs
|
|
|
|
norad_cat_ids = sorted(set([transmitter["norad_cat_id"] for transmitter in transmitters]))
|
|
|
|
|
|
|
|
# Get TLEs
|
|
|
|
tles = fetch_tles(norad_cat_ids)
|
|
|
|
|
|
|
|
# Store TLEs
|
|
|
|
fp = open(os.path.join(cache_dir, "tles_%d.txt"%ground_station_id), "w")
|
|
|
|
for norad_cat_id, (source, tle) in tles.items():
|
|
|
|
fp.write("%s\n%s\n%s\n"%(tle[0], tle[1], tle[2]))
|
|
|
|
fp.close()
|
|
|
|
|
2018-11-15 13:08:48 -07:00
|
|
|
# Set observer
|
|
|
|
observer = ephem.Observer()
|
|
|
|
observer.lon = str(ground_station['lng'])
|
|
|
|
observer.lat = str(ground_station['lat'])
|
|
|
|
observer.elevation = ground_station['altitude']
|
|
|
|
minimum_altitude = ground_station['min_horizon']
|
|
|
|
|
2018-11-18 14:03:16 -07:00
|
|
|
# Read tles
|
|
|
|
with open(os.path.join(cache_dir, "tles_%d.txt"%ground_station_id), "r") as f:
|
2018-11-15 13:08:48 -07:00
|
|
|
lines = f.readlines()
|
2018-11-18 14:03:16 -07:00
|
|
|
tles = [twolineelement(lines[i], lines[i+1], lines[i+2])
|
|
|
|
for i in range(0, len(lines), 3)]
|
2018-11-15 13:08:48 -07:00
|
|
|
|
2018-11-18 14:03:16 -07:00
|
|
|
# Read transmitters
|
|
|
|
satellites = []
|
|
|
|
with open(os.path.join(cache_dir, "transmitters_%d.txt"%ground_station_id), "r") as f:
|
|
|
|
lines = f.readlines()
|
|
|
|
for line in lines:
|
2018-11-19 15:45:54 -07:00
|
|
|
item = line.split()
|
|
|
|
norad_cat_id, uuid, success_rate, good_count, data_count = int(item[0]), item[1], float(item[2])/100.0, int(item[3]), int(item[4])
|
2018-11-18 14:03:16 -07:00
|
|
|
for tle in tles:
|
|
|
|
if tle.id == norad_cat_id:
|
2018-11-19 15:45:54 -07:00
|
|
|
satellites.append(satellite(tle, uuid, success_rate, good_count, data_count))
|
2018-11-15 13:08:48 -07:00
|
|
|
|
|
|
|
# Find passes
|
|
|
|
passes = find_passes(satellites, observer, tmin, tmax, minimum_altitude)
|
|
|
|
|
2018-08-22 14:35:35 -06:00
|
|
|
# Priorities
|
2018-11-19 15:45:54 -07:00
|
|
|
# priorities = {"40069": 1.000, "25338": 0.990, "28654": 0.990, "33591": 0.990}
|
|
|
|
priorities = {}
|
2018-08-22 14:35:35 -06:00
|
|
|
|
|
|
|
# List of scheduled passes
|
2018-11-15 13:08:48 -07:00
|
|
|
scheduledpasses = get_scheduled_passes_from_network(ground_station_id, tmin, tmax)
|
|
|
|
print("Found %d scheduled passes between %s and %s on ground station %d\n"%(len(scheduledpasses), tmin, tmax, ground_station_id))
|
2018-08-22 14:35:35 -06:00
|
|
|
|
|
|
|
# Get passes of priority objects
|
|
|
|
prioritypasses = []
|
|
|
|
normalpasses = []
|
|
|
|
for satpass in passes:
|
|
|
|
# Get user defined priorities
|
|
|
|
if satpass['id'] in priorities:
|
|
|
|
satpass['priority'] = priorities[satpass['id']]
|
|
|
|
prioritypasses.append(satpass)
|
|
|
|
else:
|
2018-11-19 15:45:54 -07:00
|
|
|
satpass['priority'] = (float(satpass['altt'])/90.0)*satpass['success_rate']
|
2018-08-22 14:35:35 -06:00
|
|
|
normalpasses.append(satpass)
|
|
|
|
|
|
|
|
# Priority scheduler
|
|
|
|
prioritypasses = sorted(prioritypasses, key=lambda satpass: -satpass['priority'])
|
|
|
|
scheduledpasses = ordered_scheduler(prioritypasses, scheduledpasses)
|
|
|
|
|
|
|
|
# Random scheduler
|
|
|
|
normalpasses = sorted(normalpasses, key=lambda satpass: -satpass['priority'])
|
|
|
|
scheduledpasses = ordered_scheduler(normalpasses, scheduledpasses)
|
|
|
|
|
|
|
|
dt, dttot, eff = efficiency(scheduledpasses)
|
|
|
|
print("%d passes scheduled out of %d, %.0f s out of %.0f s at %.3f%% efficiency"%(len(scheduledpasses), len(passes), dt, dttot, 100*eff))
|
|
|
|
|
|
|
|
# Find unique objects
|
|
|
|
satids = sorted(set([satpass['id'] for satpass in passes]))
|
|
|
|
|
|
|
|
for satpass in sorted(scheduledpasses, key=lambda satpass: satpass['tr']):
|
|
|
|
if satpass['scheduled']==False:
|
2018-11-26 09:56:30 -07:00
|
|
|
print("%05d %s %s %3.0f %4.3f %s %s"%(int(satpass['id']), satpass['tr'].strftime("%Y-%m-%dT%H:%M:%S"), satpass['ts'].strftime("%Y-%m-%dT%H:%M:%S"), float(satpass['altt']), satpass['priority'], satpass['uuid'], satpass['name'].rstrip()))
|
2018-08-22 14:35:35 -06:00
|
|
|
|
2018-11-18 14:03:16 -07:00
|
|
|
# Schedule passes
|
2018-08-22 14:35:35 -06:00
|
|
|
for satpass in sorted(scheduledpasses, key=lambda satpass: satpass['tr']):
|
|
|
|
if satpass['scheduled']==False:
|
2018-11-18 14:03:16 -07:00
|
|
|
if schedule:
|
|
|
|
schedule_observation(username,
|
|
|
|
password,
|
|
|
|
int(satpass['id']),
|
|
|
|
satpass['uuid'],
|
|
|
|
ground_station_id,
|
|
|
|
satpass['tr'].strftime("%Y-%m-%d %H:%M:%S")+".000",
|
|
|
|
satpass['ts'].strftime("%Y-%m-%d %H:%M:%S")+".000")
|
|
|
|
|
2018-11-19 15:45:54 -07:00
|
|
|
|