01234567890123456789012345678901234567890123456789012345678901234567890123456789
445446447448449450451452453454455456457458459460461462463464 465466467468469470471472473474475476477478479480481482483484 11901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230 57705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798 5799 58005801580258035804580558065807 5808580958105811 581258135814581558165817 58185819582058215822582358245825582658275828582958305831583258335834583558365837 71047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147 720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241 72427243724472457246724772487249725072517252725372547255725672577258725972607261 72667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306 |
<----SKIPPED LINES---->
AIRCRAFT_LENGTH['Cessna Conquest 2 (twin-turboprop)'] = 11.89
AIRCRAFT_LENGTH['Cessna Skyhawk (piston-single)'] = 8.28
AIRCRAFT_LENGTH['Cessna Skylane (piston-single)'] = 8.84
AIRCRAFT_LENGTH['CESSNA T182 Turbo Skylane (piston-single)'] = 8.84
AIRCRAFT_LENGTH['Cessna T206 Turbo Stationair (piston-single)'] = 8.61
AIRCRAFT_LENGTH['Cessna 421 (twin-piston)'] = 11.09
AIRCRAFT_LENGTH['Cirrus SR-20 (piston-single)'] = 7.92
AIRCRAFT_LENGTH['Cirrus SR-22 (piston-single)'] = 7.92
AIRCRAFT_LENGTH['Cirrus SR22 Turbo (piston-single)'] = 7.92
AIRCRAFT_LENGTH['Cirrus Vision SF50 (single-jet)'] = 9.42
AIRCRAFT_LENGTH['Daher-Socata TBM-900 (single-turboprop)'] = 10.72
AIRCRAFT_LENGTH['Dassault Falcon 50 (tri-jet)'] = 18.52
AIRCRAFT_LENGTH['Dassault Falcon 2000 (twin-jet)'] = 20.23
AIRCRAFT_LENGTH['Dassault Falcon 900 (tri-jet)'] = 20.21
AIRCRAFT_LENGTH['Embraer 170/175 (twin-jet)'] = (29.90 + 31.68) / 2
AIRCRAFT_LENGTH['EMBRAER 175 (long wing) (twin-jet)'] = 31.68
AIRCRAFT_LENGTH['Embraer ERJ-135 (twin-jet)'] = 26.33
AIRCRAFT_LENGTH['Embraer ERJ-145 (twin-jet)'] = 29.87
AIRCRAFT_LENGTH['Embraer ERJ 175 (twin-jet)'] = 31.68
AIRCRAFT_LENGTH['Embraer ERJ 190 (twin-jet)'] = 36.25
AIRCRAFT_LENGTH['Embraer Legacy 450 (twin-jet)'] = 19.69
AIRCRAFT_LENGTH['Embraer Legacy 550 (twin-jet)'] = 20.74
AIRCRAFT_LENGTH['Embraer Legacy 600/650 (twin-jet)'] = 26.33
AIRCRAFT_LENGTH['Embraer Phenom 300 (twin-jet)'] = 15.9
AIRCRAFT_LENGTH['Eurocopter EC-635 (twin-turboshaft)'] = 10.21
AIRCRAFT_LENGTH['Fairchild Dornier 328JET (twin-jet)'] = 21.11
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream 3 (twin-jet)'] = 25.32
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G450 (twin-jet)'] = 27.23
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G550 (twin-jet)'] = 29.39
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G650 (twin-jet)'] = 30.41
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream IV (twin-jet)'] = 26.92
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream V (twin-jet)'] = 29.4
AIRCRAFT_LENGTH['Hawker Beechcraft 4000 (twin-jet)'] = 21.08
AIRCRAFT_LENGTH['Honda HondaJet (twin-jet)'] = 12.99
AIRCRAFT_LENGTH['IAI Gulfstream G100 (twin-jet)'] = 16.94
AIRCRAFT_LENGTH['IAI Gulfstream G150 (twin-jet)'] = 16.94
AIRCRAFT_LENGTH['IAI Gulfstream G200 (twin-jet)'] = 18.97
AIRCRAFT_LENGTH['IAI Gulfstream G280 (twin-jet)'] = 20.3
AIRCRAFT_LENGTH['Learjet 31 (twin-jet)'] = 14.83
AIRCRAFT_LENGTH['Learjet 35 (twin-jet)'] = 14.83
<----SKIPPED LINES---->
Args:
filename: string of the filename to open, potentially also including the
full path.
log_exception: boolean indicating whether to log an exception if file not
found.
Returns:
Return text string of file contents.
"""
try:
with open(filename, 'r') as content_file:
file_contents = content_file.read()
except IOError:
if log_exception:
Log('Unable to read '+filename)
return ''
return file_contents
# because reading is ~25x more expensive than getmtime, we will only read &
# parse if the getmtime is more recent than last call for this file. So this
# dict stores the a tuple, the last time read & the resulting parsed return
# value
CACHED_FILES = {}
def ReadAndParseSettings(filename):
"""Reads filename and parses the resulting key-value pairs into a dict."""
global CACHED_FILES
(last_read_time, settings) = CACHED_FILES.get(filename, (0, {}))
if os.path.exists(filename):
last_modified = os.path.getmtime(filename)
if last_modified > last_read_time:
setting_str = ReadFile(filename)
settings = ParseSettings(setting_str)
CACHED_FILES[filename] = (last_modified, settings)
return settings
# File does not - or at least no longer - exists; so remove the cache
if filename in CACHED_FILES:
CACHED_FILES.pop(filename)
return {}
<----SKIPPED LINES---->
whether the current active json changed from the prior one.
Returns:
Boolean - True if different (and processing needed), False if identical
"""
if SIMULATION_COUNTER == 0:
return True
(this_json, unused_now) = DUMP_JSONS[SIMULATION_COUNTER]
(last_json, unused_now) = DUMP_JSONS[SIMULATION_COUNTER - 1]
return this_json != last_json
def CheckRebootNeeded(
startup_time, message_queue, json_desc_dict, configuration):
"""Reboot based on duration instance has been running.
Reboot needed in one of the following situations:
- All quiet: if running for over 24 hours and all is quiet (message queue
empty, no planes in radio, and backup not currently in process).
- Mostly quiet: if running for over 36 hours and message queue is empty and
it's 3a.
- Reboot requested via html form.
Also checks if reset requested via html form.
"""
reboot = False
global SHUTDOWN_SIGNAL
running_hours = (time.time() - startup_time) / SECONDS_IN_HOUR
if (
running_hours >= HOURS_IN_DAY and
not message_queue and
not json_desc_dict.get('radio_range_flights') and
# script /home/pi/splitflap/backup.sh creates temp file in this
# directory; after it is copied to the NAS, it is deleted
not os.listdir('/media/backup')):
msg = 'All quiet reboot needed after running for %.2f hours' % running_hours
SHUTDOWN_SIGNAL = msg
Log(msg)
reboot = True
if (
running_hours > HOURS_IN_DAY * 1.5 and
not message_queue and
int(EpochDisplayTime(time.time(), '%-H')) >= 3):
msg = ('Early morning reboot needed after running for %.2f hours'
% running_hours)
SHUTDOWN_SIGNAL = msg
Log(msg)
reboot = True
if 'soft_reboot' in configuration:
msg = 'Soft reboot requested via web form'
SHUTDOWN_SIGNAL = msg
Log(msg)
reboot = True
RemoveSetting(configuration, 'soft_reboot')
if 'end_process' in configuration:
msg = 'Process end requested via web form'
SHUTDOWN_SIGNAL = msg
Log(msg)
RemoveSetting(configuration, 'end_process')
return reboot
<----SKIPPED LINES---->
# We repeat the loop every x seconds; this ensures that if the processing
# time is long, we don't wait another x seconds after processing completes
next_loop_time = time.time() + LOOP_DELAY_SECONDS
# These files are read only if the version on disk has been modified more
# recently than the last time it was read
last_dump_json_timestamp = 0
init_timing.append((time.time(), 7))
WaitUntilKillComplete(already_running_ids)
init_timing.append((time.time(), 8))
personal_message = None # Unknown what personal message is displayed
temp_last_logged = 0 # Keeps track of when temperature was last logged
LogTimes(init_timing)
reboot = False
iteration = 0 # counter that tracks how many times thru while loop
start_time = time.time()
if initial_memory_dump:
DumpMemorySnapsnot(
configuration, iteration, start_time, initial_frame_count)
Log('Finishing initialization of %d; starting radio polling loop' %
os.getpid())
while ((not SIMULATION or SIMULATION_COUNTER < len(DUMP_JSONS))
and not SHUTDOWN_SIGNAL):
last_heartbeat_time = Heartbeat(last_heartbeat_time)
new_configuration = ReadAndParseSettings(CONFIG_FILE)
UpdateRollingLogSize(new_configuration)
CheckForNewFilterCriteria(
configuration, new_configuration, message_queue, flights)
configuration = new_configuration
ResetLogs(configuration) # clear the logs if requested
UpdateRollingLogSize(configuration)
# if this is a SIMULATION, then process every diff dump. But if it
# isn't a simulation, then only read & do related processing for the
# next dump if the last-modified timestamp indicates the file has been
<----SKIPPED LINES---->
insight_messages = CreateFlightInsights(
flights,
configuration.get('insights'),
insight_message_distribution)
if configuration.get('next_flight', 'off') == 'on':
next_flight_text = FlightInsightNextFlight(flights, configuration)
if next_flight_text:
insight_messages.insert(0, next_flight_text)
insight_messages = [(FLAG_MSG_INSIGHT, m) for m in insight_messages]
for insight_message in insight_messages:
message_queue.insert(0, insight_message)
else: # flight didn't meet display criteria
flight['insight_types'] = []
PickleObjectToFile(
flight, PICKLE_FLIGHTS, True, timestamp=flight['now'])
# now that we've saved the flight, we have no more need to keep the
# memory-hogging persistent_path key of that flight in live memory
if 'persistent_path' in flights[-1]:
del flights[-1]['persistent_path']
else:
remote, servo = RefreshArduinos(
remote, servo,
to_remote_q, to_servo_q, to_main_q, shutdown,
flights, json_desc_dict, configuration, screen_history)
message_queue, next_message_time = ProcessArduinoCommmands(
to_main_q, flights, configuration, message_queue, next_message_time)
personal_message = PersonalMessage(
configuration, message_queue, personal_message)
if SIMULATION:
if now:
simulated_hour = EpochDisplayTime(now, '%Y-%m-%d %H:00%z')
if simulated_hour != prev_simulated_hour:
print(simulated_hour)
prev_simulated_hour = simulated_hour
histogram = ReadAndParseSettings(HISTOGRAM_CONFIG_FILE)
RemoveFile(HISTOGRAM_CONFIG_FILE)
# We also need to make sure there are flights on which to generate a
# histogram! Why might there not be any flights? Primarily during a
# simulation, if there's a lingering histogram file at the time of
# history restart.
if histogram and not flights:
Log('Histogram requested (%s) but no flights in memory' % histogram)
if histogram and flights:
message_queue.extend(TriggerHistograms(flights, histogram))
if message_queue: # Any personal message displayed has been cleared
<----SKIPPED LINES---->
message_queue, next_message_time, configuration, screen_history)
reboot = CheckRebootNeeded(
startup_time, message_queue, json_desc_dict, configuration)
temp_last_logged = CheckTemperature(configuration, temp_last_logged)
if not SIMULATION:
time.sleep(max(0, next_loop_time - time.time()))
next_loop_time = time.time() + LOOP_DELAY_SECONDS
else:
SIMULATION_COUNTER += 1
if simulation_slowdown:
SimulationSlowdownNearFlight(flights, persistent_nearby_aircraft)
# now that we've completed the loop, lets potentially dump the
# memory snapshot
iteration += 1 # this completes the iteration-th time thru the loop
if initial_memory_dump:
DumpMemorySnapsnot(
configuration, iteration, start_time, initial_frame_count)
if SIMULATION:
SimulationEnd(message_queue, flights, screen_history)
PerformGracefulShutdown(shutdown, reboot)
if __name__ == "__main__":
#interrupt, as in ctrl-c
signal.signal(signal.SIGINT, InterruptShutdownFromSignal)
#terminate, when another instance found or via kill
signal.signal(signal.SIGTERM, InterruptShutdownFromSignal)
if '-i' in sys.argv:
BootstrapInsightList()
else:
main_settings = ReadAndParseSettings(CONFIG_FILE)
if 'code_profiling_enabled' in main_settings:
import cProfile
cProfile.run(
<----SKIPPED LINES---->
|
01234567890123456789012345678901234567890123456789012345678901234567890123456789
445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485 11911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231 5771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846 71137114711571167117711871197120712171227123712471257126712771287129713071317132 71337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155 72147215721672177218721972207221722272237224722572267227722872297230723172327233 7234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285 72907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330 |
<----SKIPPED LINES---->
AIRCRAFT_LENGTH['Cessna Conquest 2 (twin-turboprop)'] = 11.89
AIRCRAFT_LENGTH['Cessna Skyhawk (piston-single)'] = 8.28
AIRCRAFT_LENGTH['Cessna Skylane (piston-single)'] = 8.84
AIRCRAFT_LENGTH['CESSNA T182 Turbo Skylane (piston-single)'] = 8.84
AIRCRAFT_LENGTH['Cessna T206 Turbo Stationair (piston-single)'] = 8.61
AIRCRAFT_LENGTH['Cessna 421 (twin-piston)'] = 11.09
AIRCRAFT_LENGTH['Cirrus SR-20 (piston-single)'] = 7.92
AIRCRAFT_LENGTH['Cirrus SR-22 (piston-single)'] = 7.92
AIRCRAFT_LENGTH['Cirrus SR22 Turbo (piston-single)'] = 7.92
AIRCRAFT_LENGTH['Cirrus Vision SF50 (single-jet)'] = 9.42
AIRCRAFT_LENGTH['Daher-Socata TBM-900 (single-turboprop)'] = 10.72
AIRCRAFT_LENGTH['Dassault Falcon 50 (tri-jet)'] = 18.52
AIRCRAFT_LENGTH['Dassault Falcon 2000 (twin-jet)'] = 20.23
AIRCRAFT_LENGTH['Dassault Falcon 900 (tri-jet)'] = 20.21
AIRCRAFT_LENGTH['Embraer 170/175 (twin-jet)'] = (29.90 + 31.68) / 2
AIRCRAFT_LENGTH['EMBRAER 175 (long wing) (twin-jet)'] = 31.68
AIRCRAFT_LENGTH['Embraer ERJ-135 (twin-jet)'] = 26.33
AIRCRAFT_LENGTH['Embraer ERJ-145 (twin-jet)'] = 29.87
AIRCRAFT_LENGTH['Embraer ERJ 175 (twin-jet)'] = 31.68
AIRCRAFT_LENGTH['Embraer ERJ 190 (twin-jet)'] = 36.25
AIRCRAFT_LENGTH['Embraer ERJ-190 (twin-jet)'] = 36.25
AIRCRAFT_LENGTH['Embraer Legacy 450 (twin-jet)'] = 19.69
AIRCRAFT_LENGTH['Embraer Legacy 550 (twin-jet)'] = 20.74
AIRCRAFT_LENGTH['Embraer Legacy 600/650 (twin-jet)'] = 26.33
AIRCRAFT_LENGTH['Embraer Phenom 300 (twin-jet)'] = 15.9
AIRCRAFT_LENGTH['Eurocopter EC-635 (twin-turboshaft)'] = 10.21
AIRCRAFT_LENGTH['Fairchild Dornier 328JET (twin-jet)'] = 21.11
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream 3 (twin-jet)'] = 25.32
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G450 (twin-jet)'] = 27.23
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G550 (twin-jet)'] = 29.39
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream G650 (twin-jet)'] = 30.41
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream IV (twin-jet)'] = 26.92
AIRCRAFT_LENGTH['Gulfstream Aerospace Gulfstream V (twin-jet)'] = 29.4
AIRCRAFT_LENGTH['Hawker Beechcraft 4000 (twin-jet)'] = 21.08
AIRCRAFT_LENGTH['Honda HondaJet (twin-jet)'] = 12.99
AIRCRAFT_LENGTH['IAI Gulfstream G100 (twin-jet)'] = 16.94
AIRCRAFT_LENGTH['IAI Gulfstream G150 (twin-jet)'] = 16.94
AIRCRAFT_LENGTH['IAI Gulfstream G200 (twin-jet)'] = 18.97
AIRCRAFT_LENGTH['IAI Gulfstream G280 (twin-jet)'] = 20.3
AIRCRAFT_LENGTH['Learjet 31 (twin-jet)'] = 14.83
AIRCRAFT_LENGTH['Learjet 35 (twin-jet)'] = 14.83
<----SKIPPED LINES---->
Args:
filename: string of the filename to open, potentially also including the
full path.
log_exception: boolean indicating whether to log an exception if file not
found.
Returns:
Return text string of file contents.
"""
try:
with open(filename, 'r') as content_file:
file_contents = content_file.read()
except IOError:
if log_exception:
Log('Unable to read '+filename)
return ''
return file_contents
# because reading is ~25x more expensive than getmtime, we will only read &
# parse if the getmtime is more recent than last call for this file. So this
# dict stores a 2-tuple, the last time read & the resulting parsed return
# value
CACHED_FILES = {}
def ReadAndParseSettings(filename):
"""Reads filename and parses the resulting key-value pairs into a dict."""
global CACHED_FILES
(last_read_time, settings) = CACHED_FILES.get(filename, (0, {}))
if os.path.exists(filename):
last_modified = os.path.getmtime(filename)
if last_modified > last_read_time:
setting_str = ReadFile(filename)
settings = ParseSettings(setting_str)
CACHED_FILES[filename] = (last_modified, settings)
return settings
# File does not - or at least no longer - exists; so remove the cache
if filename in CACHED_FILES:
CACHED_FILES.pop(filename)
return {}
<----SKIPPED LINES---->
whether the current active json changed from the prior one.
Returns:
Boolean - True if different (and processing needed), False if identical
"""
if SIMULATION_COUNTER == 0:
return True
(this_json, unused_now) = DUMP_JSONS[SIMULATION_COUNTER]
(last_json, unused_now) = DUMP_JSONS[SIMULATION_COUNTER - 1]
return this_json != last_json
def CheckRebootNeeded(
startup_time, message_queue, json_desc_dict, configuration):
"""Reboot based on duration instance has been running.
Reboot needed in one of the following situations:
- All quiet: if running for over 24 hours and all is quiet (message queue
empty, no planes in radio, and backup not currently in process).
- Mostly quiet: if running for over 36 hours and message queue is empty and
it's 4a.
- Reboot requested via html form.
Also checks if reset requested via html form.
"""
reboot = False
global SHUTDOWN_SIGNAL
running_hours = (time.time() - startup_time) / SECONDS_IN_HOUR
restart_days = configuration.get('restart_days', 1)
min_hours = restart_days * HOURS_IN_DAY
if (
running_hours >= min_hours and
not message_queue and
not json_desc_dict.get('radio_range_flights') and
# script /home/pi/splitflap/backup.sh creates temp file in this
# directory; after it is copied to the NAS, it is deleted
not os.listdir('/media/backup')):
msg = ('All quiet reboot triggered based on %d days (%d hours); '
'actual runtime: %.2f hours' %
(restart_days, min_hours, running_hours))
SHUTDOWN_SIGNAL = msg
Log(msg)
reboot = True
# Wait another half day
restart_days += 0.5
min_hours = restart_days * HOURS_IN_DAY
if (
running_hours > min_hours and
not message_queue and
int(EpochDisplayTime(time.time(), '%-H')) >= 4):
msg = ('Early morning reboot triggered based on %.1f (%d hours); '
'actual runtime: %.2f hours' %
(restart_days, min_hours, running_hours))
SHUTDOWN_SIGNAL = msg
Log(msg)
reboot = True
if 'soft_reboot' in configuration:
msg = 'Soft reboot requested via web form'
SHUTDOWN_SIGNAL = msg
Log(msg)
reboot = True
RemoveSetting(configuration, 'soft_reboot')
if 'end_process' in configuration:
msg = 'Process end requested via web form'
SHUTDOWN_SIGNAL = msg
Log(msg)
RemoveSetting(configuration, 'end_process')
return reboot
<----SKIPPED LINES---->
# We repeat the loop every x seconds; this ensures that if the processing
# time is long, we don't wait another x seconds after processing completes
next_loop_time = time.time() + LOOP_DELAY_SECONDS
# These files are read only if the version on disk has been modified more
# recently than the last time it was read
last_dump_json_timestamp = 0
init_timing.append((time.time(), 7))
WaitUntilKillComplete(already_running_ids)
init_timing.append((time.time(), 8))
personal_message = None # Unknown what personal message is displayed
temp_last_logged = 0 # Keeps track of when temperature was last logged
LogTimes(init_timing)
reboot = False
iteration = 0 # counter that tracks how many times thru while loop
if initial_memory_dump:
DumpMemorySnapsnot(
configuration, iteration, startup_time, initial_frame_count)
Log('Finishing initialization of %d; starting radio polling loop' %
os.getpid())
while ((not SIMULATION or SIMULATION_COUNTER < len(DUMP_JSONS))
and not SHUTDOWN_SIGNAL):
last_heartbeat_time = Heartbeat(last_heartbeat_time)
new_configuration = ReadAndParseSettings(CONFIG_FILE)
UpdateRollingLogSize(new_configuration)
CheckForNewFilterCriteria(
configuration, new_configuration, message_queue, flights)
configuration = new_configuration
ResetLogs(configuration) # clear the logs if requested
UpdateRollingLogSize(configuration)
# if this is a SIMULATION, then process every diff dump. But if it
# isn't a simulation, then only read & do related processing for the
# next dump if the last-modified timestamp indicates the file has been
<----SKIPPED LINES---->
insight_messages = CreateFlightInsights(
flights,
configuration.get('insights'),
insight_message_distribution)
if configuration.get('next_flight', 'off') == 'on':
next_flight_text = FlightInsightNextFlight(flights, configuration)
if next_flight_text:
insight_messages.insert(0, next_flight_text)
insight_messages = [(FLAG_MSG_INSIGHT, m) for m in insight_messages]
for insight_message in insight_messages:
message_queue.insert(0, insight_message)
else: # flight didn't meet display criteria
flight['insight_types'] = []
PickleObjectToFile(
flight, PICKLE_FLIGHTS, True, timestamp=flight['now'])
else:
remote, servo = RefreshArduinos(
remote, servo,
to_remote_q, to_servo_q, to_main_q, shutdown,
flights, json_desc_dict, configuration, screen_history)
message_queue, next_message_time = ProcessArduinoCommmands(
to_main_q, flights, configuration, message_queue, next_message_time)
personal_message = PersonalMessage(
configuration, message_queue, personal_message)
# MEMORY MANAGEMENT
# now that we've saved the flight, we have no more need to keep the
# memory-hogging persistent_path key of that flight in live memory
if 'persistent_path' in flights[-1]:
del flights[-1]['persistent_path']
# it turns out we only need the last screen in the screen history, not
# the entire history, so we can purge all the rest from active memory
# to eliminate a slow-growing memory hog
screen_history = [screen_history[-1]]
# we also do not need more than MAX_INSIGHT_HORIZON_DAYS of history
# of the flights, so we can purge flights older than that as the flights
# list slowly grows over time. we can search the entire list every time
# but that's unnecessary; instead we can just pop off the 0-th element
# each time through the list if it's more than 1 + max days in the past.
# Why + 1? Because the histogram generation expects that many *full* days
# of history, so to make sure we don't have a partial day if we were to
# generate the monthly histograms mid-day, we will keep an extra day.
if time.time() - flights[0]['now'] > SECONDS_IN_DAY * (
MAX_INSIGHT_HORIZON_DAYS + 1):
flights.pop(0)
if SIMULATION:
if now:
simulated_hour = EpochDisplayTime(now, '%Y-%m-%d %H:00%z')
if simulated_hour != prev_simulated_hour:
print(simulated_hour)
prev_simulated_hour = simulated_hour
histogram = ReadAndParseSettings(HISTOGRAM_CONFIG_FILE)
RemoveFile(HISTOGRAM_CONFIG_FILE)
# We also need to make sure there are flights on which to generate a
# histogram! Why might there not be any flights? Primarily during a
# simulation, if there's a lingering histogram file at the time of
# history restart.
if histogram and not flights:
Log('Histogram requested (%s) but no flights in memory' % histogram)
if histogram and flights:
message_queue.extend(TriggerHistograms(flights, histogram))
if message_queue: # Any personal message displayed has been cleared
<----SKIPPED LINES---->
message_queue, next_message_time, configuration, screen_history)
reboot = CheckRebootNeeded(
startup_time, message_queue, json_desc_dict, configuration)
temp_last_logged = CheckTemperature(configuration, temp_last_logged)
if not SIMULATION:
time.sleep(max(0, next_loop_time - time.time()))
next_loop_time = time.time() + LOOP_DELAY_SECONDS
else:
SIMULATION_COUNTER += 1
if simulation_slowdown:
SimulationSlowdownNearFlight(flights, persistent_nearby_aircraft)
# now that we've completed the loop, lets potentially dump the
# memory snapshot
iteration += 1 # this completes the iteration-th time thru the loop
if initial_memory_dump:
DumpMemorySnapsnot(
configuration, iteration, startup_time, initial_frame_count)
if SIMULATION:
SimulationEnd(message_queue, flights, screen_history)
PerformGracefulShutdown(shutdown, reboot)
if __name__ == "__main__":
#interrupt, as in ctrl-c
signal.signal(signal.SIGINT, InterruptShutdownFromSignal)
#terminate, when another instance found or via kill
signal.signal(signal.SIGTERM, InterruptShutdownFromSignal)
if '-i' in sys.argv:
BootstrapInsightList()
else:
main_settings = ReadAndParseSettings(CONFIG_FILE)
if 'code_profiling_enabled' in main_settings:
import cProfile
cProfile.run(
<----SKIPPED LINES---->
|