arduino-2020-05-30-1312.py
01234567890123456789012345678901234567890123456789012345678901234567890123456789









3334353637383940414243444546474849505152 53 545556575859606162636465666768697071727374








267268269270271272273274275276277278279280281282283284285286 287288289290291292293294295296297298299  300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 331332333334335336337338339340341342343344345346347348349350351352353








661662663664665666667668669670671672673674675676677678679680681682   683684685686687688689690691692693694695696697698699700701702








1215121612171218121912201221122212231224122512261227122812291230123112321233123412351236   



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





if RASPBERRY_PI:
  ARDUINO_LOG = MESSAGEBOARD_PATH + ARDUINO_LOG
  SERIALS_LOG = MESSAGEBOARD_PATH + SERIALS_LOG
  SERVO_SIMULATED_OUT = MESSAGEBOARD_PATH + SERVO_SIMULATED_OUT
  SERVO_SIMULATED_IN = MESSAGEBOARD_PATH + SERVO_SIMULATED_IN
  REMOTE_SIMULATED_OUT = MESSAGEBOARD_PATH + REMOTE_SIMULATED_OUT
  REMOTE_SIMULATED_IN = MESSAGEBOARD_PATH + REMOTE_SIMULATED_IN

  ARDUINO_ROLLING_LOG = WEBSERVER_PATH + ARDUINO_ROLLING_LOG

CONNECTION_FLAG_BLUETOOTH = 1
CONNECTION_FLAG_USB = 2
CONNECTION_FLAG_SIMULATED = 3
RASPBERRY_PI = psutil.sys.platform.title() == 'Linux'

SN_SERVO = '5583834303435111C1A0'
SERVO_CONNECTION = (CONNECTION_FLAG_BLUETOOTH, (2, '98:D3:11:FC:42:16', 1))

SN_REMOTE = '75835343130351802272'

REMOTE_CONNECTION = (CONNECTION_FLAG_BLUETOOTH, (1, '98:D3:91:FD:B1:8F', 1))  # directly connected to Serial2

REMOTE_CONNECTION = (CONNECTION_FLAG_BLUETOOTH, (1, '98:D3:91:FD:B3:C9', 1))  # connected thru MOSFET to Serial1

MIN_ALTITUDE = 5  # below this elevation degrees, turn off the tracking

if SIMULATE_ARDUINO:
  SERVO_CONNECTION = (CONNECTION_FLAG_SIMULATED, (SERVO_SIMULATED_IN, SERVO_SIMULATED_OUT))
  REMOTE_CONNECTION = (
      CONNECTION_FLAG_SIMULATED, (REMOTE_SIMULATED_IN, REMOTE_SIMULATED_OUT))

KEY_NOT_PRESENT_STRING = 'N/A'

DISP_LAST_FLIGHT_NUMB_ORIG_DEST = 0
DISP_LAST_FLIGHT_AZIMUTH_ELEVATION = 1
DISP_FLIGHT_COUNT_LAST_SEEN = 2
DISP_RADIO_RANGE = 3
DISPLAY_MODE_NAMES = [
    'LAST_FLIGHT_NUMB_ORIG_DEST', 'LAST_FLIGHT_AZIMUTH_ELEVATION',
    'FLIGHT_COUNT_LAST_SEEN', 'RADIO_RANGE']

WRITE_DELAY_TIME = 0.2  # write to arduino every n seconds
READ_DELAY_TIME = 0.1  # read from arduino every n seconds




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





    Args:
      format_string: String of the form expected by struct.pack

    Returns:
      Tuple of values matching that as identified in format_string.
    """
    if self.connection_type == CONNECTION_FLAG_SIMULATED:
      if (
          self.__simulated_reads__ and
          time.time() - self.start_time > self.__simulated_reads__[0][0]):  # time for next
        next_line = self.__simulated_reads__.pop(0)
        return next_line[1]
      return ()

    if not format_string:
      format_string = self.read_format
    try:
      data = Read(self.link, format_string)
    except OSError as e:

      if self.error_pin:
        self.to_parent_q.put(('pin', (self.error_pin, True)))
      self.Reopen(log_message='Failed to read: %s' % e)
      return self.Read(format_string=format_string)
    self.last_read = time.time()
    if data:
      self.last_receipt = time.time()
      if LOG_SERIALS:
        ts = time.time() - self.start_time
        str_data = str(['%7.2f' % d if isinstance(d, float) else str(d) for d in data])
        with open(SERIALS_LOG, 'a') as f:
          f.write('%10.3f RECD@%s: %s\n' % (ts, self.name, str_data))
    if self.read_timeout and self.last_read - self.last_receipt > self.read_timeout:


      if self.error_pin:
        self.to_parent_q.put(('pin', (self.error_pin, True)))
      self.Reopen(log_message='Heartbeat not received in %.2f seconds (expected: %.2f)'
                  % (self.last_read - self.last_receipt, self.read_timeout))
      return self.Read(format_string=format_string)

    return data

  def Write(self, values, format_string=None):
    """Writes to an open serial.

    Writes to an open serial values as identified in the format_string provided here,
    or if not provided in this call, as saved on the Serial instance.  If an OSError
    exception is detected, this method will attempt to reopen the connection.

    Args:
      values: tuple of values to send matching that as identified in format_string.
      format_string: String of the form expected by struct.pack
    """
    ts = time.time() - self.start_time
    str_values = str(['%7.2f' % v if isinstance(v, float) else str(v) for v in values])
    if self.connection_type == CONNECTION_FLAG_SIMULATED:
      with open(self.connection_tuple[1], 'a') as f:
        f.write('%10.3f: %s\n' % (ts, str_values))
      return

    if not format_string:
      format_string = self.write_format
    try:
      Write(self.link, values, format_string)
    except OSError as e:

      if self.error_pin:
        self.to_parent_q.put(('pin', (self.error_pin, True)))
      self.Reopen(log_message='Failed to write: %s' % e)
      self.Write(values)
    if LOG_SERIALS:
      with open(SERIALS_LOG, 'a') as f:
        f.write('%10.3f SENT@%s: %s\n' % (ts, self.name, str_values))

  def HasReset(self):
    """Indicates exactly oncewhether the serial connection has reset since last called."""
    if self.connection_type == CONNECTION_FLAG_SIMULATED:
      raise NotImplementedError('Not implemented for simulations')

    flag = self.reset_flag
    self.reset_flag = False
    return flag


def RunCommand(cmd, sleep_seconds=1, log=True):
  """Runs shell command, checking if it completed (perhaps with errors) within timeout."""
  conn = subprocess.Popen(cmd, shell=True)
  time.sleep(sleep_seconds)
  conn.poll()




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




      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']:
        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()
  Log('Shutdown signal received by process %d' % os.getpid(), link)
  to_parent_q.put(('pin', (messageboard.GPIO_ERROR_ARDUINO_SERVO_CONNECTION, True)))





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




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





        TestDisplayMode(DISP_LAST_FLIGHT_NUMB_ORIG_DEST)
        TestDisplayMode(DISP_LAST_FLIGHT_AZIMUTH_ELEVATION)
        TestDisplayMode(DISP_FLIGHT_COUNT_LAST_SEEN)
        TestDisplayMode(DISP_RADIO_RANGE)

    if time.time() >= next_write:
      next_write = SendRemoteMessage(
          flight, json_desc_dict, configuration, additional_attr,
          display_mode, write_keys, write_format_tuple, link)

    if time.time() >= next_read:
      values_t = link.Read()  # simple ack message sent by servos
      values_d = dict(zip(read_keys, values_t))
      if values_d.get('confirmed'):
        display_mode, low_batt = ExecuteArduinoCommand(
            values_d, configuration, display_mode, low_batt, to_parent_q, link)
      next_read = time.time() + READ_DELAY_TIME

  link.Close()
  Log('Shutdown signal received by process %d' % os.getpid(), link)
  to_parent_q.put(('pin', (messageboard.GPIO_ERROR_ARDUINO_REMOTE_CONNECTION, True)))




01234567890123456789012345678901234567890123456789012345678901234567890123456789









3334353637383940414243444546474849505152535455565758596061626364656667686970717273747576








269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358








666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710








1223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247



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





if RASPBERRY_PI:
  ARDUINO_LOG = MESSAGEBOARD_PATH + ARDUINO_LOG
  SERIALS_LOG = MESSAGEBOARD_PATH + SERIALS_LOG
  SERVO_SIMULATED_OUT = MESSAGEBOARD_PATH + SERVO_SIMULATED_OUT
  SERVO_SIMULATED_IN = MESSAGEBOARD_PATH + SERVO_SIMULATED_IN
  REMOTE_SIMULATED_OUT = MESSAGEBOARD_PATH + REMOTE_SIMULATED_OUT
  REMOTE_SIMULATED_IN = MESSAGEBOARD_PATH + REMOTE_SIMULATED_IN

  ARDUINO_ROLLING_LOG = WEBSERVER_PATH + ARDUINO_ROLLING_LOG

CONNECTION_FLAG_BLUETOOTH = 1
CONNECTION_FLAG_USB = 2
CONNECTION_FLAG_SIMULATED = 3
RASPBERRY_PI = psutil.sys.platform.title() == 'Linux'

SN_SERVO = '5583834303435111C1A0'
SERVO_CONNECTION = (CONNECTION_FLAG_BLUETOOTH, (2, '98:D3:11:FC:42:16', 1))

SN_REMOTE = '75835343130351802272'
# directly connected to Serial2
# REMOTE_CONNECTION = (CONNECTION_FLAG_BLUETOOTH, (1, '98:D3:91:FD:B1:8F', 1))
# connected thru MOSFET to Serial1
REMOTE_CONNECTION = (CONNECTION_FLAG_BLUETOOTH, (1, '98:D3:91:FD:B3:C9', 1))

MIN_ALTITUDE = 5  # below this elevation degrees, turn off the tracking

if SIMULATE_ARDUINO:
  SERVO_CONNECTION = (CONNECTION_FLAG_SIMULATED, (SERVO_SIMULATED_IN, SERVO_SIMULATED_OUT))
  REMOTE_CONNECTION = (
      CONNECTION_FLAG_SIMULATED, (REMOTE_SIMULATED_IN, REMOTE_SIMULATED_OUT))

KEY_NOT_PRESENT_STRING = 'N/A'

DISP_LAST_FLIGHT_NUMB_ORIG_DEST = 0
DISP_LAST_FLIGHT_AZIMUTH_ELEVATION = 1
DISP_FLIGHT_COUNT_LAST_SEEN = 2
DISP_RADIO_RANGE = 3
DISPLAY_MODE_NAMES = [
    'LAST_FLIGHT_NUMB_ORIG_DEST', 'LAST_FLIGHT_AZIMUTH_ELEVATION',
    'FLIGHT_COUNT_LAST_SEEN', 'RADIO_RANGE']

WRITE_DELAY_TIME = 0.2  # write to arduino every n seconds
READ_DELAY_TIME = 0.1  # read from arduino every n seconds




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





    Args:
      format_string: String of the form expected by struct.pack

    Returns:
      Tuple of values matching that as identified in format_string.
    """
    if self.connection_type == CONNECTION_FLAG_SIMULATED:
      if (
          self.__simulated_reads__ and
          time.time() - self.start_time > self.__simulated_reads__[0][0]):  # time for next
        next_line = self.__simulated_reads__.pop(0)
        return next_line[1]
      return ()

    if not format_string:
      format_string = self.read_format
    try:
      data = Read(self.link, format_string)
    except OSError as e:
      failure_message = 'Failed to read: %s' % e
      if self.error_pin:
        self.to_parent_q.put(('pin', (self.error_pin, True, failure_message)))
      self.Reopen(log_message=failure_message)
      return self.Read(format_string=format_string)
    self.last_read = time.time()
    if data:
      self.last_receipt = time.time()
      if LOG_SERIALS:
        ts = time.time() - self.start_time
        str_data = str(['%7.2f' % d if isinstance(d, float) else str(d) for d in data])
        with open(SERIALS_LOG, 'a') as f:
          f.write('%10.3f RECD@%s: %s\n' % (ts, self.name, str_data))
    if self.read_timeout and self.last_read - self.last_receipt > self.read_timeout:
      failure_message = 'Heartbeat not received in %.2f seconds (expected: %.2f)' % (
          self.last_read - self.last_receipt, self.read_timeout)
      if self.error_pin:
        self.to_parent_q.put(('pin', (self.error_pin, True, failure_message)))
      self.Reopen(log_message=failure_message)

      return self.Read(format_string=format_string)

    return data

  def Write(self, values, format_string=None):
    """Writes to an open serial.

    Writes to an open serial values as identified in the format_string provided here,
    or if not provided in this call, as saved on the Serial instance.  If an OSError
    exception is detected, this method will attempt to reopen the connection.

    Args:
      values: tuple of values to send matching that as identified in format_string.
      format_string: String of the form expected by struct.pack
    """
    ts = time.time() - self.start_time
    str_values = str(['%7.2f' % v if isinstance(v, float) else str(v) for v in values])
    if self.connection_type == CONNECTION_FLAG_SIMULATED:
      with open(self.connection_tuple[1], 'a') as f:
        f.write('%10.3f: %s\n' % (ts, str_values))
      return

    if not format_string:
      format_string = self.write_format
    try:
      Write(self.link, values, format_string)
    except OSError as e:
      failure_message = 'Failed to write: %s' % e
      if self.error_pin:
        self.to_parent_q.put(('pin', (self.error_pin, True, failure_message)))
      self.Reopen(log_message=failure_message)
      self.Write(values)
    if LOG_SERIALS:
      with open(SERIALS_LOG, 'a') as f:
        f.write('%10.3f SENT@%s: %s\n' % (ts, self.name, str_values))

  def HasReset(self):
    """Indicates exactly oncewhether the serial connection has reset since last called."""
    if self.connection_type == CONNECTION_FLAG_SIMULATED:
      raise NotImplementedError('Not implemented for simulations')

    flag = self.reset_flag
    self.reset_flag = False
    return flag


def RunCommand(cmd, sleep_seconds=1, log=True):
  """Runs shell command, checking if it completed (perhaps with errors) within timeout."""
  conn = subprocess.Popen(cmd, shell=True)
  time.sleep(sleep_seconds)
  conn.poll()




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




      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']:
        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()
  failure_message = 'Shutdown signal received by process %d' % os.getpid()
  Log(failure_message, link)
  to_parent_q.put((
      'pin',
      (messageboard.GPIO_ERROR_ARDUINO_SERVO_CONNECTION, True, failure_message)))


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




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





        TestDisplayMode(DISP_LAST_FLIGHT_NUMB_ORIG_DEST)
        TestDisplayMode(DISP_LAST_FLIGHT_AZIMUTH_ELEVATION)
        TestDisplayMode(DISP_FLIGHT_COUNT_LAST_SEEN)
        TestDisplayMode(DISP_RADIO_RANGE)

    if time.time() >= next_write:
      next_write = SendRemoteMessage(
          flight, json_desc_dict, configuration, additional_attr,
          display_mode, write_keys, write_format_tuple, link)

    if time.time() >= next_read:
      values_t = link.Read()  # simple ack message sent by servos
      values_d = dict(zip(read_keys, values_t))
      if values_d.get('confirmed'):
        display_mode, low_batt = ExecuteArduinoCommand(
            values_d, configuration, display_mode, low_batt, to_parent_q, link)
      next_read = time.time() + READ_DELAY_TIME

  link.Close()
  failure_message = 'Shutdown signal received by process %d' % os.getpid()
  Log(failure_message, link)
  to_parent_q.put((
      'pin',
      (messageboard.GPIO_ERROR_ARDUINO_REMOTE_CONNECTION, True, failure_message)))