207 lines
7.9 KiB
Python
207 lines
7.9 KiB
Python
from datetime import datetime , timedelta
|
|
import requests
|
|
from flask import Flask , render_template,redirect,url_for
|
|
import json
|
|
from apscheduler.schedulers.background import BackgroundScheduler
|
|
import ephem
|
|
from satnogs_api_client import fetch_satellites, DB_BASE_URL,fetch_tle_of_observation
|
|
from satellite_tle import fetch_tles
|
|
|
|
scheduler = BackgroundScheduler()
|
|
app = Flask(__name__)
|
|
|
|
modes = {1: 'FM', 2: 'AFSK1k2', 5: 'SSTV', 6: 'CW', 7: 'FMN', 9: 'USB', 15: 'GFSK4k8', 17: 'AHRPT', 18: 'AFSK9k6', 19: 'AM', 20: 'LSB', 21: 'FSK1k2', 22: 'FSK9k6', 26: 'GFSK1k2', 27: 'GFSK2k4', 28: 'GFSK9k6', 29: 'GFSK19k2', 30: 'MSK1k2', 31: 'MSK2k4', 32: 'MSK4k8', 33: 'MSK9k6', 34: 'MSK19k2', 35: 'MSK38k4', 36: 'GMSK1k2', 37: 'GMSK2k4', 38: 'GMSK4k8', 39: 'GMSK9k6', 40: 'PSK31', 41: 'PSK63', 42: 'QPSK31', 43: 'QPSK63', 44: 'APT', 45: 'HRPT', 46: 'FSK4k8', 47: 'BPSK1k2', 48: 'GMSK19k2', 49: 'AFSK', 50: 'BPSK', 51: 'FSK19k2', 52: 'BPSK115k2', 53: 'LRPT', 54: 'BPSK9k6', 55: 'FFSK1k2', 56: 'FSK2k4', 57: 'DSTAR', 58: 'DUV', 59: 'CERTO', 60: 'BPSK400', 61: 'OFDM', 62: 'QPSK38k4'}
|
|
|
|
|
|
Passes = []
|
|
Stations = []
|
|
TLEs = {}
|
|
|
|
class Pass:
|
|
id = 0
|
|
start = None
|
|
end = None
|
|
ground_station = None
|
|
satellite = None
|
|
transmitter = None
|
|
|
|
def __repr__(self):
|
|
return "\n<ID>: {}\n<Start>: {}\n<End>: {}\n<Ground Station>: {}\n<Satellite> {}\n<Transmitter>: {}".format(self.id,self.start.strftime('%Y-%m-%dT%H:%M:%S%z'),self.end.strftime('%Y-%m-%dT%H:%M:%S%z'),self.ground_station,json.dumps(self.satellite,indent = 1),json.dumps(self.transmitter,indent=1))
|
|
|
|
|
|
|
|
def getActive():
|
|
start = (datetime.utcnow() - timedelta(0,0,0,0,20)).strftime('%Y-%m-%dT%H:%M:%S%z')
|
|
end = (datetime.utcnow() + timedelta(0,0,0,0,30)).strftime('%Y-%m-%dT%H:%M:%S%z')
|
|
|
|
passesR = requests.get("https://network.satnogs.org/api/observations/?end="+end+"&format=json&start="+start)
|
|
passes = passesR.json()
|
|
if passesR.links.has_key("next"):
|
|
while passesR.links.has_key("next"):
|
|
passesR = requests.get(passesR.links["next"]["url"])
|
|
passes += passesR.json()
|
|
ground_stations = {}
|
|
for x in passes:
|
|
if datetime.strptime(x["start"],'%Y-%m-%dT%H:%M:%Sz') > datetime.utcnow() or datetime.strptime(x["end"],'%Y-%m-%dT%H:%M:%Sz') < datetime.utcnow():
|
|
passes.remove(x)
|
|
else:
|
|
if ground_stations.has_key(x["ground_station"]):
|
|
ground_stations[x["ground_station"]].append(x)
|
|
else:
|
|
ground_stations[x["ground_station"]] = []
|
|
ground_stations[x["ground_station"]].append(x)
|
|
passes = []
|
|
for x in ground_stations:
|
|
start = datetime.utcnow()
|
|
current = {"start":datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S%z')+"z"}
|
|
for y in ground_stations[x]:
|
|
if datetime.strptime(y["start"],'%Y-%m-%dT%H:%M:%Sz') < datetime.strptime(current["start"],'%Y-%m-%dT%H:%M:%Sz'):
|
|
current = y
|
|
passes.append(current)
|
|
Passes =[]
|
|
for x in passes:
|
|
temp = Pass()
|
|
temp.id = x["id"]
|
|
temp.start = datetime.strptime(x["start"],'%Y-%m-%dT%H:%M:%Sz')
|
|
temp.end = datetime.strptime(x["end"],'%Y-%m-%dT%H:%M:%Sz')
|
|
temp.ground_station = x["ground_station"]
|
|
temp.satellite = requests.get("https://db.satnogs.org/api/satellites/"+str(x["norad_cat_id"])) .json()
|
|
temp.transmitter = requests.get("https://db.satnogs.org/api/transmitters/"+x["transmitter"]).json()
|
|
Passes.append(temp)
|
|
|
|
|
|
|
|
return Passes
|
|
|
|
|
|
def GetGroundStations():
|
|
stationsR = requests.get("https://network.satnogs.org/api/stations/")
|
|
stations = stationsR.json()
|
|
while stationsR.links.has_key("next"):
|
|
stationsR = requests.get(stationsR.links["next"]["url"])
|
|
stations += stationsR.json()
|
|
|
|
for x in stations:
|
|
if x["last_seen"] == None:
|
|
stations.remove(x)
|
|
continue
|
|
|
|
if datetime.strptime(x["last_seen"],'%Y-%m-%dT%H:%M:%Sz') < (datetime.utcnow()- timedelta(10,0,0,0)):
|
|
stations.remove(x)
|
|
for x in stations:
|
|
if x["last_seen"] == None:
|
|
stations.remove(x)
|
|
continue
|
|
|
|
if datetime.strptime(x["last_seen"],'%Y-%m-%dT%H:%M:%Sz') < (datetime.utcnow()- timedelta(10,0,0,0)):
|
|
stations.remove(x)
|
|
|
|
|
|
return stations
|
|
|
|
|
|
@scheduler.scheduled_job('interval',minutes=3)
|
|
def updatePasses():
|
|
global Passes
|
|
print "Updating Passes"
|
|
Passes = getActive()
|
|
|
|
@scheduler.scheduled_job('interval',hours=10)
|
|
def updateStations():
|
|
global Stations
|
|
print "Updating Stations"
|
|
Stations = GetGroundStations()
|
|
|
|
@scheduler.scheduled_job('interval',days=1)
|
|
def updateTLE():
|
|
print "Updating TLE"
|
|
global TlEs
|
|
sats = fetch_satellites(url=DB_BASE_URL, max_satellites=None)
|
|
satnogs_db_norad_ids = set(sat['norad_cat_id'] for sat in sats if sat['status'] != 're-entered')
|
|
# Remove satellites with temporary norad ids
|
|
temporary_norad_ids = set(filter(lambda norad_id: norad_id >= 99900, satnogs_db_norad_ids))
|
|
satnogs_db_norad_ids = satnogs_db_norad_ids - temporary_norad_ids
|
|
|
|
# Fetch TLEs for the satellites of interest
|
|
tles = fetch_tles(satnogs_db_norad_ids)
|
|
TLEs = {}
|
|
for norad_id, (source, tle) in tles.items():
|
|
TLEs[norad_id] = [str(tle[0]),str(tle[1]),str(tle[2])]
|
|
print('\nTLEs for {} of {} requested satellites found ({} satellites with temporary norad ids skipped).'.format(len(tles), len(satnogs_db_norad_ids), len(temporary_norad_ids)))
|
|
|
|
|
|
|
|
|
|
@app.route("/")
|
|
def map_view():
|
|
stations = []
|
|
for x in Stations:
|
|
stations.append({'id':x['id'],'name':x['name'],'lat_lng':[x["lat"],x['lng']]})
|
|
return render_template("map.html",stations = stations)
|
|
|
|
@app.route('/occuringobservations')
|
|
def occuring_observations():
|
|
obs = []
|
|
for x in Passes:
|
|
obs.append("<a href='https://network.satnogs.org/observations/"+str(x.id)+"'>"+str(x.id)+"</a>")
|
|
return json.dumps(obs)
|
|
|
|
@app.route('/api/activestations')
|
|
def api_active_stations():
|
|
stations = []
|
|
for x in Passes:
|
|
stations.append(x.ground_station)
|
|
return json.dumps(stations)
|
|
|
|
@app.route('/api/onlinestations')
|
|
def api_online_stations():
|
|
stations = []
|
|
for x in Stations:
|
|
stations.append(x["id"])
|
|
return json.dumps(stations)
|
|
|
|
|
|
|
|
@app.route('/api/occuringobservations')
|
|
def api_occuring_observations():
|
|
obs = []
|
|
for x in Passes:
|
|
obs.append(x.id)
|
|
return json.dumps(obs)
|
|
|
|
@app.route('/api/occuringsats')
|
|
def api_occuring_sats():
|
|
obs = {}
|
|
for x in Passes:
|
|
if x.satellite['norad_cat_id'] not in TLEs.keys():
|
|
q = fetch_tle_of_observation(x.id)
|
|
TLEs[ x.satellite['norad_cat_id'] ] = [str(x.satellite["name"]),str(q[0]),str(q[1])]
|
|
satellite = ephem.readtle(TLEs[x.satellite['norad_cat_id']][0],TLEs[x.satellite['norad_cat_id']][1],TLEs[x.satellite['norad_cat_id']][2])
|
|
now = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')
|
|
satellite.compute(now)
|
|
lat = satellite.sublat*57.295779514
|
|
long = satellite.sublong*57.295779514
|
|
obs[x.satellite['norad_cat_id']] = {"name":x.satellite["name"],"lat_lng":[lat,long],"eclipsed":satellite.eclipsed,"image":x.satellite["image"]}
|
|
return json.dumps(obs)
|
|
|
|
@app.route('/api/satstationpairs')
|
|
def api_sat_station_pairs():
|
|
pairs = []
|
|
for x in Passes:
|
|
pairs.append([x.ground_station,x.satellite['norad_cat_id']])
|
|
return json.dumps(pairs)
|
|
|
|
@app.route('/api/getsatloc/<int:norad>')
|
|
def get_sat_loc(norad):
|
|
satellite = ephem.readtle(TLEs[norad][0],TLEs[norad][1],TLEs[norad][2])
|
|
now = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')
|
|
satellite.compute(now)
|
|
lat = satellite.sublat*57.295779514
|
|
long = satellite.sublong*57.295779514
|
|
return json.dumps([lat,long,satellite.eclipsed])
|
|
|
|
updatePasses()
|
|
updateStations()
|
|
updateTLE()
|
|
scheduler.start()
|
|
app.run(use_reloader=False,host = "0.0.0.0") |