Example #1
0
static bool
ReadFlightListInner(Port &port,
                    RecordedFlightList &flight_list,
                    OperationEnvironment &env)
{
  env.SetProgressRange(10);
  if (!Volkslogger::ConnectAndFlush(port, env, 20000))
    return false;
  env.SetProgressPosition(3);

  uint8_t dirbuffer[VLAPI_LOG_MEMSIZE];
  int data_length = Volkslogger::ReadFlightList(port, env,
                                                dirbuffer, sizeof(dirbuffer));
  if (data_length <= 0)
    return data_length == 0;

  std::vector<DIRENTRY> directory;
  if (!conv_dir(directory, dirbuffer, data_length))
    return false;

  if (directory.empty())
    return true;

  env.SetProgressPosition(8);
  if (!ConvertDirectoryToRecordedFlightList(directory, flight_list))
    return false;
  env.SetProgressPosition(10);

  return true;
}
Example #2
0
void
CAI302WaypointUploader::Run(OperationEnvironment &env)
{
  Waypoints waypoints;

  env.SetText(_("Loading Waypoints..."));
  if (!reader.Parse(waypoints, env)) {
    env.SetErrorMessage(_("Failed to load file."));
    return;
  }

  if (waypoints.size() > 9999) {
    env.SetErrorMessage(_("Too many waypoints."));
    return;
  }

  env.SetText(_("Uploading Waypoints"));
  env.SetProgressRange(waypoints.size() + 1);
  env.SetProgressPosition(0);

  if (!device.ClearPoints(env)) {
    if (!env.IsCancelled())
      env.SetErrorMessage(_("Failed to erase waypoints."));
    return;
  }

  if (!device.EnableBulkMode(env)) {
    if (!env.IsCancelled())
      env.SetErrorMessage(_("Failed to switch baud rate."));
    return;
  }

  unsigned id = 1;
  for (auto i = waypoints.begin(), end = waypoints.end();
       i != end; ++i, ++id) {
    if (env.IsCancelled())
      break;

    env.SetProgressPosition(id);

    if (!device.WriteNavpoint(id, *i, env)) {
      if (!env.IsCancelled())
        env.SetErrorMessage(_("Failed to write waypoint."));
      break;
    }
  }

  device.DisableBulkMode(env);
}
Example #3
0
int
Net::DownloadToBuffer(Session &session, const char *url,
                      void *_buffer, size_t max_length,
                      OperationEnvironment &env)
{
  Request request(session, url, 10000);
  if (!request.Send(10000))
    return -1;

  int64_t total = request.GetLength();
  if (total >= 0)
    env.SetProgressRange(total);
  total = 0;

  uint8_t *buffer = (uint8_t *)_buffer, *p = buffer, *end = buffer + max_length;
  while (p != end) {
    if (env.IsCancelled())
      return -1;

    ssize_t nbytes = request.Read(p, end - p, 5000);
    if (nbytes < 0)
      return -1;
    if (nbytes == 0)
      break;

    p += nbytes;

    total += nbytes;
    env.SetProgressPosition(total);
  }

  return p - buffer;
}
/**
 * Parses the data provided by the airfield details file handle
 */
static void
ParseAirfieldDetails(Waypoints &way_points, TLineReader &reader,
                     OperationEnvironment &operation)
{
  tstring details;
  std::vector<tstring> files_external, files_embed;
  TCHAR name[201];
  const TCHAR *filename;

  name[0] = 0;

  bool in_details = false;
  int i;

  const long filesize = std::max(reader.GetSize(), 1l);
  operation.SetProgressRange(100);

  TCHAR *line;
  while ((line = reader.ReadLine()) != NULL) {
    if (line[0] == _T('[')) { // Look for start
      if (in_details)
        SetAirfieldDetails(way_points, name, details, files_external,
                           files_embed);

      details.clear();
      files_external.clear();
      files_embed.clear();

      // extract name
      for (i = 1; i < 201; i++) {
        if (line[i] == _T(']'))
          break;

        name[i - 1] = line[i];
      }
      name[i - 1] = 0;

      in_details = true;

      operation.SetProgressPosition(reader.Tell() * 100 / filesize);
    } else if ((filename =
                StringAfterPrefixCI(line, _T("image="))) != NULL) {
      files_embed.emplace_back(filename);
    } else if ((filename =
                StringAfterPrefixCI(line, _T("file="))) != NULL) {
#ifdef ANDROID
      files_external.emplace_back(filename);
#endif
    } else {
      // append text to details string
      if (!StringIsEmpty(line)) {
        details += line;
        details += _T('\n');
      }
    }
  }

  if (in_details)
    SetAirfieldDetails(way_points, name, details, files_external, files_embed);
}
Example #5
0
bool
Volkslogger::WriteBulk(Port &port, OperationEnvironment &env,
                       const void *buffer, unsigned length)
{
  const unsigned delay = 1;

  env.SetProgressRange(length);

  uint16_t crc16 = 0;
  const uint8_t *p = (const uint8_t *)buffer, *end = p + length;
  while (p < end) {
    unsigned n = end - p;
    if (n > 400)
      n = 400;

    n = port.Write(p, n);
    if (n == 0)
      return false;

    crc16 = UpdateCRC16CCITT(p, n, crc16);
    p += n;

    env.SetProgressPosition(p - (const uint8_t *)buffer);

    /* throttle sending a bit, or the Volkslogger's receive buffer
       will overrun */
    env.Sleep(delay * 100);
  }

  return port.Write(crc16 >> 8) && port.Write(crc16 & 0xff);
}
Example #6
0
 virtual void Run(OperationEnvironment &env) {
   env.SetText(_T("Working..."));
   env.SetProgressRange(30);
   for (unsigned i = 0; i < 30 && !env.IsCancelled(); ++i) {
     env.SetProgressPosition(i);
     env.Sleep(500);
   }
 }
Example #7
0
bool
AirspaceParser::Parse(TLineReader &reader, OperationEnvironment &operation)
{
  bool ignore = false;

  // Create and init ProgressDialog
  operation.SetProgressRange(1024);

  const long file_size = reader.GetSize();

  TempAirspaceType temp_area;
  AirspaceFileType filetype = AFT_UNKNOWN;

  TCHAR *line;

  // Iterate through the lines
  for (unsigned line_num = 1; (line = reader.ReadLine()) != NULL; line_num++) {
    // Skip empty line
    if (StringIsEmpty(line))
      continue;

    if (filetype == AFT_UNKNOWN) {
      filetype = DetectFileType(line);
      if (filetype == AFT_UNKNOWN)
        continue;
    }

    // Parse the line
    if (filetype == AFT_OPENAIR)
      if (!ParseLine(airspaces, line, temp_area) &&
          !ShowParseWarning(line_num, line, operation))
        return false;

    if (filetype == AFT_TNP)
      if (!ParseLineTNP(airspaces, line, temp_area, ignore) &&
          !ShowParseWarning(line_num, line, operation))
        return false;

    // Update the ProgressDialog
    if ((line_num & 0xff) == 0)
      operation.SetProgressPosition(reader.Tell() * 1024 / file_size);
  }

  if (filetype == AFT_UNKNOWN) {
    operation.SetErrorMessage(_("Unknown airspace filetype"));
    return false;
  }

  // Process final area (if any)
  if (!temp_area.points.empty())
    temp_area.AddPolygon(airspaces);

  return true;
}
Example #8
0
bool
FlarmDevice::DownloadFlight(Path path, OperationEnvironment &env)
{
  FileOutputStream fos(path);
  BufferedOutputStream os(fos);

  if (env.IsCancelled())
    return false;

  env.SetProgressRange(100);
  while (true) {
    // Create header for getting IGC file data
    FLARM::FrameHeader header = PrepareFrameHeader(FLARM::MT_GETIGCDATA);

    // Send request
    if (!SendStartByte() ||
        !SendFrameHeader(header, env, 1000) ||
        env.IsCancelled())
      return false;

    // Wait for an answer and save the payload for further processing
    AllocatedArray<uint8_t> data;
    uint16_t length;
    bool ack = WaitForACKOrNACK(header.GetSequenceNumber(), data,
                                length, env, 10000) == FLARM::MT_ACK;

    // If no ACK was received
    if (!ack || length <= 3 || env.IsCancelled())
      return false;

    length -= 3;

    // Read progress (in percent)
    uint8_t progress = *(data.begin() + 2);
    env.SetProgressPosition(std::min((unsigned)progress, 100u));

    const char *last_char = (const char *)data.end() - 1;
    bool is_last_packet = (*last_char == 0x1A);
    if (is_last_packet)
      length--;

    // Read IGC data
    const char *igc_data = (const char *)data.begin() + 3;
    os.Write(igc_data, length);

    if (is_last_packet)
      break;
  }

  os.Flush();
  fos.Commit();

  return true;
}
Example #9
0
static bool
DownloadToFile(Net::Session &session, const char *url, FILE *file,
               char *md5_digest,
               OperationEnvironment &env)
{
  assert(url != NULL);
  assert(file != NULL);

  Net::Request request(session, url, 10000);
  if (!request.Send(10000))
    return false;

  int64_t total = request.GetLength();
  if (total >= 0)
    env.SetProgressRange(total);
  total = 0;

  MD5 md5;
  md5.InitKey();

  uint8_t buffer[4096];
  while (true) {
    if (env.IsCancelled())
      return false;

    ssize_t nbytes = request.Read(buffer, sizeof(buffer), 5000);
    if (nbytes < 0)
      return false;

    if (nbytes == 0)
      break;

    if (md5_digest != NULL)
      md5.Append(buffer, nbytes);

    size_t written = fwrite(buffer, 1, nbytes, file);
    if (written != (size_t)nbytes)
      return false;

    total += nbytes;
    env.SetProgressPosition(total);
  }

  if (md5_digest != NULL) {
    md5.Finalize();
    md5.GetDigest(md5_digest);
  }

  return true;
}
Example #10
0
static bool
DownloadFlightInner(Port &port, const RecordedFlightInfo &flight,
                    FILE *file, OperationEnvironment &env)
{
  if (!LX::CommandMode(port, env))
    return false;

  port.Flush();

  LX::SeekMemory seek;
  seek.start_address = flight.internal.lx.start_address;
  seek.end_address = flight.internal.lx.end_address;
  if (!LX::SendPacket(port, LX::SEEK_MEMORY, &seek, sizeof(seek), env) ||
      !LX::ExpectACK(port, env))
      return false;

  LX::MemorySection memory_section;
  if (!LX::ReceivePacketRetry(port, LX::READ_MEMORY_SECTION,
                              &memory_section, sizeof(memory_section), env,
                              5000, 2000, 60000, 2))
      return false;

  unsigned lengths[LX::MemorySection::N];
  unsigned total_length = 0;
  for (unsigned i = 0; i < LX::MemorySection::N; ++i) {
    lengths[i] = FromBE16(memory_section.lengths[i]);
    total_length += lengths[i];
  }

  env.SetProgressRange(total_length);

  uint8_t *data = new uint8_t[total_length], *p = data;
  for (unsigned i = 0; i < LX::MemorySection::N && lengths[i] > 0; ++i) {
    if (!LX::ReceivePacketRetry(port, (LX::Command)(LX::READ_LOGGER_DATA + i),
                                p, lengths[i], env,
                                20000, 2000, 300000, 2)) {
      delete [] data;
      return false;
    }

    p += lengths[i];
    env.SetProgressPosition(p - data);
  }

  bool success = LX::ConvertLXNToIGC(data, total_length, file);
  delete [] data;

  return success;
}
Example #11
0
static bool
DownloadFlightInner(Port &port, const char *filename, FILE *file,
                    OperationEnvironment &env)
{
  PortNMEAReader reader(port, env);
  unsigned row_count = 0, i = 1;

  while (true) {
    /* read up to 32 lines at a time */
    unsigned nrequest = row_count == 0 ? 1 : 32;
    if (row_count > 0) {
      assert(i <= row_count);
      const unsigned remaining = row_count - i + 1;
      if (nrequest > remaining)
        nrequest = remaining;
    }

    const unsigned start = i;
    const unsigned end = start + nrequest;

    /* send request to Nano */

    reader.Flush();
    if (!RequestFlight(port, filename, start, end, env))
      return false;

    /* read the requested lines and save to file */

    TimeoutClock timeout(2000);
    while (i != end) {
      const char *line = reader.ExpectLine("PLXVC,FLIGHT,A,", timeout);
      if (line == nullptr ||
          !HandleFlightLine(line, file, i, row_count))
        return false;
    }

    if (i > row_count)
      /* finished successfully */
      return true;

    if (start == 1)
      /* configure the range in the first iteration, now that we know
         the length of the file */
      env.SetProgressRange(row_count);

    env.SetProgressPosition(i - 1);
  }
}
Example #12
0
/**
 * Parses the data provided by the airfield details file handle
 */
static void
ParseAirfieldDetails(Waypoints &way_points, TLineReader &reader,
                     OperationEnvironment &operation)
{
  tstring Details;
  TCHAR Name[201];

  Name[0] = 0;

  bool inDetails = false;
  int i;

  long filesize = std::max(reader.size(), 1l);
  operation.SetProgressRange(100);

  TCHAR *TempString;
  while ((TempString = reader.read()) != NULL) {
    if (TempString[0] == _T('[')) { // Look for start
      if (inDetails)
        SetAirfieldDetails(way_points, Name, Details);

      Details.clear();

      // extract name
      for (i = 1; i < 201; i++) {
        if (TempString[i] == _T(']'))
          break;

        Name[i - 1] = TempString[i];
      }
      Name[i - 1] = 0;

      inDetails = true;

      operation.SetProgressPosition(reader.tell() * 100 / filesize);
    } else {
      // append text to details string
      if (!string_is_empty(TempString)) {
        Details += TempString;
        Details += _T('\n');
      }
    }
  }

  if (inDetails)
    SetAirfieldDetails(way_points, Name, Details);
}
Example #13
0
void
WaypointReaderBase::Parse(Waypoints &way_points, TLineReader &reader,
                          OperationEnvironment &operation)
{
  const long filesize = std::max(reader.GetSize(), 1l);
  operation.SetProgressRange(100);

  // Read through the lines of the file
  TCHAR *line;
  for (unsigned i = 0; (line = reader.ReadLine()) != nullptr; i++) {
    // and parse them
    ParseLine(line, i, way_points);

    if ((i & 0x3f) == 0)
      operation.SetProgressPosition(reader.Tell() * 100 / filesize);
  }
}
Example #14
0
static bool
ReadFlightListInner(Port &port, RecordedFlightList &flight_list,
                    OperationEnvironment &env)
{
  env.SetProgressRange(8);

  for (unsigned i = 0; i < 8 && !flight_list.full(); ++i) {
    CAI302::FileList file_list;
    if (!CAI302::UploadFileList(port, i, file_list, env))
      break;

    for (unsigned j = 0; j < 8 && !flight_list.full(); ++j) {
      const CAI302::FileList::FileInfo &file = file_list.files[j];
      if (file.start_utc.month > 0)
        Copy(flight_list.append(), i * 8 + j, file);
    }

    env.SetProgressPosition(i);
  }

  return !flight_list.empty() && !env.IsCancelled();
}
Example #15
0
bool
Nano::ReadFlightList(Port &port, RecordedFlightList &flight_list,
                     OperationEnvironment &env)
{
  port.StopRxThread();
  PortNMEAReader reader(port, env);

  TimeoutClock timeout(2000);
  int nflights = GetNumberOfFlights(port, reader, env, timeout);
  if (nflights <= 0)
    return nflights == 0;

  env.SetProgressRange(nflights);

  unsigned requested_tail = 1;
  while (true) {
    const unsigned room = flight_list.max_size() - flight_list.size();
    const unsigned remaining = nflights - requested_tail + 1;
    const unsigned nmax = std::min(room, remaining);
    if (nmax == 0)
      break;

    /* read 8 records at a time */
    const unsigned nrequest = std::min(nmax, 8u);

    timeout = TimeoutClock(2000);
    if (!GetLogbookContents(port, reader, flight_list,
                            requested_tail, nrequest, env, timeout))
      return false;

    requested_tail += nrequest;
    env.SetProgressPosition(requested_tail - 1);
  }

  return true;
}
Example #16
0
void
TopographyStore::Load(OperationEnvironment &operation, NLineReader &reader,
                      const TCHAR *directory, struct zzip_dir *zdir)
{
  Reset();

  // Create buffer for the shape filenames
  // (shape_filename will be modified with the shape_filename_end pointer)
  char shape_filename[MAX_PATH];
  if (directory != nullptr) {
    const WideToACPConverter narrow_directory(directory);
    strcpy(shape_filename, narrow_directory);
    strcat(shape_filename, DIR_SEPARATOR_S);
  } else
    shape_filename[0] = 0;

  char *shape_filename_end = shape_filename + strlen(shape_filename);

  // Read file size to have a rough progress estimate for the progress bar
  const long filesize = std::max(reader.GetSize(), 1l);

  // Set progress bar to 100 steps
  operation.SetProgressRange(100);

  // Iterate through shape files in the "topology.tpl" file until
  // end or max. file number reached
  char *line;
  while (!files.full() && (line = reader.ReadLine()) != nullptr) {
    // .tpl Line format: filename,range,icon,field,r,g,b,pen_width,label_range,important_range,alpha

    // Ignore comments (lines starting with *) and empty lines
    if (StringIsEmpty(line) || line[0] == '*')
      continue;

    // Find first comma to extract shape filename
    char *p = strchr(line, ',');
    if (p == nullptr || p == line)
      // If no comma was found -> ignore this line/shapefile
      continue;

    if (HasLittleMemory()) {
      /* hard-coded blacklist for huge files on PPC2000; those
         devices usually have very little memory */

      // Null-terminate the line string after the first comma
      // for strcmp() calls in IsHugeTopographyFile() function
      *p = 0;

      // Skip large topography files
      if (IsHugeTopographyFile(line))
        continue;
    }

    // Extract filename and append it to the shape_filename buffer
    memcpy(shape_filename_end, line, p - line);
    // Append ".shp" file extension to the shape_filename buffer
    strcpy(shape_filename_end + (p - line), ".shp");

    // Parse shape range
    fixed shape_range = fixed(strtod(p + 1, &p)) * 1000;
    if (*p != _T(','))
      continue;

    // Extract shape icon name
    char icon_name[23];
    char *start = p + 1;
    p = strchr(start, ',');
    // Null-terminate the line string at the next comma for strncpy() call
    *p = 0;
    strncpy(icon_name, start, 22);
    ResourceId icon = ResourceId::Null(), big_icon = ResourceId::Null();

    if (strlen(icon_name) > 0) {
      const LOOKUP_ICON *ip = icon_list;
      while (ip->name != nullptr) {
        if (StringIsEqual(ip->name, icon_name)) {
          icon = ip->resource_id;
          big_icon = ip->big_resource_id;
          break;
        }
        ip++;
      }
    }

    // Parse shape field for text display
    long shape_field = strtol(p + 1, &p, 10) - 1;
    if (*p != _T(','))
      continue;

    // Parse red component of line / shading colour
    uint8_t red = (uint8_t)strtol(p + 1, &p, 10);
    if (*p != _T(','))
      continue;

    // Parse green component of line / shading colour
    uint8_t green = (uint8_t)strtol(p + 1, &p, 10);
    if (*p != _T(','))
      continue;

    // Parse blue component of line / shading colour
    uint8_t blue = (uint8_t)strtol(p + 1, &p, 10);

    // Parse pen width of lines
    unsigned pen_width = 1;
    if (*p == _T(',')) {
      pen_width = strtoul(p + 1, &p, 10);
      if (pen_width < 1)
        pen_width = 1;
      else if (pen_width>31)
        pen_width=31;
    }

    // Parse range for displaying labels
    fixed label_range = shape_range;
    if (*p == _T(','))
      label_range = fixed(strtod(p + 1, &p)) * 1000;

    // Parse range for displaying labels with "important" rendering style
    fixed labelImportantRange = fixed(0);
    if (*p == _T(','))
      labelImportantRange = fixed(strtod(p + 1, &p)) * 1000;

    // Handle alpha component
    // If not present at all (i.e. v6.6 or earlier file), default to 100% opaque
    uint8_t alpha = 255;
    if (*p == _T(',')) {
      // An alpha component of shading colour is present (v6.7 or later file).
      alpha = (uint8_t)strtol(p + 1, &p, 10);
      // Ignore a totally transparent file!
      if (alpha == 0)
        continue;
#ifndef ENABLE_OPENGL
      // Without OpenGL ignore anything but 100% opaque
      if (alpha != 255)
        continue;
#endif
    }

    // Create TopographyFile instance from parsed line
    TopographyFile *file = new TopographyFile(zdir, shape_filename,
                                              shape_range, label_range,
                                              labelImportantRange,
#ifdef ENABLE_OPENGL
                                              Color(red, green, blue, alpha),
#else
                                              Color(red, green, blue),
#endif
                                              shape_field, icon, big_icon,
                                              pen_width);
    if (file->IsEmpty())
      // If the shape file could not be read -> skip this line/file
      delete file;
    else
      // .. otherwise append it to our list of shape files
      files.append(file);

    // Update progress bar
    operation.SetProgressPosition((reader.Tell() * 100) / filesize);
  }
}
Example #17
0
bool
FlytecDevice::DownloadFlight(const RecordedFlightInfo &flight,
                             Path path, OperationEnvironment &env)
{
  port.StopRxThread();

  PeriodClock status_clock;
  status_clock.Update();

  // Request flight record
  char buffer[256];
  sprintf(buffer, "$PBRTR,%02d", flight.internal.flytec);
  AppendNMEAChecksum(buffer);
  strcat(buffer, "\r\n");

  port.Write(buffer);
  if (!ExpectXOff(port, env, 1000))
    return false;

  // Open file writer
  FileHandle writer(path, _T("wb"));
  if (!writer.IsOpen())
    return false;

  unsigned start_sec = flight.start_time.GetSecondOfDay();
  unsigned end_sec = flight.end_time.GetSecondOfDay();
  if (end_sec < start_sec)
    end_sec += 24 * 60 * 60;

  unsigned range = end_sec - start_sec;
  env.SetProgressRange(range);

  while (true) {
    // Check if the user cancelled the operation
    if (env.IsCancelled())
      return false;

    // Receive the next line
    if (!ReceiveLine(port, buffer, ARRAY_SIZE(buffer), 1000))
      return false;

    // XON was received
    if (StringIsEmpty(buffer))
      break;

    if (status_clock.CheckUpdate(250) &&
        *buffer == 'B') {
      // Parse the fix time
      BrokenTime time;
      if (IGCParseTime(buffer + 1, time)) {

        unsigned time_sec = time.GetSecondOfDay();
        if (time_sec < start_sec)
          time_sec += 24 * 60 * 60;

        if (time_sec > end_sec + 5 * 60)
          time_sec = start_sec;

        unsigned position = time_sec - start_sec;
        if (position > range)
          position = range;

        env.SetProgressPosition(position);
      }
    }

    // Write line to the file
    writer.Write(buffer);
  }

  return true;
}
Example #18
0
bool
FlytecDevice::ReadFlightList(RecordedFlightList &flight_list,
                             OperationEnvironment &env)
{
  port.StopRxThread();

  char buffer[256];
  strcpy(buffer, "$PBRTL,");
  AppendNMEAChecksum(buffer);
  strcat(buffer, "\r\n");

  port.Write(buffer);
  if (!ExpectXOff(port, env, 1000))
    return false;

  unsigned tracks = 0;
  while (true) {
    // Check if the user cancelled the operation
    if (env.IsCancelled())
      return false;

    // Receive the next line
    if (!ReceiveLine(port, buffer, ARRAY_SIZE(buffer), 1000))
      return false;

    // XON was received, last record was read already
    if (StringIsEmpty(buffer))
      break;

    // $PBRTL    Identifier
    // AA        total number of stored tracks
    // BB        actual number of track (0 indicates the most actual track)
    // DD.MM.YY  date of recorded track (UTC)(e.g. 24.03.04)
    // hh:mm:ss  starttime (UTC)(e.g. 08:23:15)
    // HH:MM:SS  duration (e.g. 03:23:15)
    // *ZZ       Checksum as defined by NMEA

    RecordedFlightInfo flight;
    NMEAInputLine line(buffer);

    // Skip $PBRTL
    line.Skip();

    if (tracks == 0) {
      // If number of tracks not read yet
      // .. read and save it
      if (!line.ReadChecked(tracks))
        continue;

      env.SetProgressRange(tracks);
    } else
      line.Skip();

    if (!line.ReadChecked(flight.internal.flytec))
      continue;

    if (tracks != 0 && flight.internal.flytec < tracks)
      env.SetProgressPosition(flight.internal.flytec);

    char field_buffer[16];
    line.Read(field_buffer, ARRAY_SIZE(field_buffer));
    if (!ParseDate(field_buffer, flight.date))
      continue;

    line.Read(field_buffer, ARRAY_SIZE(field_buffer));
    if (!ParseTime(field_buffer, flight.start_time))
      continue;

    BrokenTime duration;
    line.Read(field_buffer, ARRAY_SIZE(field_buffer));
    if (!ParseTime(field_buffer, duration))
      continue;

    flight.end_time = flight.start_time + duration;
    flight_list.append(flight);
  }

  return true;
}
Example #19
0
static bool
DownloadFlightInner(Port &port, const RecordedFlightInfo &flight,
                    const TCHAR *path, OperationEnvironment &env)
{
  assert(flight.internal.cai302 < 64);

  BinaryWriter writer(path);
  if (writer.HasError())
    return false;

  CAI302::FileASCII file_ascii;
  if (!UploadFileASCII(port, flight.internal.cai302, file_ascii, env) ||
      env.IsCancelled())
    return false;

  unsigned bytes_per_block = ReadUnalignedBE16(&file_ascii.bytes_per_block);
  unsigned num_blocks = ReadUnalignedBE16(&file_ascii.num_blocks);
  env.SetProgressRange(num_blocks);

  unsigned allocated_size = sizeof(CAI302::FileData) + bytes_per_block;
  void *allocated = malloc(allocated_size);
  CAI302::FileData *header = (CAI302::FileData *)allocated;
  void *data = header + 1;

  unsigned current_block = 0;
  unsigned valid_bytes;
  do {
    int i = UploadFileData(port, true, header, allocated_size, env);
    if (i < (int)sizeof(*header)) {
      free(allocated);
      return false;
    }

    i -= sizeof(*header);

    valid_bytes = FromBE16(header->valid_bytes);
    if ((unsigned)i < valid_bytes) {
      free(allocated);
      return false;
    }

    if (!writer.Write(data, 1, valid_bytes)) {
      free(allocated);
      return false;
    }

    env.SetProgressPosition(current_block++);
  } while (valid_bytes == bytes_per_block);

  free(allocated);

  CAI302::FileSignatureASCII signature;
  if (!CAI302::UploadFileSignatureASCII(port, signature, env))
    return false;

  valid_bytes = FromBE16(signature.size);
  if (valid_bytes > sizeof(signature.signature))
    return false;

  if (!writer.Write(signature.signature, 1, valid_bytes))
    return false;

  return true;
}
Example #20
0
static bool
DownloadFlightInner(Port &port, const char *filename, FILE *file,
                    OperationEnvironment &env)
{
  PortNMEAReader reader(port, env);
  unsigned row_count = 0, i = 1;

  while (true) {
    /* read up to 32 lines at a time */
    unsigned nrequest = row_count == 0 ? 1 : 32;
    if (row_count > 0) {
      assert(i <= row_count);
      const unsigned remaining = row_count - i + 1;
      if (nrequest > remaining)
        nrequest = remaining;
    }

    const unsigned start = i;
    const unsigned end = start + nrequest;
    unsigned request_retry_count = 0;

    /* read the requested lines and save to file */

    while (i != end) {
      if (i == start) {
        /* send request range to Nano */
        reader.Flush();
        if (!RequestFlight(port, filename, start, end, env))
          return false;
        request_retry_count++;
      }

      TimeoutClock timeout(2000);
      const char *line = reader.ExpectLine("PLXVC,FLIGHT,A,", timeout);
      if (line == nullptr || !HandleFlightLine(line, file, i, row_count)) {
        if (request_retry_count > 5)
          return false;

        /* Discard data which might still be in-transit, e.g. buffered
           inside a bluetooth dongle */
        port.FullFlush(env, 200, 2000);

        /* If we already received parts of the request range correctly break
           out of the loop to calculate new request range */
        if (i != start)
          break;

        /* No valid reply received (i==start) - request same range again */
      }
    }

    if (i > row_count)
      /* finished successfully */
      return true;

    if (start == 1)
      /* configure the range in the first iteration, now that we know
         the length of the file */
      env.SetProgressRange(row_count);

    env.SetProgressPosition(i - 1);
  }
}
Example #21
0
int
Volkslogger::ReadBulk(Port &port, OperationEnvironment &env,
                      void *buffer, size_t max_length,
                      unsigned timeout_firstchar_ms)
{
  unsigned nbytes = 0;
  bool dle_r = false;
  uint16_t crc16 = 0;
  bool start = false, ende = false;

  memset(buffer, 0xff, max_length);

  uint8_t *p = (uint8_t *)buffer;

  constexpr unsigned TIMEOUT_NORMAL_MS = 2000;
  /**
   * We need to wait longer for the first char to
   * give the logger time to calculate security
   * when downloading a log-file.
   * Therefore timeout_firstchar is configurable.
   * If the timeout parameter is not specified or 0,
   * set standard timeout
   */
  if (timeout_firstchar_ms == 0)
    timeout_firstchar_ms = TIMEOUT_NORMAL_MS;

  unsigned const PROGRESS_BAR_RANGE = 1000;
  env.SetProgressRange(PROGRESS_BAR_RANGE);

  while (!ende) {
    env.SetProgressPosition(nbytes % PROGRESS_BAR_RANGE);
    // Zeichen anfordern und darauf warten
    if (!port.Write(ACK))
      return -1;

    // Set longer timeout on first char
    unsigned timeout = start ? TIMEOUT_NORMAL_MS : timeout_firstchar_ms;
    if (port.WaitRead(env, timeout) != Port::WaitResult::READY)
      return -1;

    int ch = port.GetChar();
    if (ch < 0)
      return -1;

    // dabei ist Benutzerabbruch jederzeit möglich
    if (env.IsCancelled()) {
      env.Sleep(10);
      port.Write(CAN);
      port.Write(CAN);
      port.Write(CAN);
      return -1;
    }

    // oder aber das empfangene Zeichen wird ausgewertet
    switch (ch) {
    case DLE:
      if (!dle_r) {             //!DLE, DLE -> Achtung!
        dle_r = true;
      }
      else { 	                 // DLE, DLE -> DLE-Zeichen
        dle_r = false;
        if (start) {
          if(nbytes < max_length)
            *p++ = ch;
          nbytes++;
          crc16 = UpdateCRC16CCITT(ch, crc16);
        }
      }
      break;
    case ETX:
      if (!dle_r) {             //!DLE, ETX -> Zeichen
        if (start) {
          if(nbytes < max_length) {
            *p++ = ch;
          }
          nbytes++;
          crc16 = UpdateCRC16CCITT(ch, crc16);
        };
      }
      else {
        if (start) {
          ende = true; // DLE, ETX -> Blockende
          dle_r = false;
        }
      }
      break;
    case STX:
      if (!dle_r) { //!DLE, STX -> Zeichen
        if (start) {
          if(nbytes < max_length)
            *p++ = ch;
          nbytes++;
          crc16 = UpdateCRC16CCITT(ch, crc16);
        }
      }
      else {
        start = true; // DLE, STX -> Blockstart
        dle_r = false;
        crc16 = 0;
      }
      break;
    default:
      if (start) {
        if(nbytes < max_length)
          *p++ = ch;
        nbytes++;
        crc16 = UpdateCRC16CCITT(ch, crc16);
      }
      break;
    }
  }

  env.SetProgressPosition(PROGRESS_BAR_RANGE);
  env.Sleep(100);

  if (crc16 != 0)
    return -1;

  if (nbytes < 2)
    return 0;

  // CRC am Ende abschneiden
  return nbytes - 2;
}
Example #22
0
bool
FlarmDevice::DeclareInternal(const Declaration &declaration,
                             OperationEnvironment &env)
{
  unsigned size = declaration.Size();

  env.SetProgressRange(6 + size);
  env.SetProgressPosition(0);

  if (!SetPilot(declaration.pilot_name.c_str(), env))
    return false;

  env.SetProgressPosition(1);

  if (!SetPlaneRegistration(declaration.aircraft_registration.c_str(), env))
    return false;

  env.SetProgressPosition(2);

  if (!SetPlaneType(declaration.aircraft_type.c_str(), env))
    return false;

  env.SetProgressPosition(3);

  if (!SetConfig("NEWTASK", "Task", env))
    return false;

  env.SetProgressPosition(4);

  if (!SetConfig("ADDWP", "0000000N,00000000E,T", env))
    return false;

  env.SetProgressPosition(5);

  for (unsigned i = 0; i < size; ++i) {
    int DegLat, DegLon;
    fixed tmp, MinLat, MinLon;
    char NoS, EoW;

    tmp = declaration.GetLocation(i).latitude.Degrees();
    if (negative(tmp)) {
      NoS = 'S';
      tmp = -tmp;
    } else {
      NoS = 'N';
    }
    DegLat = (int)tmp;
    MinLat = (tmp - fixed(DegLat)) * 60 * 1000;

    tmp = declaration.GetLocation(i).longitude.Degrees();
    if (negative(tmp)) {
      EoW = 'W';
      tmp = -tmp;
    } else {
      EoW = 'E';
    }
    DegLon = (int)tmp;
    MinLon = (tmp - fixed(DegLon)) * 60 * 1000;

    /*
     * We use the waypoint index here as name to get around the 192 byte
     * task size limit of the FLARM devices.
     *
     * see Flarm DataPort Manual:
     * "The total data size entered through this command may not surpass
     * 192 bytes when calculated as follows: 7+(Number of Waypoints * 9) +
     * (sum of length of all task and waypoint descriptions)"
     */
    NarrowString<90> buffer;
    buffer.Format("%02d%05.0f%c,%03d%05.0f%c,%d",
                  DegLat, (double)MinLat, NoS,
                  DegLon, (double)MinLon, EoW, i + 1);

    if (!SetConfig("ADDWP", buffer, env))
      return false;

    env.SetProgressPosition(6 + i);
  }

  if (!SetConfig("ADDWP", "0000000N,00000000E,L", env))
    return false;

  env.SetProgressPosition(6 + size);

  // PFLAC,S,KEY,VALUE
  // Expect
  // PFLAC,A,blah
  // PFLAC,,COPIL:
  // PFLAC,,COMPID:
  // PFLAC,,COMPCLASS:

  // PFLAC,,NEWTASK:
  // PFLAC,,ADDWP:

  // Reset the FLARM to activate the declaration
  Restart(env);

  return true;
}
Example #23
0
void
TopographyStore::Load(OperationEnvironment &operation, NLineReader &reader,
                      const TCHAR *directory, struct zzip_dir *zdir)
{
  Reset();

  // Create buffer for the shape filenames
  // (shape_filename will be modified with the shape_filename_end pointer)
  char shape_filename[MAX_PATH];
  if (directory != NULL) {
    const WideToACPConverter narrow_directory(directory);
    strcpy(shape_filename, narrow_directory);
    strcat(shape_filename, DIR_SEPARATOR_S);
  } else
    shape_filename[0] = 0;

  char *shape_filename_end = shape_filename + strlen(shape_filename);

  // Read file size to have a rough progress estimate for the progress bar
  long filesize = std::max(reader.size(), 1l);

  // Set progress bar to 100 steps
  operation.SetProgressRange(100);

  // Iterate through shape files in the "topology.tpl" file until
  // end or max. file number reached
  char *line;
  while (!files.full() && (line = reader.read()) != NULL) {
    // Line format: filename,range,icon,field,r,g,b,pen_width,label_range,important_range

    // Ignore comments (lines starting with *) and empty lines
    if (StringIsEmpty(line) || line[0] == '*')
      continue;

    // Find first comma to extract shape filename
    char *p = strchr(line, ',');
    if (p == NULL || p == line)
      // If no comma was found -> ignore this line/shapefile
      continue;

    if (HasLittleMemory()) {
      /* hard-coded blacklist for huge files on PPC2000; those
         devices usually have very little memory */

      // Null-terminate the line string after the first comma
      // for strcmp() calls in IsHugeTopographyFile() function
      *p = 0;

      // Skip large topography files
      if (IsHugeTopographyFile(line))
        continue;
    }

    // Extract filename and append it to the shape_filename buffer
    memcpy(shape_filename_end, line, p - line);
    // Append ".shp" file extension to the shape_filename buffer
    strcpy(shape_filename_end + (p - line), ".shp");

    // Parse shape range
    fixed shape_range = fixed(strtod(p + 1, &p)) * 1000;
    if (*p != _T(','))
      continue;

    // Parse shape icon id
    long shape_icon = strtol(p + 1, &p, 10);
    if (*p != _T(','))
      continue;

    // Parse shape field for text display
    long shape_field = strtol(p + 1, &p, 10) - 1;
    if (*p != _T(','))
      continue;

    // Parse red component of line / shading colour
    uint8_t red = (uint8_t)strtol(p + 1, &p, 10);
    if (*p != _T(','))
      continue;

    // Parse green component of line / shading colour
    uint8_t green = (uint8_t)strtol(p + 1, &p, 10);
    if (*p != _T(','))
      continue;

    // Parse blue component of line / shading colour
    uint8_t blue = (uint8_t)strtol(p + 1, &p, 10);

    // Parse pen width of lines
    int pen_width=1;
    if (*p == _T(',')) {
      pen_width = strtol(p + 1, &p, 10);
      if (pen_width<0)
        pen_width=1;
      else if (pen_width>31)
        pen_width=31;
    }

    // Parse range for displaying labels
    fixed label_range = shape_range;
    if (*p == _T(','))
      label_range = fixed(strtod(p + 1, &p)) * 1000;

    // Parse range for displaying labels with "important" rendering style
    fixed labelImportantRange = fixed_zero;
    if (*p == _T(','))
      labelImportantRange = fixed(strtod(p + 1, &p)) * 1000;

    // Create TopographyFile instance from parsed line
    TopographyFile *file = new TopographyFile(zdir, shape_filename,
                                              shape_range, label_range,
                                              labelImportantRange,
                                              Color(red, green, blue),
                                              shape_field, shape_icon,
                                              pen_width);
    if (file->IsEmpty())
      // If the shape file could not be read -> skip this line/file
      delete file;
    else
      // .. otherwise append it to our list of shape files
      files.append(file);

    // Update progress bar
    operation.SetProgressPosition((reader.tell() * 100) / filesize);
  }
}