arduino-2020-06-04-0808.py
01234567890123456789012345678901234567890123456789012345678901234567890123456789









618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765











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




  # Ensures that the child can exit if the parent exits unexpectedly
  # docs.python.org/2/library/multiprocessing.html#multiprocessing.Queue.cancel_join_thread
  to_arduino_q.cancel_join_thread()
  to_parent_q.cancel_join_thread()

  # write_format: azimuth, altitude, R, G, & B intensity
  # read heartbeat: millis
  link = Serial(
      *SERVO_CONNECTION, read_timeout=7,
      error_pin=messageboard.GPIO_ERROR_ARDUINO_SERVO_CONNECTION, to_parent_q=to_parent_q,
      read_format='l', write_format='ffhhh', name='Servo')
  link.Open()

  last_flight = {}
  last_angles = (0, 0)
  flight, json_desc_dict, configuration, additional_attr = InitialMessageValues(
      to_arduino_q)
  next_read = 0
  next_write = 0
  now = GetNow(json_desc_dict, additional_attr)
  timing = []
  flight_present = False

  while not shutdown.value:
    timing.append((time.time(), 2))
    if not to_arduino_q.empty():
      flight, json_desc_dict, configuration, additional_attr = to_arduino_q.get(
          block=False)

      if 'test_servos' in configuration:
        messageboard.RemoveSetting(configuration, 'test_servos')
        link.Write((0, 0, *LASER_RGB_OFF))
        time.sleep(1)
        link.Write((90, 0, *LASER_RGB_OFF))
        time.sleep(1)
        link.Write((180, 0, *LASER_RGB_OFF))
        time.sleep(1)
        link.Write((270, 0, *LASER_RGB_OFF))

      timing.append((time.time(), 3))
      new_flight = DifferentFlights(flight, last_flight)
      timing.append((time.time(), 3.5))
      if new_flight:
        Log('Flight changed from %s to %s' % (
            messageboard.DisplayFlightNumber(last_flight),
            messageboard.DisplayFlightNumber(flight)
        ), ser=link)

        timing.append((time.time(), 4))
        # Turn off laser so that line isn't traced while it moves to new position
        link.Write((*last_angles, *LASER_RGB_OFF))

      last_flight = flight
      timing.append((time.time(), 5))

    if time.time() >= next_read:
      link.Read()  # simple ack message sent by servos
      next_read = time.time() + READ_DELAY_TIME
      timing.append((time.time(), 6))

    now = GetNow(json_desc_dict, additional_attr)
    timing.append((time.time(), 7))

    current_angles = AzimuthAltitude(flight, now)
    timing.append((time.time(), 8))
    if current_angles and time.time() > next_write:
      if current_angles[1] >= configuration['minimum_altitude_servo_tracking']:
        Log('Flight #: %s current_angles: %s' % (
            messageboard.DisplayFlightNumber(flight), str(current_angles)))
        messageboard.LogTimes(timing, threshold=0.2)
        flight_present = True
        laser_rgb = LaserRGBFlight(flight)
        timing = [(time.time(), 0)]
        link.Write((*current_angles, *laser_rgb))
        last_angles = current_angles
        timing.append((time.time(), 1.1))

      # flight no longer tracked; send one more command to turn off lasers
      elif flight_present:
        timing = [(time.time(), 1.2)]
        link.Write((*last_angles, *LASER_RGB_OFF))
        flight_present = False

      next_write = time.time() + WRITE_DELAY_TIME
    else:
      timing = timing = [(time.time(), 1.3)]

  link.Close(SHUTDOWN_TEXT)


LASER_RGB_OFF = (0, 0, 0)
def LaserRGBFlight(flight):
  """Based on flight attributes, set the laser."""
  if not flight:
    return LASER_RGB_OFF
  return 1, 0, 0


def DifferentFlights(f1, f2):
  """True if flights same except for persistent path; False if they differ.

  We cannot simply check if two flights are identical by checking equality of the dicts,
  because a few attributes are updated after the flight is first found:
  - the persistent_path is kept current
  - cached_* attributes may be updated
  - the insights are generated after flight first enqueued
  On the other hand, we cannot check if they are identical by looking just at the
  flight number, because flight numbers may be unknown. Thus, this checks all
  attributes except the persistent path.

  Returns:
    List of the different keys, excluding the persistent_path key.
  """
  if f1 is None and f2 is None:
    return []
  if f1 is None:
    return sorted(list(f2.keys()))
  if f2 is None:
    return sorted(list(f1.keys()))

  excluded_keys = ['persistent_path', 'insight_types']
  different_attributes = []
  for key in set(f1.keys()).union(set(f2.keys())):
    if key not in excluded_keys and not key.startswith(messageboard.CACHED_ELEMENT_PREFIX):
      if f1.get(key) != f2.get(key):
        different_attributes.append(key)

  return sorted(different_attributes)


def FloatToAlphanumericStr(x, decimals, total_length, sign=True):
  """Formats a float as a string without a decimal point.

  Since the decimal point is controlled independently on the alphanumeric display,
  numbers that include decimals must be sent without the decimal point.  This formats
  a float as %+5.2f, for example - but without the decimal.

  Args:
    x: Value to format.
    decimals: how many digits should follow the (absent) decimal point.
    total_length: desired total length of the resulting string-ified number (inclusive
      of the absent decimal point.
    sign: boolean indicating whether a sign should be included for positive numbers.

  Returns:
    String as specified - for instance, 0.4 might be formatted as ' +04'.
  """
  sign_str = ''




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





01234567890123456789012345678901234567890123456789012345678901234567890123456789









618619620621622623624625626627628629630631632633634635636637 638639640 641642643644645646647648649650651652653654 655 656657658659660661 662663664665 666667668669 670671 672673 674675676677 678679 680681 682683684 685686687688  689690691692693694695696697698699700701702             703704705706  707708709710711712   713714715716717718719720721722723724725726727728729730731732











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




  # Ensures that the child can exit if the parent exits unexpectedly
  # docs.python.org/2/library/multiprocessing.html#multiprocessing.Queue.cancel_join_thread
  to_arduino_q.cancel_join_thread()
  to_parent_q.cancel_join_thread()

  # write_format: azimuth, altitude, R, G, & B intensity
  # read heartbeat: millis
  link = Serial(
      *SERVO_CONNECTION, read_timeout=7,
      error_pin=messageboard.GPIO_ERROR_ARDUINO_SERVO_CONNECTION, to_parent_q=to_parent_q,
      read_format='l', write_format='ffhhh', name='Servo')
  link.Open()

  last_flight = {}
  last_angles = (0, 0)
  flight, json_desc_dict, configuration, additional_attr = InitialMessageValues(
      to_arduino_q)
  next_read = 0
  next_write = 0
  now = GetNow(json_desc_dict, additional_attr)

  flight_present = False

  while not shutdown.value:

    if not to_arduino_q.empty():
      flight, json_desc_dict, configuration, additional_attr = to_arduino_q.get(
          block=False)

      if 'test_servos' in configuration:
        messageboard.RemoveSetting(configuration, 'test_servos')
        link.Write((0, 0, *LASER_RGB_OFF))
        time.sleep(1)
        link.Write((90, 0, *LASER_RGB_OFF))
        time.sleep(1)
        link.Write((180, 0, *LASER_RGB_OFF))
        time.sleep(1)
        link.Write((270, 0, *LASER_RGB_OFF))


      new_flight = DifferentFlights(flight, last_flight)

      if new_flight:
        Log('Flight changed from %s to %s' % (
            messageboard.DisplayFlightNumber(last_flight),
            messageboard.DisplayFlightNumber(flight)
        ), ser=link)


        # Turn off laser so that line isn't traced while it moves to new position
        link.Write((*last_angles, *LASER_RGB_OFF))

      last_flight = flight


    if time.time() >= next_read:
      link.Read()  # simple ack message sent by servos
      next_read = time.time() + READ_DELAY_TIME


    now = GetNow(json_desc_dict, additional_attr)


    current_angles = AzimuthAltitude(flight, now)

    if current_angles and time.time() > next_write:
      if current_angles[1] >= configuration['minimum_altitude_servo_tracking']:
        Log('Flight #: %s current_angles: %s' % (
            messageboard.DisplayFlightNumber(flight), str(current_angles)))

        flight_present = True
        laser_rgb = LaserRGBFlight(flight)

        link.Write((*current_angles, *laser_rgb))
        last_angles = current_angles


      # flight no longer tracked; send one more command to turn off lasers
      elif flight_present:

        link.Write((*last_angles, *LASER_RGB_OFF))
        flight_present = False

      next_write = time.time() + WRITE_DELAY_TIME



  link.Close(SHUTDOWN_TEXT)


LASER_RGB_OFF = (0, 0, 0)
def LaserRGBFlight(flight):
  """Based on flight attributes, set the laser."""
  if not flight:
    return LASER_RGB_OFF
  return 1, 0, 0


def DifferentFlights(f1, f2):
  """True if both squawk and flight number different; false otherwise."""













  if f1 is None and f2 is None:
    return True
  if f1 is None or f2 is None:
    return True



  if (
      f1.get('flight_number') != f2.get('flight_number')
      and f1.get('squawk') != f2.get('squawk')):
    return True
  return False





def FloatToAlphanumericStr(x, decimals, total_length, sign=True):
  """Formats a float as a string without a decimal point.

  Since the decimal point is controlled independently on the alphanumeric display,
  numbers that include decimals must be sent without the decimal point.  This formats
  a float as %+5.2f, for example - but without the decimal.

  Args:
    x: Value to format.
    decimals: how many digits should follow the (absent) decimal point.
    total_length: desired total length of the resulting string-ified number (inclusive
      of the absent decimal point.
    sign: boolean indicating whether a sign should be included for positive numbers.

  Returns:
    String as specified - for instance, 0.4 might be formatted as ' +04'.
  """
  sign_str = ''




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