Fix PEP8 styling issues
parent
a762e1147a
commit
5b36c23855
|
@ -13,6 +13,7 @@ import glob
|
|||
import lxml.html
|
||||
import argparse
|
||||
|
||||
|
||||
class twolineelement:
|
||||
"""TLE class"""
|
||||
|
||||
|
@ -48,6 +49,7 @@ class satellite:
|
|||
self.good_count = good_count
|
||||
self.data_count = data_count
|
||||
|
||||
|
||||
def get_scheduled_passes_from_network(ground_station, tmin, tmax):
|
||||
# Get first page
|
||||
client = requests.session()
|
||||
|
@ -58,7 +60,9 @@ def get_scheduled_passes_from_network(ground_station, tmin, tmax):
|
|||
|
||||
while True:
|
||||
if start:
|
||||
r = client.get("https://network.satnogs.org/api/observations/?ground_station=%d"%ground_station)
|
||||
r = client.get(
|
||||
"https://network.satnogs.org/api/observations/?ground_station=%d" %
|
||||
ground_station)
|
||||
start = False
|
||||
else:
|
||||
nextpage = r.links.get("next")
|
||||
|
@ -66,9 +70,18 @@ def get_scheduled_passes_from_network(ground_station, tmin, tmax):
|
|||
|
||||
# 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"),
|
||||
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:
|
||||
|
@ -78,6 +91,7 @@ def get_scheduled_passes_from_network(ground_station, tmin, tmax):
|
|||
|
||||
return scheduledpasses
|
||||
|
||||
|
||||
def overlap(satpass, scheduledpasses):
|
||||
# No overlap
|
||||
overlap = False
|
||||
|
@ -95,21 +109,23 @@ def overlap(satpass, scheduledpasses):
|
|||
# Pass end falls within end
|
||||
elif satpass['ts'] >= scheduledpass['tr'] and satpass['ts'] < scheduledpass['ts']:
|
||||
overlap = True
|
||||
if overlap == True:
|
||||
if overlap:
|
||||
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:
|
||||
if not overlap(satpass, scheduledpasses):
|
||||
scheduledpasses.append(satpass)
|
||||
|
||||
return scheduledpasses
|
||||
|
||||
|
||||
def random_scheduler(passes, scheduledpasses):
|
||||
"""Schedule passes based on random ordering"""
|
||||
# Shuffle passes
|
||||
|
@ -117,24 +133,29 @@ def random_scheduler(passes, scheduledpasses):
|
|||
|
||||
return ordered_scheduler(passes, scheduledpasses)
|
||||
|
||||
|
||||
def efficiency(passes):
|
||||
|
||||
# Loop over passes
|
||||
start = False
|
||||
for satpass in passes:
|
||||
if start==False:
|
||||
if not start:
|
||||
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']
|
||||
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()
|
||||
return dt.total_seconds(), dttot.total_seconds(
|
||||
), dt.total_seconds() / dttot.total_seconds()
|
||||
|
||||
|
||||
def find_passes(satellites, observer, tmin, tmax, minimum_altitude):
|
||||
# Loop over satellites
|
||||
|
@ -204,12 +225,14 @@ def find_passes(satellites, observer, tmin, tmax, minimum_altitude):
|
|||
'data_count': satellite.data_count,
|
||||
'scheduled': False}
|
||||
passes.append(satpass)
|
||||
observer.date = ephem.Date(ts).datetime() + timedelta(minutes=1)
|
||||
observer.date = ephem.Date(
|
||||
ts).datetime() + timedelta(minutes=1)
|
||||
else:
|
||||
keep_digging = False
|
||||
|
||||
return passes
|
||||
|
||||
|
||||
def get_groundstation_info(ground_station_id):
|
||||
# Get first page
|
||||
client = requests.session()
|
||||
|
@ -242,6 +265,7 @@ def get_groundstation_info(ground_station_id):
|
|||
else:
|
||||
return {}
|
||||
|
||||
|
||||
def get_active_transmitter_info(fmin, fmax):
|
||||
# Open session
|
||||
client = requests.session()
|
||||
|
@ -257,6 +281,7 @@ def get_active_transmitter_info(fmin, fmax):
|
|||
|
||||
return transmitters
|
||||
|
||||
|
||||
def get_last_update(fname):
|
||||
try:
|
||||
fp = open(fname, "r")
|
||||
|
@ -267,19 +292,28 @@ def get_last_update(fname):
|
|||
return None
|
||||
|
||||
|
||||
def schedule_observation(username, password, norad_cat_id, uuid, ground_station_id, starttime, endtime):
|
||||
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
|
||||
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
|
||||
# Get the observation/new/ page to get the CSFR token
|
||||
obs = session.get(obsURL)
|
||||
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}
|
||||
|
@ -293,8 +327,11 @@ def schedule_observation(username, password, norad_cat_id, uuid, ground_station_
|
|||
form["total"] = str(1)
|
||||
session.post(obsURL, data=form, headers={'referer': obsURL})
|
||||
|
||||
|
||||
def get_transmitter_success_rate(norad, uuid):
|
||||
transmitters = requests.get("https://network.satnogs.org/transmitters/"+str(norad)).json()["transmitters"]
|
||||
transmitters = requests.get(
|
||||
"https://network.satnogs.org/transmitters/" +
|
||||
str(norad)).json()["transmitters"]
|
||||
success_rate = 0
|
||||
good_count = 0
|
||||
data_count = 0
|
||||
|
@ -307,16 +344,30 @@ def get_transmitter_success_rate(norad, uuid):
|
|||
|
||||
return success_rate, good_count, data_count
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Parse arguments
|
||||
parser = argparse.ArgumentParser(description="Automatically schedule observations on a SatNOGS station.")
|
||||
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]",
|
||||
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(
|
||||
"-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")
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--dryrun",
|
||||
help="Dry run (do not schedule passes)",
|
||||
action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Settings
|
||||
|
@ -341,15 +392,27 @@ if __name__ == "__main__":
|
|||
os.mkdir(cache_dir)
|
||||
|
||||
# Get last update
|
||||
tlast = get_last_update(os.path.join(cache_dir, "last_update_%d.txt"%ground_station_id))
|
||||
tlast = get_last_update(
|
||||
os.path.join(
|
||||
cache_dir,
|
||||
"last_update_%d.txt" %
|
||||
ground_station_id))
|
||||
|
||||
# Update logic
|
||||
update = False
|
||||
if tlast==None or (tnow-tlast).total_seconds()>data_age_hours*3600:
|
||||
if tlast is None or (tnow - tlast).total_seconds() > data_age_hours * 3600:
|
||||
update = True
|
||||
if not os.path.isfile(os.path.join(cache_dir, "transmitters_%d.txt"%ground_station_id)):
|
||||
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)):
|
||||
if not os.path.isfile(
|
||||
os.path.join(
|
||||
cache_dir,
|
||||
"tles_%d.txt" %
|
||||
ground_station_id)):
|
||||
update = True
|
||||
|
||||
# Update
|
||||
|
@ -361,25 +424,45 @@ if __name__ == "__main__":
|
|||
# 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.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")
|
||||
fp = open(
|
||||
os.path.join(
|
||||
cache_dir,
|
||||
"transmitters_%d.txt" %
|
||||
ground_station_id),
|
||||
"w")
|
||||
for transmitter in transmitters:
|
||||
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))
|
||||
fp.write(
|
||||
"%05d %s %d %d %d\n" %
|
||||
(transmitter["norad_cat_id"],
|
||||
transmitter["uuid"],
|
||||
success_rate,
|
||||
good_count,
|
||||
data_count))
|
||||
fp.close()
|
||||
|
||||
# Get NORAD IDs
|
||||
norad_cat_ids = sorted(set([transmitter["norad_cat_id"] for transmitter in transmitters]))
|
||||
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")
|
||||
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()
|
||||
|
@ -403,10 +486,17 @@ if __name__ == "__main__":
|
|||
lines = f.readlines()
|
||||
for line in lines:
|
||||
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])
|
||||
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])
|
||||
for tle in tles:
|
||||
if tle.id == norad_cat_id:
|
||||
satellites.append(satellite(tle, uuid, success_rate, good_count, data_count))
|
||||
satellites.append(
|
||||
satellite(
|
||||
tle,
|
||||
uuid,
|
||||
success_rate,
|
||||
good_count,
|
||||
data_count))
|
||||
|
||||
# Find passes
|
||||
passes = find_passes(satellites, observer, tmin, tmax, minimum_altitude)
|
||||
|
@ -416,8 +506,11 @@ if __name__ == "__main__":
|
|||
priorities = {}
|
||||
|
||||
# List of scheduled passes
|
||||
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))
|
||||
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))
|
||||
|
||||
# Get passes of priority objects
|
||||
prioritypasses = []
|
||||
|
@ -428,30 +521,49 @@ if __name__ == "__main__":
|
|||
satpass['priority'] = priorities[satpass['id']]
|
||||
prioritypasses.append(satpass)
|
||||
else:
|
||||
satpass['priority'] = (float(satpass['altt'])/90.0)*satpass['success_rate']
|
||||
satpass['priority'] = (
|
||||
float(satpass['altt']) / 90.0) * satpass['success_rate']
|
||||
normalpasses.append(satpass)
|
||||
|
||||
# Priority scheduler
|
||||
prioritypasses = sorted(prioritypasses, key=lambda satpass: -satpass['priority'])
|
||||
prioritypasses = sorted(
|
||||
prioritypasses,
|
||||
key=lambda satpass: -
|
||||
satpass['priority'])
|
||||
scheduledpasses = ordered_scheduler(prioritypasses, scheduledpasses)
|
||||
|
||||
# Random scheduler
|
||||
normalpasses = sorted(normalpasses, key=lambda satpass: -satpass['priority'])
|
||||
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))
|
||||
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:
|
||||
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()))
|
||||
if not satpass['scheduled']:
|
||||
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()))
|
||||
|
||||
# Schedule passes
|
||||
for satpass in sorted(scheduledpasses, key=lambda satpass: satpass['tr']):
|
||||
if satpass['scheduled']==False:
|
||||
if not satpass['scheduled']:
|
||||
if schedule:
|
||||
schedule_observation(username,
|
||||
password,
|
||||
|
@ -460,5 +572,3 @@ if __name__ == "__main__":
|
|||
ground_station_id,
|
||||
satpass['tr'].strftime("%Y-%m-%d %H:%M:%S") + ".000",
|
||||
satpass['ts'].strftime("%Y-%m-%d %H:%M:%S") + ".000")
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue