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----> |