实时飞行航班跟踪系统
这个代码是根据每个民航飞机上的ADS-B信号交换系统的数据进行分析的,每个民航飞机在飞行中,ADS-B会不断广播信号,这个信息包括了大量信息,航班号,航线,GPS的位置信息和高度信息等.以前我也通过改过的电视棒,接收ADS-B的消息,查看头顶的飞机的信息.今天我们通过调用被称作"虚拟雷达服务系统"的网站服务(Virtual Radar Server),来获取全球的ADS-B信息,再配合地图信息,我们就可以查看全球任何地方的飞机航班的实时信息.
01. "虚拟雷达服务系统"(Virtual Radar Server)
Virtual Radar Server是一套web API,提供全球的所有航班的ADS-B的信息.
我们以北京首都机场为例,机场的坐标为: 116.609226,40.084729.
以下的坐标我们全部通过百度的拾取坐标系统完成.(http://api.map.baidu.com/lbsapi/getpoint/index.html)
包括:lat,lon和地图的级别(level).
Virtual Radar Server的服务调用很简单,以北京机场为例,我们发出http的请求:http://public-api.adsbexchange.com/VirtualRadar/AircraftList.json?lat=40.084729&lng=116.609226&fDstL=0&fDstU=20
返回数据为:
"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}
这个信息很丰富包括北京机场空域的当前查询的时间实时航班状况,很翔实吧,除了上边的信息还有机型和飞行年限,国籍等等.
02. 地图系统
有了ADS-B的信息,我们需要一套地图系统,把航班信息实时显示出来,达到实时跟踪的目的.
本着极客的开源精神,我们采用开源的GIS系统,那就是大名鼎鼎的OpenStreetMap(简称OSM),开源wiki地图.当然也不用自己造轮子,
采用cartopy的库,已经封装的很好了.
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网站的文章,链接如下:create-simple-live-flight-tracking-python
本人出于兴趣和好奇心,做这个测试和学习,请大家不要把本代码用于商业用途和其他违反法律的用途.