實(shí)時飛行航班跟蹤系統(tǒng)
這個代碼是根據(jù)每個民航飛機(jī)上的ADS-B信號交換系統(tǒng)的數(shù)據(jù)進(jìn)行分析的,每個民航飛機(jī)在飛行中,ADS-B會不斷廣播信號,這個信息包括了大量信息,航班號,航線,GPS的位置信息和高度信息等.以前我也通過改過的電視棒,接收ADS-B的消息,查看頭頂?shù)娘w機(jī)的信息.今天我們通過調(diào)用被稱作"虛擬雷達(dá)服務(wù)系統(tǒng)"的網(wǎng)站服務(wù)(Virtual Radar Server),來獲取全球的ADS-B信息,再配合地圖信息,我們就可以查看全球任何地方的飛機(jī)航班的實(shí)時信息.
01. "虛擬雷達(dá)服務(wù)系統(tǒng)"(Virtual Radar Server)
Virtual Radar Server是一套web API,提供全球的所有航班的ADS-B的信息.
我們以北京首都機(jī)場為例,機(jī)場的坐標(biāo)為: 116.609226,40.084729.
以下的坐標(biāo)我們?nèi)客ㄟ^百度的拾取坐標(biāo)系統(tǒng)完成.(http://api.map.baidu.com/lbsapi/getpoint/index.html)
包括:lat,lon和地圖的級別(level).
Virtual Radar Server的服務(wù)調(diào)用很簡單,以北京機(jī)場為例,我們發(fā)出http的請求:http://public-api.adsbexchange.com/VirtualRadar/AircraftList.json?lat=40.084729&lng=116.609226&fDstL=0&fDstU=20
返回?cái)?shù)據(jù)為:
"src":1,"feeds":[{"id":1,"name":"From Cons","polarPlot":false}],"srcFeed":1,"showSil":true,"showFlg":true,"showPic":true,"flgH":20,"flgW":85,"acList":
[{"Id":7869665,"Rcvr":1,"HasSig":false,"Icao":"7814E1","Bad":false,"Reg":"B-205R","FSeen":"\/Date(1545566038556)\/","TSecs":32,"CMsgs":9,"Alt":1200,"GAlt":1752,"InHg":30.4724388,"AltT":0,"Lat":39.997192,"Long":116.586182,"PosTime":1545566049218,"Mlat":false,"Tisb":false,"Spd":140.0,"Trak":350.0,"TrkH":false,"Type":"B738","Mdl":"Boeing 737NG 800/W","Man":"Boeing","CNum":"61691","Op":"China Eastern Airlines","OpIcao":"CES","Sqk":"6255","Help":false,"Vsi":-830,"VsiT":0,"Dst":9.93,"Brng":191.4,"WTC":2,"Species":1,"Engines":"2","EngType":3,"EngMount":0,"Mil":false,"Cou":"China","HasPic":false,"Interested":false,"FlightsCount":0,"SpdTyp":0,"CallSus":false,"Trt":2,"Year":"2018"},
{"Id":7865354,"Rcvr":1,"HasSig":false,"Icao":"78040A","Bad":false,"Reg":"B-6610","FSeen":"\/Date(1545565998339)\/","TSecs":72,"CMsgs":9,"Alt":3475,"GAlt":4027,"InHg":30.4724388,"AltT":0,"Lat":40.154663,"Long":116.58508,"PosTime":1545566064133,"Mlat":false,"Tisb":false,"Spd":200.0,"Trak":350.0,"TrkH":false,"Type":"A320","Mdl":"Airbus A320 214","Man":"Airbus","CNum":"3221","Op":"Air China","OpIcao":"CCA","Sqk":"3074","Help":false,"Vsi":1530,"VsiT":0,"Dst":8.04,"Brng":345.2,"WTC":2,"Species":1,"Engines":"2","EngType":3,"EngMount":0,"Mil":false,"Cou":"China","HasPic":false,"Interested":false,"FlightsCount":0,"SpdTyp":0,"CallSus":false,"Trt":2,"Year":"2007"},
{"Id":10897700,"Rcvr":1,"HasSig":false,"Icao":"A64924","Bad":false,"Reg":"N504DN","FSeen":"\/Date(1545565975827)\/","TSecs":95,"CMsgs":18,"Alt":3550,"GAlt":4102,"InHg":30.4724388,"AltT":0,"Lat":40.197876,"Long":116.583008,"PosTime":1545566045902,"Mlat":false,"Tisb":false,"Spd":240.0,"TrkH":false,"Type":"A359","Mdl":"Airbus A350 941","Man":"Airbus","CNum":"160","Op":"Delta Air Lines","OpIcao":"DAL","Sqk":"0023","Help":false,"Vsi":640,"VsiT":0,"Dst":12.78,"Brng":350.0,"WTC":3,"Species":1,"Engines":"2","EngType":3,"EngMount":0,"Mil":false,"Cou":"United States","HasPic":false,"Interested":false,"FlightsCount":0,"SpdTyp":0,"CallSus":false,"Trt":2,"Year":"2017"},
{"Id":7866011,"Rcvr":1,"HasSig":false,"Icao":"78069B","Bad":false,"Reg":"B-6713","FSeen":"\/Date(1545565926840)\/","TSecs":144,"CMsgs":24,"Alt":1050,"GAlt":1602,"InHg":30.4724388,"AltT":0,"Call":"CES5274","Lat":40.004883,"Long":116.584961,"PosTime":1545565937704,"Mlat":false,"PosStale":true,"Tisb":false,"Spd":130.0,"Trak":350.0,"TrkH":false,"Type":"A320","Mdl":"Airbus A320 232","Man":"Airbus","CNum":"4342","From":"ZGSZ Shenzhen Bao'an, China","To":"ZSSS Shanghai Hongqiao, China","Op":"China Eastern Airlines","OpIcao":"CES","Sqk":"1506","Help":false,"Vsi":-760,"VsiT":0,"Dst":9.12,"Brng":193.1,"WTC":2,"Species":1,"Engines":"2","EngType":3,"EngMount":0,"Mil":false,"Cou":"China","HasPic":false,"Interested":false,"FlightsCount":0,"SpdTyp":0,"CallSus":false,"Trt":2,"Year":"2010"},{"Id":7868555,"Rcvr":1,"HasSig":false,"Icao":"78108B","Bad":false,"Reg":"B-8651","FSeen":"\/Date(1545565908661)\/","TSecs":162,"CMsgs":29,"Alt":5550,"GAlt":6102,"InHg":30.4724388,"AltT":0,"Call":"CES5130","Lat":40.227539,"Long":116.59082,"PosTime":1545565926445,"Mlat":false,"PosStale":true,"Tisb":false,"Spd":250.0,"Trak":10.0,"TrkH":false,"Type":"A321","Mdl":"Airbus A321 211SL","Man":"Airbus","CNum":"7446","From":"ZBAA Beijing Capital, China","To":"ZSPD Shanghai Pudong, China","Op":"China Eastern Airlines","OpIcao":"CES","Sqk":"","Vsi":3390,"VsiT":0,"Dst":15.96,"Brng":354.4,"WTC":2,"Species":1,"Engines":"2","EngType":3,"EngMount":0,"Mil":false,"Cou":"China","HasPic":false,"Interested":false,"FlightsCount":0,"SpdTyp":0,"CallSus":false,"Trt":2,"Year":"2016"},{"Id":7866095,"Rcvr":1,"HasSig":false,"Icao":"7806EF","Bad":false,"Reg":"B-6741","FSeen":"\/Date(1545565762309)\/","TSecs":308,"CMsgs":54,"Alt":1550,"GAlt":2102,"InHg":30.4724388,"AltT":0,"Lat":40.107056,"Long":116.61853,"PosTime":1545565849855,"Mlat":false,"PosStale":true,"Tisb":false,"Spd":150.0,"Trak":20.0,"TrkH":false,"Type":"A321","Mdl":"Airbus A321 232","Man":"Airbus","CNum":"4617","Op":"Air China","OpIcao":"CCA","Sqk":"5644","Help":false,"Vsi":3130,"VsiT":0,"Dst":2.61,"Brng":17.7,"WTC":2,"Species":1,"Engines":"2","EngType":3,"EngMount":0,"Mil":false,"Cou":"China","HasPic":false,"Interested":false,"FlightsCount":0,"SpdTyp":0,"CallSus":false,"Trt":2,"Year":"2011"},{"Id":7865006,"Rcvr":1,"HasSig":false,"Icao":"7802AE","Bad":false,"Reg":"B-6292","FSeen":"\/Date(1545565737249)\/","TSecs":333,"CMsgs":48,"Alt":3175,"GAlt":3727,"InHg":30.4724388,"AltT":0,"Lat":40.154297,"Long":116.585449,"PosTime":1545565750441,"Mlat":false,"PosStale":true,"Tisb":false,"Spd":230.0,"Trak":350.0,"TrkH":false,"Type":"A320","Mdl":"Airbus A320 214","Man":"Airbus","CNum":"2960","Op":"China Southern Airlines","OpIcao":"CSN","Sqk":"3042","Help":false,"Vsi":2170,"VsiT":0,"Dst":8.0,"Brng":345.4,"WTC":2,"Species":1,"Engines":"2","EngType":3,"EngMount":0,"Mil":false,"Cou":"China","HasPic":false,"Interested":false,"FlightsCount":0,"SpdTyp":0,"CallSus":false,"Trt":2,"Year":"2006"},{"Id":7869825,"Rcvr":1,"HasSig":false,"Icao":"781581","Bad":false,"Reg":"B-304D","FSeen":"\/Date(1545565691016)\/","TSecs":380,"CMsgs":55,"Alt":1900,"GAlt":2452,"InHg":30.4724388,"AltT":0,"Call":"CES5121","Lat":39.963867,"Long":116.591431,"PosTime":1545565707209,"Mlat":false,"PosStale":true,"Tisb":false,"Spd":150.0,"Trak":350.0,"TrkH":false,"Type":"A359","Mdl":"Airbus A350 941","Man":"Airbus","CNum":"248","From":"ZSSS Shanghai Hongqiao, China","To":"ZBAA Beijing Capital, China","Op":"China Eastern Airlines","OpIcao":"CES","Sqk":"","Vsi":-960,"VsiT":0,"Dst":13.52,"Brng":186.4,"WTC":3,"Species":1,"Engines":"2","EngType":3,"EngMount":0,"Mil":false,"Cou":"China","HasPic":false,"Interested":false,"FlightsCount":0,"SpdTyp":0,"CallSus":false,"Trt":2,"Year":"2018"},{"Id":7868557,"Rcvr":1,"HasSig":false,"Icao":"78108D","Bad":false,"Reg":"B-8653","FSeen":"\/Date(1545565395118)\/","TSecs":676,"CMsgs":103,"Alt":875,"GAlt":1427,"InHg":30.4724388,"AltT":0,"Lat":40.0979,"Long":116.59375,"PosTime":1545565395118,"Mlat":false,"PosStale":true,"Tisb":false,"Spd":150.0,"Trak":350.0,"TrkH":false,"Type":"A321","Mdl":"Airbus A321 211SL","Man":"Airbus","CNum":"7360","Op":"China Eastern Airlines","OpIcao":"CES","Sqk":"5645","Help":false,"Vsi":2300,"VsiT":0,"Dst":1.97,"Brng":318.1,"WTC":2,"Species":1,"Engines":"2","EngType":3,"EngMount":0,"Mil":false,"Cou":"China","HasPic":false,"Interested":false,"FlightsCount":0,"SpdTyp":0,"CallSus":false,"Trt":2,"Year":"2016"},{"Id":7864902,"Rcvr":1,"HasSig":false,"Icao":"780246","Bad":false,"Reg":"B-1752","FSeen":"\/Date(1545565305511)\/","TSecs":765,"CMsgs":114,"Alt":17700,"GAlt":18252,"InHg":30.4724388,"AltT":0,"Lat":40.189819,"Long":116.592896,"PosTime":1545565422854,"Mlat":false,"PosStale":true,"Tisb":false,"Spd":300.0,"Trak":3.3,"TrkH":false,"Type":"B738","Mdl":"Boeing 737NG 89P/W","Man":"Boeing","CNum":"61310","Op":"China United Airlines","OpIcao":"CUA","Sqk":"4132","Help":false,"Vsi":0,"VsiT":0,"Dst":11.77,"Brng":353.2,"WTC":2,"Species":1,"Engines":"2","EngType":3,"EngMount":0,"Mil":false,"Cou":"China","HasPic":false,"Interested":false,"FlightsCount":0,"SpdTyp":0,"CallSus":false,"Trt":2,"Year":"2014"}],"totalAc":6973,"lastDv":"636811040952533347","shtTrlSec":65,"stm":1545566071058}
這個信息很豐富包括北京機(jī)場空域的當(dāng)前查詢的時間實(shí)時航班狀況,很翔實(shí)吧,除了上邊的信息還有機(jī)型和飛行年限,國籍等等.
02. 地圖系統(tǒng)
有了ADS-B的信息,我們需要一套地圖系統(tǒng),把航班信息實(shí)時顯示出來,達(dá)到實(shí)時跟蹤的目的.
本著極客的開源精神,我們采用開源的GIS系統(tǒng),那就是大名鼎鼎的OpenStreetMap(簡稱OSM),開源wiki地圖.當(dāng)然也不用自己造輪子,
采用cartopy的庫,已經(jīng)封裝的很好了.
OpenStreetMap
03.代碼
import urllib.request
import json
import matplotlib.pyplot as plt
from matplotlib import animation
import cartopy.crs as ccrs
from cartopy.io.img_tiles import OSM
"""
bj: 116.609226,40.084729
p0: 116.305383,40.415131
p1: 116.972285,39.88748
"""
anotation_list = []
# SET AXES
fig, ax = plt.subplots()
ax = plt.axes(projection=ccrs.PlateCarree())
ax.set_ylim(39.8874, 40.4151)
ax.set_xlim(116.3054, 116.9722)
# ADD OSM BASEMAP
osm_tiles = OSM()
ax.add_image(osm_tiles, 11) # Zoom Level 13
# PLOT Beijing Captial AIRPORT
ax.text(116.609226, 40.084729, 'Beijing', horizontalalignment='right', size='large')
ax.plot([116.609226], [40.084729], 'bo')
# PLOT TRACK
track, = ax.plot([], [], 'ro')
opener = urllib.request.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
# UPDATE FUNCTION
def update(self):
# SEND QUERY
fp = opener.open(
'http://public-api.adsbexchange.com/VirtualRadar/AircraftList.json?lat=40.084729&lng=116.609226&fDstL=0&fDstU=20')
mybyte = fp.read()
mystr = mybyte.decode("utf8")
js_str = json.loads(mystr)
print(mystr)
fp.close()
lat_list = []
long_list = []
op_list = [] # OPERATOR LIST
for num, flight_data in enumerate(js_str['acList']):
lat = flight_data['Lat']
lon = flight_data['Long']
lat_list.append(lat)
long_list.append(lon)
try:
op_list.append(flight_data['Op']) # STORE OPERATOR DATA INTO LIST
except:
op_list.append('Null')
track.set_data(long_list, lat_list)
# LABELING
# REMOVE LABEL
for num, annot in enumerate(anotation_list):
annot.remove()
anotation_list[:] = []
# CREATE LABEL CONTAINER
for num, annot in enumerate(js_str['acList']):
annotation = ax.annotate('text', xy=(0, 0), size='smaller')
anotation_list.append(annotation)
# UPDATE LABEL POSITION AND OPERATOR
for num, ano in enumerate(anotation_list):
ano.set_position((long_list[num], lat_list[num]))
ano.xy = (long_list[num], lat_list[num])
txt_op = str(op_list[num])
ano.set_text(txt_op)
return track,
# UPDATING EVERY SECOND
anim = animation.FuncAnimation(fig, update, interval=2000, blit=False)
plt.show()
04. 后記
本代碼參照了GEODOSE網(wǎng)站的文章,鏈接如下:create-simple-live-flight-tracking-python
本人出于興趣和好奇心,做這個測試和學(xué)習(xí),請大家不要把本代碼用于商業(yè)用途和其他違反法律的用途.