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; }
bool DeviceDescriptor::ReadFlightList(RecordedFlightList &flight_list, OperationEnvironment &env) { assert(borrowed); assert(port != nullptr); assert(driver != nullptr); assert(device != nullptr); StaticString<60> text; if (driver->HasPassThrough() && second_device != nullptr) { text.Format(_T("%s: %s."), _("Reading flight list"), second_driver->display_name); env.SetText(text); device->EnablePassThrough(env); return second_device->ReadFlightList(flight_list, env); } else { text.Format(_T("%s: %s."), _("Reading flight list"), driver->display_name); env.SetText(text); return device->ReadFlightList(flight_list, env); } }
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; }
bool DeviceDescriptor::DownloadFlight(const RecordedFlightInfo &flight, Path path, OperationEnvironment &env) { assert(borrowed); assert(port != nullptr); assert(driver != nullptr); assert(device != nullptr); if (port == nullptr || driver == nullptr || device == nullptr) return false; StaticString<60> text; if (driver->HasPassThrough() && (second_device != nullptr)) { text.Format(_T("%s: %s."), _("Downloading flight log"), second_driver->display_name); env.SetText(text); device->EnablePassThrough(env); return second_device->DownloadFlight(flight, path, env); } else { text.Format(_T("%s: %s."), _("Downloading flight log"), driver->display_name); env.SetText(text); return device->DownloadFlight(flight, path, env); } }
/** * 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); }
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); }
bool DeviceDescriptor::Declare(const struct Declaration &declaration, const Waypoint *home, OperationEnvironment &env) { if (port == NULL) return false; SetBusy(true); StaticString<60> text; text.Format(_T("%s: %s."), _("Sending declaration"), driver->display_name); env.SetText(text); port->StopRxThread(); bool result = device != NULL && device->Declare(declaration, home, env); if (device_blackboard->IsFLARM(index) && !IsDriver(_T("FLARM"))) { text.Format(_T("%s: FLARM."), _("Sending declaration")); env.SetText(text); FlarmDevice flarm(*port); result = flarm.Declare(declaration, home, env) || result; } port->StartRxThread(); SetBusy(false); return result; }
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); } }
bool Port::WaitConnected(OperationEnvironment &env) { while (GetState() == PortState::LIMBO && !env.IsCancelled()) env.Sleep(200); return GetState() == PortState::READY; }
void LX::CommandModeQuick(Port &port, OperationEnvironment &env) { SendSYN(port); env.Sleep(std::chrono::milliseconds(500)); SendSYN(port); env.Sleep(std::chrono::milliseconds(500)); SendSYN(port); env.Sleep(std::chrono::milliseconds(500)); }
void LX::CommandModeQuick(Port &port, OperationEnvironment &env) { port.Write(SYN); env.Sleep(500); port.Write(SYN); env.Sleep(500); port.Write(SYN); env.Sleep(500); }
void LX::CommandModeQuick(Port &port, OperationEnvironment &env) { SendSYN(port); env.Sleep(500); SendSYN(port); env.Sleep(500); SendSYN(port); env.Sleep(500); }
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; }
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 DeviceDescriptor::DoOpen(OperationEnvironment &env) { assert(config.IsAvailable()); if (config.port_type == DeviceConfig::PortType::INTERNAL) return OpenInternalSensors(); if (config.port_type == DeviceConfig::PortType::DROIDSOAR_V2) return OpenDroidSoarV2(); if (config.port_type == DeviceConfig::PortType::I2CPRESSURESENSOR) return OpenI2Cbaro(); if (config.port_type == DeviceConfig::PortType::NUNCHUCK) return OpenNunchuck(); if (config.port_type == DeviceConfig::PortType::IOIOVOLTAGE) return OpenVoltage(); if (config.port_type == DeviceConfig::PortType::ADCAIRSPEED) return OpenAdcAirspeed(); reopen_clock.Update(); Port *port = OpenPort(config, *this); if (port == NULL) { TCHAR name_buffer[64]; const TCHAR *name = config.GetPortName(name_buffer, 64); StaticString<256> msg; msg.Format(_T("%s: %s."), _("Unable to open port"), name); env.SetErrorMessage(msg); return false; } while (port->GetState() == PortState::LIMBO) { env.Sleep(200); if (env.IsCancelled() || port->GetState() == PortState::FAILED) { delete port; return false; } } if (!Open(*port, env)) { delete port; return false; } return true; }
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; }
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; }
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); } }
bool WaypointGlue::LoadWaypoints(Waypoints &way_points, const RasterTerrain *terrain, OperationEnvironment &operation) { LogStartUp(_T("ReadWaypoints")); operation.SetText(_("Loading Waypoints...")); bool found = false; // Delete old waypoints way_points.Clear(); // ### FIRST FILE ### found |= LoadWaypointFile(1, way_points, terrain, operation); // ### SECOND FILE ### found |= LoadWaypointFile(2, way_points, terrain, operation); // ### WATCHED WAYPOINT/THIRD FILE ### found |= LoadWaypointFile(3, way_points, terrain, operation); // ### MAP/FOURTH FILE ### // If no waypoint file found yet if (!found) found = LoadMapFileWaypoints(0, szProfileMapFile, way_points, terrain, operation); // Optimise the waypoint list after attaching new waypoints way_points.Optimise(); // Return whether waypoints have been loaded into the waypoint list return found; }
bool FlarmDevice::DownloadFlight(const RecordedFlightInfo &flight, Path path, OperationEnvironment &env) { if (!BinaryMode(env)) return false; FLARM::MessageType ack_result = SelectFlight(flight.internal.flarm, env); // If no ACK was received -> cancel if (ack_result != FLARM::MT_ACK || env.IsCancelled()) return false; try { if (DownloadFlight(path, env)) return true; } catch (...) { mode = Mode::UNKNOWN; throw; } mode = Mode::UNKNOWN; return false; }
bool VolksloggerDevice::Declare(const Declaration &declaration, const Waypoint *home, OperationEnvironment &env) { if (declaration.Size() < 2) return false; env.SetText(_T("Comms with Volkslogger")); port.SetRxTimeout(500); // change to IO mode baud rate unsigned lLastBaudrate = port.SetBaudrate(9600L); VLAPI vl(port, env); bool success = DeclareInner(vl, declaration, home); vl.close(1); port.SetBaudrate(lLastBaudrate); // restore baudrate return success; }
/** * Opens the airfield details file and parses it */ void WaypointDetails::ReadFile(TLineReader &reader, Waypoints &way_points, OperationEnvironment &operation) { operation.SetText(_("Loading Airfield Details File...")); ParseAirfieldDetails(way_points, reader, operation); }
bool FlarmDevice::ReadFlightList(RecordedFlightList &flight_list, OperationEnvironment &env) { if (!BinaryMode(env)) return false; // Try to receive flight information until the list is full for (uint8_t i = 0; !flight_list.full(); ++i) { FLARM::MessageType ack_result = SelectFlight(i, env); // Last record reached -> bail out and return list if (ack_result == FLARM::MT_NACK) break; // If neither ACK nor NACK was received if (ack_result != FLARM::MT_ACK || env.IsCancelled()) { mode = Mode::UNKNOWN; return false; } RecordedFlightInfo flight_info; flight_info.internal.flarm = i; if (ReadFlightInfo(flight_info, env)) flight_list.append(flight_info); } return true; }
bool WaypointGlue::LoadWaypoints(Waypoints &way_points, const RasterTerrain *terrain, OperationEnvironment &operation) { LogFormat("ReadWaypoints"); operation.SetText(_("Loading Waypoints...")); bool found = false; // Delete old waypoints way_points.Clear(); TCHAR path[MAX_PATH]; LoadWaypointFile(way_points, LocalPath(path, _T("user.cup")), WaypointFileType::SEEYOU, WaypointOrigin::USER, terrain, operation); // ### FIRST FILE ### if (Profile::GetPath(ProfileKeys::WaypointFile, path)) found |= LoadWaypointFile(way_points, path, WaypointOrigin::PRIMARY, terrain, operation); // ### SECOND FILE ### if (Profile::GetPath(ProfileKeys::AdditionalWaypointFile, path)) found |= LoadWaypointFile(way_points, path, WaypointOrigin::ADDITIONAL, terrain, operation); // ### WATCHED WAYPOINT/THIRD FILE ### if (Profile::GetPath(ProfileKeys::WatchedWaypointFile, path)) found |= LoadWaypointFile(way_points, path, WaypointOrigin::WATCHED, terrain, operation); // ### MAP/FOURTH FILE ### // If no waypoint file found yet if (!found) { auto dir = OpenMapFile(); if (dir != nullptr) { found |= LoadWaypointFile(way_points, dir, "waypoints.xcw", WaypointFileType::WINPILOT, WaypointOrigin::MAP, terrain, operation); found |= LoadWaypointFile(way_points, dir, "waypoints.cup", WaypointFileType::SEEYOU, WaypointOrigin::MAP, terrain, operation); zzip_dir_close(dir); } } // Optimise the waypoint list after attaching new waypoints way_points.Optimise(); // Return whether waypoints have been loaded into the waypoint list return found; }
int Volkslogger::SendCommandReadBulk(Port &port, unsigned baud_rate, OperationEnvironment &env, Command cmd, uint8_t param1, void *buffer, size_t max_length, const unsigned timeout_firstchar_ms) { unsigned old_baud_rate = port.GetBaudrate(); if (old_baud_rate != 0) { if (!SendCommandSwitchBaudRate(port, env, cmd, param1, baud_rate)) return -1; /* after switching baud rates, this sleep time is necessary; it has been verified experimentally */ env.Sleep(300); } else { /* port does not support baud rate switching, use plain SendCommand() without new baud rate */ if (!SendCommand(port, env, cmd, param1)) return -1; } int nbytes = ReadBulk(port, env, buffer, max_length, timeout_firstchar_ms); if (old_baud_rate != 0) port.SetBaudrate(old_baud_rate); return nbytes; }
bool Port::ExpectString(const char *token, OperationEnvironment &env, unsigned timeout_ms) { assert(token != NULL); const char *const token_end = token + strlen(token); const TimeoutClock timeout(timeout_ms); char buffer[256]; const char *p = token; while (true) { WaitResult wait_result = WaitRead(env, timeout.GetRemainingOrZero()); if (wait_result != WaitResult::READY) // Operation canceled, Timeout expired or I/O error occurred return false; int nbytes = Read(buffer, std::min(sizeof(buffer), size_t(token_end - p))); if (nbytes < 0 || env.IsCancelled()) return false; for (const char *q = buffer, *end = buffer + nbytes; q != end; ++q) { const char ch = *q; if (ch != *p) /* retry */ p = token; else if (++p == token_end) return true; } } }
bool Volkslogger::SendCommand(Port &port, OperationEnvironment &env, Command cmd, uint8_t param1, uint8_t param2) { static constexpr unsigned delay = 2; /* flush buffers */ if (!port.FullFlush(env, 20, 100)) return false; /* reset command interpreter */ if (!Reset(port, env, 6)) return false; /* send command packet */ const uint8_t cmdarray[8] = { (uint8_t)cmd, param1, param2, 0, 0, 0, 0, 0, }; if (!port.Write(ENQ)) return false; env.Sleep(delay); if (!SendWithCRC(port, cmdarray, sizeof(cmdarray), env)) return false; /* wait for confirmation */ return port.WaitRead(env, 4000) == Port::WaitResult::READY && port.GetChar() == 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); }
bool DeviceDescriptor::DoOpen(OperationEnvironment &env) { assert(config.IsAvailable()); if (config.port_type == DeviceConfig::PortType::INTERNAL) return OpenInternalSensors(); if (config.port_type == DeviceConfig::PortType::DROIDSOAR_V2) return OpenDroidSoarV2(); if (config.port_type == DeviceConfig::PortType::I2CPRESSURESENSOR) return OpenI2Cbaro(); if (config.port_type == DeviceConfig::PortType::NUNCHUCK) return OpenNunchuck(); if (config.port_type == DeviceConfig::PortType::IOIOVOLTAGE) return OpenVoltage(); reopen_clock.Update(); Port *port = OpenPort(config, port_listener, *this); if (port == nullptr) { TCHAR name_buffer[64]; const TCHAR *name = config.GetPortName(name_buffer, 64); StaticString<256> msg; msg.Format(_T("%s: %s."), _("Unable to open port"), name); env.SetErrorMessage(msg); return false; } DumpPort *dump_port = new DumpPort(port); dump_port->Disable(); if (!port->WaitConnected(env) || !OpenOnPort(dump_port, env)) { if (!env.IsCancelled()) ++n_failures; delete dump_port; return false; } ResetFailureCounter(); return true; }
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); } }