-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathtracker.py
executable file
·227 lines (201 loc) · 8.01 KB
/
tracker.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#
# tracker.py
#
#
import sys
import traceback
import time
from time import sleep
from twitter import *
from configparser import ConfigParser
from string import Template
import datasource
import fa_api
import flightdata
import geomath
import screenshot
# Read the configuration file for this application.
parser = ConfigParser()
parser.read('config.ini')
# Assign AboveTustin variables.
abovetustin_distance_alarm = float(parser.get('abovetustin', 'distance_alarm')) # The alarm distance in miles.
abovetustin_elevation_alarm = float(parser.get('abovetustin', 'elevation_alarm')) # The angle in degrees that indicates if the airplane is overhead or not.
abovetustin_wait_x_updates = int(parser.get('abovetustin', 'wait_x_updates')) # Number of updates to wait after the airplane has left the alarm zone before tweeting.
abovetustin_sleep_time = float(parser.get('abovetustin', 'sleep_time')) # Time between each loop.
# Assign FlightAware variables.
fa_enable = parser.getboolean('flightaware', 'fa_enable')
fa_username = parser.get('flightaware', 'fa_username')
fa_api_key = parser.get('flightaware', 'fa_api_key')
# Assign Twitter variables.
twitter_consumer_key = parser.get('twitter', 'consumer_key')
twitter_consumer_secret = parser.get('twitter', 'consumer_secret')
twitter_access_token = parser.get('twitter', 'access_token')
twitter_access_token_secret = parser.get('twitter', 'access_token_secret')
# Login to twitter.
twit = Twitter(auth=(OAuth(twitter_access_token, twitter_access_token_secret, twitter_consumer_key, twitter_consumer_secret)))
# Given an aircraft 'a' tweet.
# If we have a screenshot, upload it to twitter with the tweet.
def Tweet(a, havescreenshot):
# compile the template arguments
templateArgs = dict()
flight = a.flight or a.hex
flight = flight.replace(" ", "")
templateArgs['flight'] = flight
templateArgs['icao'] = a.hex
templateArgs['icao'] = templateArgs['icao'].replace(" ", "")
templateArgs['dist_mi'] = "%.1f" % a.distance
templateArgs['dist_km'] = "%.1f" % geomath.mi2km(a.distance)
templateArgs['dist_nm'] = "%.1f" % geomath.mi2nm(a.distance)
templateArgs['alt_ft'] = a.altitude
templateArgs['alt_m'] = "%.1f" % geomath.ft2m(a.altitude)
templateArgs['el'] = "%.1f" % a.el
templateArgs['az'] = "%.1f" % a.az
templateArgs['heading'] = geomath.HeadingStr(a.track)
templateArgs['speed_mph'] = "%.1f" % a.speed
templateArgs['speed_kmph'] = "%.1f" % geomath.mi2km(a.speed)
templateArgs['speed_kts'] = "%.1f" % geomath.mi2nm(a.speed)
templateArgs['time'] = a.time.strftime('%H:%M:%S')
templateArgs['squawk'] = a.squawk
templateArgs['vert_rate_ftpm'] = a.vert_rate
templateArgs['vert_rate_mpm'] = "%.1f" % geomath.ft2m(a.vert_rate)
templateArgs['rssi'] = a.rssi
if fa_enable and faInfo:
templateArgs['orig_name'] = faInfo['orig_name']
templateArgs['dest_name'] = faInfo['dest_name']
if faInfo['orig_alt']:
templateArgs['orig_alt'] = faInfo['orig_alt']
else:
templateArgs['orig_alt'] = faInfo['orig_code']
if faInfo['dest_alt']:
templateArgs['dest_alt'] = faInfo['dest_alt']
else:
templateArgs['dest_alt'] = faInfo['dest_code']
if faInfo['dest_city']:
templateArgs['dest_city'] = faInfo['dest_city']
if faInfo['orig_city']:
templateArgs['orig_city'] = faInfo['orig_city']
if templateArgs['orig_alt'] and templateArgs['dest_alt']:
tweet = Template(parser.get('tweet', 'fa_tweet_template')).substitute(templateArgs)
else:
tweet = Template(parser.get('tweet', 'tweet_template')).substitute(templateArgs)
else:
tweet = Template(parser.get('tweet', 'tweet_template')).substitute(templateArgs)
#conditional hashtags:
hashtags = []
if a.time.hour < 7 or a.time.hour >= 23 or (a.time.weekday() == 7 and a.time.hour < 8):
hashtags.append(" #AfterHours")
if a.altitude < 1000:
hashtags.append(" #2CloseForComfort")
if a.altitude >= 1000 and a.altitude < 2500 and (templateArgs['heading'] == "S" or templateArgs['heading'] == "SW"):
hashtags.append(" #ProbablyLanding")
if a.altitude > 20000 and a.altitude < 35000:
hashtags.append(" #UpInTheClouds")
if a.altitude >= 35000:
hashtags.append(" #WayTheHeckUpThere")
if a.speed > 300 and a.speed < 500:
hashtags.append(" #MovingQuickly")
if a.speed >= 500 and a.speed < 770:
hashtags.append(" #FlyingFast")
if a.speed >= 700:
hashtags.append(" #SpeedDemon")
# add the conditional hashtags as long as there is room in 140 chars
for hash in hashtags:
if len(tweet) + len(hash) <= 280:
tweet += hash
# add the default hashtags as long as there is room
for hash in parser.get('tweet', 'default_hashtags').split(' '):
if len(tweet) + len(hash) <= 279:
tweet += " " + hash
# send tweet to twitter!
if havescreenshot:
with open('tweet.png', "rb") as imagefile:
imagedata = imagefile.read()
params = {"media[]": imagedata, "status": tweet}
twit.statuses.update_with_media(**params)
else:
twit.statuses.update(status=tweet)
# send the tweet to stdout while we're at it
print(tweet)
if __name__ == "__main__":
lastReloadTime = time.time()
display = datasource.get_map_source()
alarms = dict() # dictonary of all aircraft that have triggered the alarm
# Indexed by it's hex code, each entry contains a tuple of
# the aircraft data at the closest position so far, and a
# counter. Once the airplane is out of the alarm zone,
# the counter is incremented until we hit [abovetustin_wait_x_updates]
# (defined above), at which point we then Tweet
fd = datasource.get_data_source()
lastTime = fd.time
while True:
if time.time() > lastReloadTime + 3600 and len(alarms) == 0:
print("one hour since last browser reload... reloading now")
display.reload()
lastReloadTime = time.time()
sleep(abovetustin_sleep_time)
fd.refresh()
if fd.time == lastTime:
continue
lastTime = fd.time
print("Now: {}".format(fd.time))
current = dict() # current aircraft inside alarm zone
# loop on all the aircarft in the receiver
for a in fd.aircraft:
# if they don't have lat/lon or a heading skip them
if a.lat == None or a.lon == None or a.track == None:
continue
# check to see if it's in the alarm zone:
if a.distance < abovetustin_distance_alarm or a.el > abovetustin_elevation_alarm:
# add it to the current dictionary
current[a.hex] = a
print("{}: {}mi, {}az, {}el, {}alt, {}dB, {}seen".format(
a.ident_desc(), "%.1f" % a.distance, "%.1f" % a.az, "%.1f" % a.el,
a.altitude, "%0.1f" % a.rssi, "%.1f" % (a.seen or 0)))
if a.hex in alarms:
#if it's already in the alarms dict, check to see if we're closer
if a.distance < alarms[a.hex][0].distance:
#if we're closer than the one already there, then overwrite it
alarms[a.hex] = (a, 0)
else:
#add it to the alarms
alarms[a.hex] = (a, 0)
finishedalarms = []
# loop on all the aircraft in the alarms dict
for h, a in alarms.items():
found = False
# check to see if it's in the current set of aircraft
for h2, a2 in current.items():
if h2 == h:
print("{} not yet, dist, elv: {}, {}".format(h, "%.1f" % a[0].distance, "%.1f" % a[0].el))
found = True
break
# if it wasn't in the current set of aircraft, that means it's time to tweet!
if not found:
if a[1] < abovetustin_wait_x_updates:
alarms[h] = (a[0], a[1]+1)
else:
havescreenshot = False
if display != None:
print("time to create screenshot of {}:".format(a[0]))
hexcode = a[0].hex
hexcode = hexcode.replace(" ", "")
hexcode = hexcode.replace("~", "")
havescreenshot = display.clickOnAirplane(hexcode)
if fa_enable:
print("Getting FlightAware flight details")
faInfo = fa_api.FlightInfo(a[0].flight, fa_username, fa_api_key)
else:
faInfo = False
print("time to tweet!!!!!")
try:
Tweet(a[0], havescreenshot)
except Exception:
print("exception in Tweet():")
traceback.print_exc()
finishedalarms.append(a[0].hex)
# for each alarm that is finished, delete it from the dictionary
for h in finishedalarms:
del(alarms[h])
# flush output for following in log file
sys.stdout.flush()