messageboard-2022-11-01-0940.py
01234567890123456789012345678901234567890123456789012345678901234567890123456789









639063916392639363946395639663976398639964006401640264036404640564066407640864096410 64116412641364146415641664176418641964206421642264236424642564266427642864296430








64326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523








73337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373











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




    message_array = message_array[:expected_characters]

  message_2d_array = []
  for line_num in range(SPLITFLAP_LINE_COUNT):
    message_2d_array.append(message_array[
        line_num * SPLITFLAP_CHARS_PER_LINE :
        (line_num + 1)*SPLITFLAP_CHARS_PER_LINE])

  return message_2d_array


def PublishMessageWeb(
    s,
    subscription_id=SUBSCRIPTION_ID,
    key=KEY,
    secret=SECRET,
    timeout=5):
  """Publishes a text string to a Vestaboard.

  The message is pushed to the vestaboard splitflap display by way of its
  web services; see https://docs.vestaboard.com/introduction for more details.


  TODO: rewrite to use the easier-to-follow requests library, more in line
  with PublishMessageLocal.

  Args:
    s: String to publish.
    subscription_id: string subscription id from Vestaboard.
    key: string key from Vestaboard.
    secret: string secret from Vestaboard.
    timeout: Max duration in seconds that we should wait to establish a
      connection.

  Returns:
    Text string indicating how the message was displayed (web or local
    api), and / or any error messages encountered.
  """
  error_code = False
  curl = pycurl.Curl()

  # See https://stackoverflow.com/questions/31826814/




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




  # Set URL value
  curl.setopt(
      pycurl.URL,
      'https://platform.vestaboard.com/subscriptions/%s/message'
      % subscription_id)
  curl.setopt(pycurl.HTTPHEADER, [
      'X-Vestaboard-Api-Key:%s' % key, 'X-Vestaboard-Api-Secret:%s' % secret])
  curl.setopt(pycurl.TIMEOUT_MS, timeout*1000)
  curl.setopt(pycurl.POST, 1)

  curl.setopt(pycurl.WRITEFUNCTION, lambda x: None) # to keep stdout clean

  # preparing body the way pycurl.READDATA wants it
  body_as_dict = {'characters': StringToCharArray(s)}
  body_as_json_string = json.dumps(body_as_dict) # dict to json
  body_as_file_object = io.StringIO(body_as_json_string)

  # prepare and send. See also: pycurl.READFUNCTION to pass function instead
  curl.setopt(pycurl.READDATA, body_as_file_object)
  curl.setopt(pycurl.POSTFIELDSIZE, len(body_as_json_string))
  failure_message = ''
  try:
    curl.perform()
    status = 'Web service published'
  except pycurl.error as e:
    timing_message = CurlTimingDetailsToString(curl)
    failure_message = (
        'curl.perform() failed with message %s; timing details: %s' %
        (e, timing_message))
    # Using the remote webservice failed, but maybe the local API will
    # be more successful?  If this succeeds, then we should not indicate
    # a failure on the status light / dashboard, but we should still log
    # the remote failure
    Log(failure_message)
    error_code = PublishMessageLocal(s, timeout=timeout, update_dashboard=False)
    if not error_code:
      status = (
          'Local service published because web service failed with %s'
          % failure_message)
    else:
      status = (
          'Local service failed with %s after web service failed with %s' %
          (error_code, failure_message))
  else:
    # you may want to check HTTP response code, e.g.
    timing_message = CurlTimingDetailsToString(curl)
    status_code = curl.getinfo(pycurl.RESPONSE_CODE)
    if status_code != 200:
      failure_message = (
          'Server returned HTTP status code %d for message %s; '
          'timing details: %s' % (status_code, s, timing_message))
      Log(failure_message)
      error_code = PublishMessageLocal(
          s, timeout=timeout, update_dashboard=False)
      if not error_code:
        status = (
            'Local service published because web service failed with %s'
            % failure_message)
      else:
        status = (
            'Local service failed with %s after web service failed with %s' %
            (error_code, failure_message))

  # We've logged the error code from the external web service, but the
  # Vestaboard local API was able to recover from the error, so we need not
  # log the failure message / error code in the dashboard.
  if not error_code:
    failure_message = ''

  curl.close()
  UpdateStatusLight(
      GPIO_ERROR_VESTABOARD_CONNECTION, error_code, failure_message)

  return status


def PublishMessageLocal(
    s,
    local_key=LOCAL_KEY,
    local_address=LOCAL_VESTABOARD_ADDRESS,
    timeout=5,
    update_dashboard=True):
  """Publishes a text string to a Vestaboard via local API.

  The message is pushed to the vestaboard splitflap display by way of its
  local API; see https://docs.vestaboard.com/local for more details.

  Args:
    s: String to publish.
    local_key: string key from Vestaboard for local API access.
    local_address: the address and port to the local Vestaboard service.
    timeout: Max duration in seconds that we should wait to establish a




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





      if new_flight_flag:
        time_new_flight_found = time.time()

        # Since we no longer need the memory-hogging prior persistent_path
        # stored on the flights, we can remove it
        if flights and 'persistent_path' in flights[-1]:
          del flights[-1]['persistent_path']

        flights.append(flight)
        remote, servo = RefreshArduinos(
            remote, servo,
            to_remote_q, to_servo_q, to_main_q, shutdown,
            flights, json_desc_dict, configuration, screen_history)

        flight_meets_display_criteria, reason_flight_fails_criteria = (
            FlightMeetsDisplayCriteria(flight, configuration, log=True))

        # Initialize variables for saving in case details not populated by
        # later code prior to saving in pickle
        flight_aware_error_message = ''
        time_flight_message_inserted = 0
        time_insight_message_inserted = 0

        if flight_meets_display_criteria:
          personal_message = None  # Any personal message displayed now cleared
          flight_message = (
              FLAG_MSG_FLIGHT, CreateMessageAboutFlight(flight), flight)

          # display the next message about this flight now!
          next_message_time = time.time()
          message_queue.insert(0, flight_message)
          time_flight_message_inserted = time.time()
          # and delete any queued insight messages about other flights that have
          # not yet displayed, since a newer flight has taken precedence
          message_queue = DeleteMessageTypes(message_queue, (FLAG_MSG_INSIGHT,))

          # Though we also manage the message queue outside this conditional
          # as well, because it can take a half second to generate the flight
          # insights, this allows this message to start displaying on the
          # board immediately, so it's up there when it's most relevant




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





01234567890123456789012345678901234567890123456789012345678901234567890123456789









639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431








64336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524








73347335733673377338733973407341734273437344734573467347734873497350735173527353 73547355735673577358735973607361736273637364736573667367736873697370737173727373











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




    message_array = message_array[:expected_characters]

  message_2d_array = []
  for line_num in range(SPLITFLAP_LINE_COUNT):
    message_2d_array.append(message_array[
        line_num * SPLITFLAP_CHARS_PER_LINE :
        (line_num + 1)*SPLITFLAP_CHARS_PER_LINE])

  return message_2d_array


def PublishMessageWeb(
    s,
    subscription_id=SUBSCRIPTION_ID,
    key=KEY,
    secret=SECRET,
    timeout=5):
  """Publishes a text string to a Vestaboard.

  The message is pushed to the vestaboard splitflap display by way of its
  web services; see https://docs.vestaboard.com/introduction for more details;
  if the web service fails, it then reattempts to publish using the local api.

  TODO: rewrite to use the easier-to-follow requests library, more in line
  with PublishMessageLocal.

  Args:
    s: String to publish.
    subscription_id: string subscription id from Vestaboard.
    key: string key from Vestaboard.
    secret: string secret from Vestaboard.
    timeout: Max duration in seconds that we should wait to establish a
      connection.

  Returns:
    Text string indicating how the message was displayed (web or local
    api), and / or any error messages encountered.
  """
  error_code = False
  curl = pycurl.Curl()

  # See https://stackoverflow.com/questions/31826814/




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




  # Set URL value
  curl.setopt(
      pycurl.URL,
      'https://platform.vestaboard.com/subscriptions/%s/message'
      % subscription_id)
  curl.setopt(pycurl.HTTPHEADER, [
      'X-Vestaboard-Api-Key:%s' % key, 'X-Vestaboard-Api-Secret:%s' % secret])
  curl.setopt(pycurl.TIMEOUT_MS, timeout*1000)
  curl.setopt(pycurl.POST, 1)

  curl.setopt(pycurl.WRITEFUNCTION, lambda x: None) # to keep stdout clean

  # preparing body the way pycurl.READDATA wants it
  body_as_dict = {'characters': StringToCharArray(s)}
  body_as_json_string = json.dumps(body_as_dict) # dict to json
  body_as_file_object = io.StringIO(body_as_json_string)

  # prepare and send. See also: pycurl.READFUNCTION to pass function instead
  curl.setopt(pycurl.READDATA, body_as_file_object)
  curl.setopt(pycurl.POSTFIELDSIZE, len(body_as_json_string))
  web_failure_message = ''
  try:
    curl.perform()
    status = 'Web service published'
  except pycurl.error as e:
    timing_message = CurlTimingDetailsToString(curl)
    web_failure_message = (
        'curl.perform() failed with message %s; timing details: %s' %
        (e, timing_message))
    # Using the remote webservice failed, but maybe the local API will
    # be more successful?  If this succeeds, then we should not indicate
    # a failure on the status light / dashboard, but we should still log
    # the remote failure
    Log(web_failure_message)
    error_code = PublishMessageLocal(s, timeout=timeout, update_dashboard=False)
    if not error_code:
      status = (
          'Local service published (1) because web service failed with %s'
          % web_failure_message)
    else:
      status = (
          'Local service failed (2) with %s after web service failed with %s' %
          (error_code, web_failure_message))
  else:
    # you may want to check HTTP response code, e.g.
    timing_message = CurlTimingDetailsToString(curl)
    status_code = curl.getinfo(pycurl.RESPONSE_CODE)
    if status_code != 200:
      web_failure_message = (
          'Server returned HTTP status code %d for message %s; '
          'timing details: %s' % (status_code, s, timing_message))
      Log(web_failure_message)
      error_code = PublishMessageLocal(
          s, timeout=timeout, update_dashboard=False)
      if not error_code:
        status = (
            'Local service published (3) because web service failed with %s'
            % web_failure_message)
      else:
        status = (
            'Local service failed (4) with %s after web service failed with %s'
            % (error_code, web_failure_message))

  # We've logged the error code from the external web service, but the
  # Vestaboard local API was able to recover from the error, so we need not
  # log the failure message / error code in the dashboard.
  if not error_code:
    web_failure_message = ''

  curl.close()
  UpdateStatusLight(
      GPIO_ERROR_VESTABOARD_CONNECTION, error_code, web_failure_message)

  return status


def PublishMessageLocal(
    s,
    local_key=LOCAL_KEY,
    local_address=LOCAL_VESTABOARD_ADDRESS,
    timeout=5,
    update_dashboard=True):
  """Publishes a text string to a Vestaboard via local API.

  The message is pushed to the vestaboard splitflap display by way of its
  local API; see https://docs.vestaboard.com/local for more details.

  Args:
    s: String to publish.
    local_key: string key from Vestaboard for local API access.
    local_address: the address and port to the local Vestaboard service.
    timeout: Max duration in seconds that we should wait to establish a




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





      if new_flight_flag:
        time_new_flight_found = time.time()

        # Since we no longer need the memory-hogging prior persistent_path
        # stored on the flights, we can remove it
        if flights and 'persistent_path' in flights[-1]:
          del flights[-1]['persistent_path']

        flights.append(flight)
        remote, servo = RefreshArduinos(
            remote, servo,
            to_remote_q, to_servo_q, to_main_q, shutdown,
            flights, json_desc_dict, configuration, screen_history)

        flight_meets_display_criteria, reason_flight_fails_criteria = (
            FlightMeetsDisplayCriteria(flight, configuration, log=True))

        # Initialize variables for saving in case details not populated by
        # later code prior to saving in pickle

        time_flight_message_inserted = 0
        time_insight_message_inserted = 0

        if flight_meets_display_criteria:
          personal_message = None  # Any personal message displayed now cleared
          flight_message = (
              FLAG_MSG_FLIGHT, CreateMessageAboutFlight(flight), flight)

          # display the next message about this flight now!
          next_message_time = time.time()
          message_queue.insert(0, flight_message)
          time_flight_message_inserted = time.time()
          # and delete any queued insight messages about other flights that have
          # not yet displayed, since a newer flight has taken precedence
          message_queue = DeleteMessageTypes(message_queue, (FLAG_MSG_INSIGHT,))

          # Though we also manage the message queue outside this conditional
          # as well, because it can take a half second to generate the flight
          # insights, this allows this message to start displaying on the
          # board immediately, so it's up there when it's most relevant




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