01234567890123456789012345678901234567890123456789012345678901234567890123456789
110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 574557465747574857495750575157525753575457555756575757585759576057615762576357645765 57665767576857695770577157725773577457755776577757785779578057815782578357845785 58255826582758285829583058315832583358345835583658375838583958405841584258435844 58455846584758485849585058515852585358545855585658575858585958605861586258635864 |
<----SKIPPED LINES---->
ROLLING_LOG_SIZE = 1000 # default number of lines which may be overridden by settings file
# Users can trigger .png histograms analogous to the text ones from the web interface;
# this is the folder (within WEBSERVER_PATH) where those files are placed
WEBSERVER_IMAGE_FOLDER = 'images/'
# Multiple histograms can be generated, i.e. for airline, aircraft, day of week, etc.
# The output files are named by the prefix & suffix, i.e.: prefix + type + . + suffix,
# as in histogram_aircraft.png. These names match up to the names expected by the html
# page that displays the images. Also, note that the suffix is interpreted by matplotlib
# to identify the image format to create.
HISTOGRAM_IMAGE_PREFIX = 'histogram_'
HISTOGRAM_IMAGE_SUFFIX = 'png'
# For those of the approximately ten different types of histograms _not_ generated,
# an empty image is copied into the location expected by the webpage instead; this is
# the location of that "empty" image file.
HISTOGRAM_EMPTY_IMAGE_FILE = 'empty.png'
# This file indicates a pending request for histograms - either png, text-based, or
# both; once it is processed, this file is deleted. The contents are concatenated key-value
# pairs, histogram=all;histogram_history=24h; etc.
HISTOGRAM_CONFIG_FILE = 'histogram.txt'
HISTOGRAM_BOOLEANS = ('histogram_data_summary')
# This contains concatenated key-value configuration attributes in a similar format
# to the HISTOGRAM_CONFIG_FILE that are exposed to the user via the web interface or,
# for a subset of them, through the Arduino interface. They are polled at every iteration
# so that the most current value is always leveraged by the running software.
CONFIG_FILE = 'settings.txt'
CONFIG_BOOLEANS = ('setting_screen_enabled', 'next_flight', 'reset_logs', 'log_jsons')
# A few key settings for the messageboard are its sensitivity to displaying flights -
# though it logs all flights within range, it may not be desirable to display all
# flights to the user. Two key parameters are the maximum altitude, and the furthest
# away we anticipate the flight being at its closest point to HOME. As those two
# parameters are manipulated in the settings, a histogram is displayed with one or
# potentially two series, showing the present and potentially prior-set distribution
# of flights, by hour throughout the day, over the last seven days, normalized to
# flights per day. This allows those parameters to be fine-tuned in a useful way.
# This file is the location, on the webserver, of that image, which needs to be in
# alignment with the html page that displays it.
HOURLY_IMAGE_FILE = 'hours.png'
# This is all messages that have been sent to the board since the last time the
# file was manually cleared. Newest messages are at the bottom. It is visible at the
# webserver.
ALL_MESSAGE_FILE = 'all_messages.txt' #enumeration of all messages sent to board
# This shows the most recent n messages sent to the board. Newest messages are at the
# top for easier viewing of "what did I miss".
ROLLING_MESSAGE_FILE = 'rolling_messages.txt'
<----SKIPPED LINES---->
# This flag slows down simulation time around a flight, great for debugging the arduinos
simulation_slowdown = bool('-f' in sys.argv)
# Redirect any errors to a log file instead of the screen, and add a datestamp
if not SIMULATION:
sys.stderr = open(STDERR_FILE, 'a')
Log('', STDERR_FILE)
init_timing.append((time.time(), 1))
Log('Starting up process %d' % os.getpid())
already_running_ids = FindRunningParents()
if already_running_ids:
for pid in already_running_ids:
Log('Sending termination signal to %d' % pid)
os.kill(pid, signal.SIGTERM)
init_timing.append((time.time(), 2))
SetPinMode()
configuration = ReadAndParseSettings(CONFIG_FILE)
UpdateRollingLogSize(configuration)
startup_time = time.time()
json_desc_dict = {}
init_timing.append((time.time(), 3))
flights = UnpickleObjectFromFile(PICKLE_FLIGHTS, True, max_days=MAX_INSIGHT_HORIZON_DAYS)
# Clear the loaded flight of any cached data, identified by keys with a specific
# suffix, since code fixes may change the values for some of those cached elements
for flight in flights:
for key in list(flight.keys()):
if key.endswith(CACHED_ELEMENT_PREFIX):
flight.pop(key)
init_timing.append((time.time(), 4))
# If we're displaying just a single insight message, we want it to be something
# unique, to the extent possible; this dict holds a count of the diff types of messages
# displayed so far
insight_message_distribution = {}
# bootstrap the flight insights distribution from a list of insights on each
# flight (i.e.: flight['insight_types'] for a given flight might look like
<----SKIPPED LINES---->
# than the last time it was read
last_dump_json_timestamp = 0
init_timing.append((time.time(), 6))
WaitUntilKillComplete(already_running_ids)
init_timing.append((time.time(), 7))
LogTimes(init_timing)
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
# 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 updated since it was last read.
tmp_timestamp = 0
if not SIMULATION:
dump_json_exists = os.path.exists(DUMP_JSON_FILE)
if dump_json_exists:
tmp_timestamp = os.path.getmtime(DUMP_JSON_FILE)
if (SIMULATION and DumpJsonChanges()) or (
not SIMULATION and dump_json_exists and tmp_timestamp > last_dump_json_timestamp):
last_dump_json_timestamp = tmp_timestamp
(persistent_nearby_aircraft,
flight, now,
json_desc_dict,
persistent_path) = ScanForNewFlights(
persistent_nearby_aircraft,
persistent_path,
<----SKIPPED LINES---->
|
01234567890123456789012345678901234567890123456789012345678901234567890123456789
110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786 58265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866 |
<----SKIPPED LINES---->
ROLLING_LOG_SIZE = 1000 # default number of lines which may be overridden by settings file
# Users can trigger .png histograms analogous to the text ones from the web interface;
# this is the folder (within WEBSERVER_PATH) where those files are placed
WEBSERVER_IMAGE_FOLDER = 'images/'
# Multiple histograms can be generated, i.e. for airline, aircraft, day of week, etc.
# The output files are named by the prefix & suffix, i.e.: prefix + type + . + suffix,
# as in histogram_aircraft.png. These names match up to the names expected by the html
# page that displays the images. Also, note that the suffix is interpreted by matplotlib
# to identify the image format to create.
HISTOGRAM_IMAGE_PREFIX = 'histogram_'
HISTOGRAM_IMAGE_SUFFIX = 'png'
# For those of the approximately ten different types of histograms _not_ generated,
# an empty image is copied into the location expected by the webpage instead; this is
# the location of that "empty" image file.
HISTOGRAM_EMPTY_IMAGE_FILE = 'empty.png'
# This file indicates a pending request for histograms - either png, text-based, or
# both; once it is processed, this file is deleted. The contents are concatenated key-value
# pairs, histogram=all;histogram_history=24h; etc.
HISTOGRAM_CONFIG_FILE = 'secure/histogram.txt'
HISTOGRAM_BOOLEANS = ('histogram_data_summary')
# This contains concatenated key-value configuration attributes in a similar format
# to the HISTOGRAM_CONFIG_FILE that are exposed to the user via the web interface or,
# for a subset of them, through the Arduino interface. They are polled at every iteration
# so that the most current value is always leveraged by the running software.
CONFIG_FILE = 'secure/settings.txt'
CONFIG_BOOLEANS = ('setting_screen_enabled', 'next_flight', 'reset_logs', 'log_jsons')
# A few key settings for the messageboard are its sensitivity to displaying flights -
# though it logs all flights within range, it may not be desirable to display all
# flights to the user. Two key parameters are the maximum altitude, and the furthest
# away we anticipate the flight being at its closest point to HOME. As those two
# parameters are manipulated in the settings, a histogram is displayed with one or
# potentially two series, showing the present and potentially prior-set distribution
# of flights, by hour throughout the day, over the last seven days, normalized to
# flights per day. This allows those parameters to be fine-tuned in a useful way.
# This file is the location, on the webserver, of that image, which needs to be in
# alignment with the html page that displays it.
HOURLY_IMAGE_FILE = 'hours.png'
# This is all messages that have been sent to the board since the last time the
# file was manually cleared. Newest messages are at the bottom. It is visible at the
# webserver.
ALL_MESSAGE_FILE = 'all_messages.txt' #enumeration of all messages sent to board
# This shows the most recent n messages sent to the board. Newest messages are at the
# top for easier viewing of "what did I miss".
ROLLING_MESSAGE_FILE = 'rolling_messages.txt'
<----SKIPPED LINES---->
# This flag slows down simulation time around a flight, great for debugging the arduinos
simulation_slowdown = bool('-f' in sys.argv)
# Redirect any errors to a log file instead of the screen, and add a datestamp
if not SIMULATION:
sys.stderr = open(STDERR_FILE, 'a')
Log('', STDERR_FILE)
init_timing.append((time.time(), 1))
Log('Starting up process %d' % os.getpid())
already_running_ids = FindRunningParents()
if already_running_ids:
for pid in already_running_ids:
Log('Sending termination signal to %d' % pid)
os.kill(pid, signal.SIGTERM)
init_timing.append((time.time(), 2))
SetPinMode()
configuration = ReadAndParseSettings(CONFIG_FILE)
Log('Read CONFIG_FILE at %s: %s' % (CONFIG_FILE, str(configuration)))
startup_time = time.time()
json_desc_dict = {}
init_timing.append((time.time(), 3))
flights = UnpickleObjectFromFile(PICKLE_FLIGHTS, True, max_days=MAX_INSIGHT_HORIZON_DAYS)
# Clear the loaded flight of any cached data, identified by keys with a specific
# suffix, since code fixes may change the values for some of those cached elements
for flight in flights:
for key in list(flight.keys()):
if key.endswith(CACHED_ELEMENT_PREFIX):
flight.pop(key)
init_timing.append((time.time(), 4))
# If we're displaying just a single insight message, we want it to be something
# unique, to the extent possible; this dict holds a count of the diff types of messages
# displayed so far
insight_message_distribution = {}
# bootstrap the flight insights distribution from a list of insights on each
# flight (i.e.: flight['insight_types'] for a given flight might look like
<----SKIPPED LINES---->
# than the last time it was read
last_dump_json_timestamp = 0
init_timing.append((time.time(), 6))
WaitUntilKillComplete(already_running_ids)
init_timing.append((time.time(), 7))
LogTimes(init_timing)
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 updated since it was last read.
tmp_timestamp = 0
if not SIMULATION:
dump_json_exists = os.path.exists(DUMP_JSON_FILE)
if dump_json_exists:
tmp_timestamp = os.path.getmtime(DUMP_JSON_FILE)
if (SIMULATION and DumpJsonChanges()) or (
not SIMULATION and dump_json_exists and tmp_timestamp > last_dump_json_timestamp):
last_dump_json_timestamp = tmp_timestamp
(persistent_nearby_aircraft,
flight, now,
json_desc_dict,
persistent_path) = ScanForNewFlights(
persistent_nearby_aircraft,
persistent_path,
<----SKIPPED LINES---->
|