From d36587bb1c235e0dc9992a3891ffb46d935b402d Mon Sep 17 00:00:00 2001 From: wgaylord Date: Mon, 25 Feb 2019 11:25:57 -0600 Subject: [PATCH] Add individual station veiw --- satnogs.py | 95 ++++++++++++++++++++++++++++++++++++++--- satnogs_api_client.pyc | Bin 0 -> 5097 bytes templates/index.html | 2 +- 3 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 satnogs_api_client.pyc diff --git a/satnogs.py b/satnogs.py index c981166..3725aaf 100644 --- a/satnogs.py +++ b/satnogs.py @@ -23,6 +23,7 @@ Passes = defaultdict(list) Stations = [] TLEs = defaultdict(list) Transmitters = defaultdict(dict) +StationsPasses = defaultdict(list) SatDescrip = defaultdict(str) CZML = [] @@ -34,7 +35,7 @@ def getFuture(): observations = defaultdict(dict ) start = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S%z') - end = (datetime.utcnow() + timedelta(hours=2,minutes=30)).strftime('%Y-%m-%dT%H:%M:%S%z') + end = (datetime.utcnow() + timedelta(hours=4,minutes=30)).strftime('%Y-%m-%dT%H:%M:%S%z') passes = get_paginated_endpoint("https://network.satnogs.org/api/jobs/") obs = get_paginated_endpoint("https://network.satnogs.org/api/observations/?end="+end+"&format=json&start="+start) @@ -52,6 +53,7 @@ def getFuture(): # "transmitter":Transmitters[observations[x["id"]]["norad_cat_id"]][x["transmitter"]] Sats[observations[x["id"]]["norad_cat_id"]].append({"station":x["ground_station"],"transmitter":Transmitters[observations[x["id"]]["norad_cat_id"]][x["transmitter"]],"start":start,"end":end,"id":x["id"]}) TLEs[observations[x["id"]]["norad_cat_id"]]=[x["tle0"],x["tle1"],x["tle2"]] + StationsPasses[x["ground_station"]].append({"norad":observations[x["id"]]["norad_cat_id"],"transmitter":Transmitters[observations[x["id"]]["norad_cat_id"]][x["transmitter"]],"start":start,"end":end,"id":x["id"]}) except Exception as e: print "Error on observation number: "+str(x["id"])+ " "+str(e) broken[observations[x["id"]]["norad_cat_id"]].update([x["transmitter"]]) @@ -121,8 +123,7 @@ def updateCZML(): doc["version"]="1.0" doc["clock"]={} doc["clock"]["interval"]="0000-00-00T00:00:00Z/9999-12-31T24:00:00Z" - doc["clock"]["currentTime"] = datetime.utcnow().isoformat()+"Z" - doc["clock"]["step"] = "SYSTEM_CLOCK_MULTIPLER" + doc["clock"]["step"] = "SYSTEM_CLOCK" CZML.append(doc) StationList = {} @@ -198,8 +199,12 @@ def updateCZML(): @app.route("/") def index(): - return render_template("index.html") - + return render_template("index.html",url="/czml") + +@app.route("/station/") +def index_station(station_id): + return render_template("index.html",url="/czml/"+str(station_id)) + @app.route('/future_sats') @@ -219,7 +224,87 @@ def api_broken(): return json.dumps(output) +@app.route("/czml/") +def api_station(station_id): + czml = [] + doc = {} + doc["id"] = "document" + doc["name"] = "sats" + doc["version"]="1.0" + doc["clock"]={} + doc["clock"]["interval"]="0000-00-00T00:00:00Z/9999-12-31T24:00:00Z" + doc["clock"]["currentTime"] = datetime.utcnow().isoformat()+"Z" + doc["clock"]["step"] = "SYSTEM_CLOCK" + czml.append(doc) + + + for x in Stations: + if x["id"] == station_id: + color = [0,230,64,255] + if x["status"] == "Testing": + color = [248,148,6,255] + if x["status"] == "Offline": + color = [255,0,0,50] + + station = {} + station["id"] = str(x["id"]) + station["name"] = x["name"] + station["point"] = {} + station["show"] = True + station["point"]["color"] = {} + station["point"]["color"]["rgba"] = color + station["point"]["outlineColor"] = {} + station["point"]["outlineColor"]["rgba"] = [255,255,255,color[3]] + station["point"]["outlineWidth"] = 2.0 + station["position"] = {} + station["point"]["pixelSize"]=7.0 + station["position"]["cartographicDegrees"] = [x["lng"],x['lat'],x["altitude"]] + station["description"] = "ID: "+str(x["id"])+"
Total Observations: " + station["description"]+=str(x["observations"])+"
Status: "+x["status"]+"
QTH: " + station["description"]+=x["qthlocator"]+"
Description: "+x["description"] + czml.append(station) + break + + for y in StationsPasses[station_id]: + sat = {} + sat["id"] = str(y["id"]) + sat["name"] = TLEs[y["norad"]][0] + sat["show"] = True + sat["point"] = {} + sat["point"]["color"] = {} + sat["point"]["color"]["rgba"] = [255,0,0,255] + sat["point"]["pixelSize"]=8.0 + #sat["billboard"] = {"image":"static/sat.png","scale":0.50} + sat["position"] = {} + sat["position"]["cartographicDegrees"]=[] + sat["description"] = SatDescrip[y["norad"]] + temp = y["start"] + satObj = EarthSatellite(TLEs[y["norad"]][1],TLEs[y["norad"]][2],TLEs[y["norad"]][0]) + time = 0 + while temp <= y["end"]+timedelta(minutes=1): + + subpoint = satObj.at(ts.utc(temp)).subpoint() + lat = subpoint.latitude.degrees + lng = subpoint.longitude.degrees + elevation = subpoint.elevation.m + sat["position"]["cartographicDegrees"].extend([time,lng,lat,elevation]) + time+=60 + temp = temp+timedelta(minutes=1) + sat["position"]["interpolationAlgorithm"] = "LAGRANGE" + sat["position"]["interpolationDegree"] = 5 + sat["position"]["epoch"] = (y["start"].isoformat()+"Z").replace("+00:00","") + sat["path"] = {"show":{"interval":(y["start"].isoformat()+"Z").replace("+00:00","")+"/"+((y["end"]+timedelta(minutes=1)).isoformat()+"Z").replace("+00:00",""),"boolean":True},"width":2,"material":{"solidColor":{"color":{"rgba":[0,255,0,255]}}},"leadTime":100000,"trailTime":100000 } + + czml.append(sat) + + for y in StationsPasses[station_id]: + sat = {} + sat["id"] = str(y["id"])+"Link" + sat["polyline"] = {"show":{"interval":(y["start"].isoformat()+"Z").replace("+00:00","")+"/"+((y["end"]+timedelta(minutes=1)).isoformat()+"Z").replace("+00:00",""),"boolean":True},"width":2,"material":{"solidColor":{"color":{"rgba":y["transmitter"][1]}}},"followSurface":False,"positions":{"references":[str(y["id"])+"#position",str(station_id)+"#position"]}} + czml.append(sat) + + return json.dumps(czml) diff --git a/satnogs_api_client.pyc b/satnogs_api_client.pyc new file mode 100644 index 0000000000000000000000000000000000000000..361302889afc1901f9e9cac449703d1667b4c9ad GIT binary patch literal 5097 zcmcIo?QR>#6}_{RC{d<9EXS4Iq>b7l4HGwFqaZ5kI!YbONQxE=u!<8vRkB!dSJX-* zm);qsb}jyC(zGbhzx~sf=xgM8`T)&2cSw3A8AX9gqB*=fGdnYT?>Xn*b>-iS3!Asx zep|+W0e*iiM(n>}B=~2fE7CKvXT-$lk0Zv$9u}q$+!J zoSe+b*SNVR>4GHlYF|^krgmNJ1+^C?xh7wW>@8_$T|1X0S=7!INtV>OF3GYQtCC`i z6`gj2d+j!^H?Vh`&3@|skQXO!CFz$N zHg^5IV>j}mV_&{F=gj!`O5@4FnW68W89Kjmo9>;(w}S5jy7`|loXD}Er%y$`5;F?q zG?3!}wisF!TBC|Q>GCPrGb1NeDgGg+M(TD~+^n2p5*9FWB08XxF#9%^y*-*K?J;w4 zkBS^ubzR*F>zK!P^6k&+n#vS49t2O#4ZLgP{iQ8mwOYB*J)+VR?2Ix=Ipb z#YJ557||f^q!A9*K!<2!KZ5n(?*1d27IwdVlpSRIJE=W!`C$K}xL3qUmhbQSSnrQx z-irqlGl~aU)b3{3cw_L?G0=D@?vwRnmnJw-GRT1_9>K1n5wmI*f_iYrTn}ii1#NnX z4)TFUkPmQyI3NtCGjc2pR&h)4RQ-y$K>mszGY<1K-e1kgXjbsdr?ZUgsLCk+MdT1j z3FI5xQk5MH_%U3JV`bmRX3s`VJV-M?fET`u34GgpA5WWhyO~R)sGq|TQ9E`~mb~|D z^izbXa5V6E_-WJMgev3y4q^Hl450J#mt~|VgA&}vu}=aiDm?tB<}qZz;1Imc)zOsq zXlZQx7$!d-ECyon%NX1hyrtln~4@(ZR-i3^eu6C)OaX-YehpB5HMWrnxk}Wzc@*ZHq8J6Uh z*=pscshFBs4(ckD8$Wlm<`?$f7%MBT| z>BS*?mwRcbDpj)xeOfhjvtXc1p=3h71*gFLyo`8fFVd@&-YcZ ziu)8V2D3tG1DFx61o4D{Xk84Z22V5Eyauy&A()IqOIgv%`>7@7c2BawAnSM5J4HV1 zCrl`iv-Q_G;q?t4c*bxX`0==HGUyBFSFV9n%04Xy{yPjpZdw8Wnd`UKWQME(p zaGV{pjwQ(1KFkk)#6_9eWw8V=900h&NsiIX_1Z!q0_jJE9coPON z;HwgnGoT+?o_KO<4gh08M#I#lG(E#bvTPEPN#5~6A^y(sPm{sU2U9&&KKd9Cu_66@ zrQV}3c<((=l62f7^jk`Yz+K>wXAogU0Z~^WC9AU4OUj0_7f#Vq&HId$LXm|U8J#S$ z%(xbqWs(PHnBJ?DHzaZ<{6I#iZ9$K-+%!Kd=gKcIW(gzKgEf56f^4h74RgbzhS_F{ z8XgfC8JGHspfOSmr52n*beS_*gVU)k6~i&3P{*ac)D=%lMIFjEo#+!96H`O;8}&;= zA2RgnsOjxjBFKaIPe|^%#suQ0Sao_eb=TP^T+;XAT{a>8K z(#w_ByDC31He)}PcKhQwSDC4+=q?qVJ21|{hj^J_hbqG|$xIML+_m&|<)S8sl(QFl zg##t%@Nz1T<8l;Tmt5AcZaF8#_Rrj9o_m=ps?Jr@rV{WxQ;&RuiwxqZe%S(l;DasH zAkfw=kO)$`g>n%>x&?WKif&O~p`@T*Rk=1#-chq5vQSjYtD(Bqv_!4R3EtWM#3CnI z(7UvsqpH^Mz5&D&)GH0jSxdD_Ux9wJyMD~(4K}1;$Vxl>1)E>8`4yWF(L5InwJx{tClT)T@?_Xex0yffI+_(z c59%oQ^;4-|udmgY>Z`R{eWg~fU8^m92c8LhGXMYp literal 0 HcmV?d00001 diff --git a/templates/index.html b/templates/index.html index b5b13d0..f556a48 100644 --- a/templates/index.html +++ b/templates/index.html @@ -21,7 +21,7 @@ viewer.terrainProvider = Cesium.createWorldTerrain(); viewer.scene.globe.shadows=Cesium.ShadowMode.CAST_ONLY viewer.scene.globe.enableLighting = true - viewer.dataSources.add(Cesium.CzmlDataSource.load("/czml")) + viewer.dataSources.add(Cesium.CzmlDataSource.load("{{ url }}")) var now = new Cesium.JulianDate(); viewer.clock.currentTime = now; viewer.clock.shouldAnimate = true