Beispiel #1
0
bool
FlarmDevice::ReadFlightInfo(RecordedFlightInfo &flight,
                            OperationEnvironment &env)
{
  // Create header for getting record information
  FLARM::FrameHeader header = PrepareFrameHeader(FLARM::MT_GETRECORDINFO);

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

  // Wait for an answer and save the payload for further processing
  AllocatedArray<uint8_t> data;
  uint16_t length;
  uint8_t ack_result =
    WaitForACKOrNACK(header.GetSequenceNumber(), data, length, env, 1000);

  // If neither ACK nor NACK was received
  if (ack_result != FLARM::MT_ACK || length <= 2)
    return false;

  char *record_info = (char *)data.begin() + 2;
  return ParseRecordInfo(record_info, flight);
}
Beispiel #2
0
  size_t HandleBinary(const void *_data, size_t length) {
    const uint8_t *const data = (const uint8_t *)_data, *end = data + length;
    const uint8_t *p = data;

    p = std::find(p, end, FLARM::START_FRAME);
    if (p == NULL)
      return length;

    ++p;

    FLARM::FrameHeader header;
    size_t nbytes = Unescape(p, end, &header, sizeof(header));
    p += nbytes;
    if (nbytes < sizeof(header))
      return p - data;

    //XXX size_t payload_length = header.GetLength();

    switch (header.type) {
    case FLARM::MT_PING:
    case FLARM::MT_SELECTRECORD:
      SendACK(header.GetSequenceNumber());
      break;

    case FLARM::MT_EXIT:
      SendACK(header.GetSequenceNumber());
      binary = false;
      break;
    }

    return p - data;
  }
Beispiel #3
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;
}
Beispiel #4
0
FLARM::MessageType
FlarmDevice::WaitForACKOrNACK(uint16_t sequence_number,
                              AllocatedArray<uint8_t> &data, uint16_t &length,
                              OperationEnvironment &env, unsigned timeout_ms)
{
  const TimeoutClock timeout(timeout_ms);

  // Receive frames until timeout or expected frame found
  while (!timeout.HasExpired()) {
    // Wait until the next start byte comes around
    if (!WaitForStartByte(env, timeout.GetRemainingOrZero()))
      continue;

    // Read the following FrameHeader
    FLARM::FrameHeader header;
    if (!ReceiveFrameHeader(header, env, timeout.GetRemainingOrZero()))
      continue;

    // Read and check length of the FrameHeader
    length = header.GetLength();
    if (length <= sizeof(header))
      continue;

    // Calculate payload length
    length -= sizeof(header);

    // Read payload and check length
    data.GrowDiscard(length);
    if (!ReceiveEscaped(data.begin(), length,
                        env, timeout.GetRemainingOrZero()))
      continue;

    // Verify CRC
    if (header.GetCRC() != FLARM::CalculateCRC(header, data.begin(), length))
      continue;

    // Check message type
    if (header.type != FLARM::MT_ACK && header.type != FLARM::MT_NACK)
      continue;

    // Check payload length
    if (length < 2)
      continue;

    // Check whether the received ACK is for the right sequence number
    if (FromLE16(*((const uint16_t *)(const void *)data.begin())) ==
        sequence_number)
      return (FLARM::MessageType)header.type;
  }

  return FLARM::MT_ERROR;
}
Beispiel #5
0
bool
FlarmDevice::BinaryPing(OperationEnvironment &env, unsigned timeout_ms)
{
  const TimeoutClock timeout(timeout_ms);

  // Create header for sending a binary ping request
  FLARM::FrameHeader header = PrepareFrameHeader(FLARM::MT_PING);

  // Send request and wait for positive answer
  return SendStartByte() &&
    SendFrameHeader(header, env, timeout.GetRemainingOrZero()) &&
    WaitForACK(header.GetSequenceNumber(), env, timeout.GetRemainingOrZero());
}
Beispiel #6
0
FLARM::MessageType
FlarmDevice::SelectFlight(uint8_t record_number, OperationEnvironment &env)
{
  // Create header for selecting a log record
  uint8_t data[1] = { record_number };
  FLARM::FrameHeader header = PrepareFrameHeader(FLARM::MT_SELECTRECORD,
                                                 data, sizeof(data));

  // Send request
  if (!SendStartByte() ||
      !SendFrameHeader(header, env, 1000) ||
      !SendEscaped(data, sizeof(data), env, 1000))
    return FLARM::MT_ERROR;

  // Wait for an answer
  return WaitForACKOrNACK(header.GetSequenceNumber(), env, 1000);
}