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; }
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); }
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; }
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()); }
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); }