messageboard-2020-06-21-1105.py
01234567890123456789012345678901234567890123456789012345678901234567890123456789









109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149








50085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060  50615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086











                            <----SKIPPED LINES---->




# data or code logic to check into. It is only cleared out manually.
LOGFILE = 'log.txt'
# Identical to the LOGFILE, except it includes just the most recent n lines.
# Newest lines are at the end.
ROLLING_LOGFILE = 'secure/rolling_log.txt' #file for error messages

# default number of lines which may be overridden by settings file
ROLLING_LOG_SIZE = 1000

# 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_RELATIVE_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'
HISTOGRAM_IMAGE_HTML = 'histograms.html'

# 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




                            <----SKIPPED LINES---->





  Returns:
    List of histogram messages, if text-based histograms are selected; empty
    list otherwise.
  """
  histogram_messages = []

  if histogram_settings['type'] in ('messageboard', 'both'):
    histogram_messages = MessageboardHistograms(
        flights,
        histogram_settings['histogram'],
        histogram_settings['histogram_history'],
        histogram_settings['histogram_max_screens'],
        histogram_settings.get('histogram_data_summary', False),
        heartbeat=heartbeat)
  if histogram_settings['type'] in ('images', 'both'):

    # Since Google Chrome seems to ignore all instructions to not cache, we need
    # to make sure we do not reuse file names - hence the epoch_string - and
    # then we need to
    # 1) update the histograms.html file with the correct file links, and
    # 2) delete the images that are now obsolete.
    epoch_string = '%d_' % round(time.time())

    generated_histograms = ImageHistograms(
        flights,
        histogram_settings['histogram'],
        histogram_settings['histogram_history'],
        filename_prefix=HISTOGRAM_IMAGE_PREFIX + epoch_string,
        heartbeat=heartbeat)
    html_lines = ReadFile(HISTOGRAM_IMAGE_HTML).split('\n')
    replaced_images = []
    for identifier, new_filename in generated_histograms:
      # for each histogram, find the html_line with the matching id
      # Example line:
      #   <img id="destination" src="images/histogram_destination.png"><p>
      identifier = '"%s"' % identifier
      n, line = None, None  # addresses pylint complaint
      found = False
      for n, line in enumerate(html_lines):
        if identifier in line:
          found = True
          break
        found = False
      if found:
        start_char = line.find(WEBSERVER_IMAGE_RELATIVE_FOLDER)
        end_character = (
            line.find(HISTOGRAM_IMAGE_SUFFIX, start_char) +
            len(HISTOGRAM_IMAGE_SUFFIX))
        old_filename = line[start_char:end_character]
        line = line.replace(old_filename, new_filename)
        html_lines[n] = line
        replaced_images.append(old_filename)


    new_html = '\n'.join(html_lines)
    WriteFile(HISTOGRAM_IMAGE_HTML, new_html)

    # Remove those obsoleted files
    for f in replaced_images:
      RemoveFile(WEBSERVER_PATH + f)

  return histogram_messages


def SaveFlightsByAltitudeDistanceCSV(
    flights,
    max_days=0,
    filename='flights_by_alt_dist.csv',
    precision=100):
  """Generates CSV of hour of day, altitude, and distance.

  Generates a csv with 26 columns:
  - col#1: altitude (in feet)
  - col#2: distance (in feet)
  - cols#3-26: hour of the day

  The first row is a header row; subsequent rows list the number of flights
  that have occurred in the last max_days with an altitude and min distance
  less than that identified in the first two columns. Each row increments
  elevation or altitude by precision feet, up to the max determined by the max




                            <----SKIPPED LINES---->





01234567890123456789012345678901234567890123456789012345678901234567890123456789









109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149








500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064    50655066506750685069507050715072507350745075507650775078507950805081508250835084











                            <----SKIPPED LINES---->




# data or code logic to check into. It is only cleared out manually.
LOGFILE = 'log.txt'
# Identical to the LOGFILE, except it includes just the most recent n lines.
# Newest lines are at the end.
ROLLING_LOGFILE = 'secure/rolling_log.txt' #file for error messages

# default number of lines which may be overridden by settings file
ROLLING_LOG_SIZE = 1000

# 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_RELATIVE_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'
HISTOGRAM_IMAGE_HTML = 'histograms.php'

# 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




                            <----SKIPPED LINES---->





  Returns:
    List of histogram messages, if text-based histograms are selected; empty
    list otherwise.
  """
  histogram_messages = []

  if histogram_settings['type'] in ('messageboard', 'both'):
    histogram_messages = MessageboardHistograms(
        flights,
        histogram_settings['histogram'],
        histogram_settings['histogram_history'],
        histogram_settings['histogram_max_screens'],
        histogram_settings.get('histogram_data_summary', False),
        heartbeat=heartbeat)
  if histogram_settings['type'] in ('images', 'both'):

    # Since Google Chrome seems to ignore all instructions to not cache, we need
    # to make sure we do not reuse file names - hence the epoch_string - and
    # then we need to
    # 1) update the histograms.php file with the correct file links, and
    # 2) delete the images that are now obsolete.
    epoch_string = EpochDisplayTime(time.time(), '%Y%m%d_%H%M%S_')

    ImageHistograms(
        flights,
        histogram_settings['histogram'],
        histogram_settings['histogram_history'],
        filename_prefix=HISTOGRAM_IMAGE_PREFIX + epoch_string,
        heartbeat=heartbeat)
    histogram_id_sequence = [
        'origin', 'destination',
        'day_of_month', 'day_of_week', 'hour',
        'bearing', 'distance', 'speed', 'vert_rate', 'altitude',
        'airline', 'aircraft', 'aircraft_length']
    path = WEBSERVER_PATH + WEBSERVER_IMAGE_RELATIVE_FOLDER
    files = os.listdir(path)
    lines = [
        '<head>',
        '<title>Flight Tracker: Histograms</title>',
        '</head>',
        '<body>',
        '<?php include "nav.html" ?>',
        '<div class="resp-iframe">'
    ]
    for histogram_id in histogram_id_sequence:
      matching_files = sorted([f for f in files if histogram_id in f])
      # save the most recent; delete the others
      lines.append('<img id="%s" src="images/%s"><p>' % (
          histogram_id, matching_files[-1]))
      for f in matching_files[:-1]:
        RemoveFile(
            os.path.join(WEBSERVER_PATH, WEBSERVER_IMAGE_RELATIVE_FOLDER, f))

    lines.extend(['</div>', '</body>'])
    html = '\n'.join(lines)
    WriteFile(HISTOGRAM_IMAGE_HTML, html)





  return histogram_messages


def SaveFlightsByAltitudeDistanceCSV(
    flights,
    max_days=0,
    filename='flights_by_alt_dist.csv',
    precision=100):
  """Generates CSV of hour of day, altitude, and distance.

  Generates a csv with 26 columns:
  - col#1: altitude (in feet)
  - col#2: distance (in feet)
  - cols#3-26: hour of the day

  The first row is a header row; subsequent rows list the number of flights
  that have occurred in the last max_days with an altitude and min distance
  less than that identified in the first two columns. Each row increments
  elevation or altitude by precision feet, up to the max determined by the max




                            <----SKIPPED LINES---->