Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

log_files: add blocking download_file; add erase log file function #1649

Merged
merged 7 commits into from
Apr 13, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions examples/logfile_download/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.10.2)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

project(logfile_download)

add_executable(logfile_download
logfile_download.cpp
)

find_package(MAVSDK REQUIRED)

target_link_libraries(logfile_download
MAVSDK::mavsdk_log_files
MAVSDK::mavsdk
)

if(NOT MSVC)
add_compile_options(logfile_download PRIVATE -Wall -Wextra)
else()
add_compile_options(logfile_download PRIVATE -WX -W2)
endif()
122 changes: 122 additions & 0 deletions examples/logfile_download/logfile_download.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
//
// Example how to download logfiles with MAVSDK.
//

#include <mavsdk/mavsdk.h>
#include <mavsdk/plugins/log_files/log_files.h>

#include <chrono>
#include <functional>
#include <future>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <thread>

using namespace mavsdk;
using std::chrono::seconds;
using std::this_thread::sleep_for;

void usage(const std::string& bin_name)
{
std::cerr << "Usage : " << bin_name << " <connection_url> [--rm]\n"
<< '\n'
<< "Connection URL format should be :\n"
<< " For TCP : tcp://[server_host][:server_port]\n"
<< " For UDP : udp://[bind_host][:bind_port]\n"
<< " For Serial : serial:///path/to/serial/dev[:baudrate]\n"
<< "For example, to connect to the simulator use URL: udp://:14540\n"
<< '\n'
<< "To remove log files after all downloads completed,\n"
<< "please add the --rm argument" << std::endl;
}

std::shared_ptr<System> get_system(Mavsdk& mavsdk)
{
std::cerr << "Waiting to discover system...\n";
auto prom = std::promise<std::shared_ptr<System>>{};
auto fut = prom.get_future();

// We wait for new systems to be discovered, once we find one that has an
// autopilot, we decide to use it.
mavsdk.subscribe_on_new_system([&mavsdk, &prom]() {
auto system = mavsdk.systems().back();

// Unsubscribe again as we only want to find one system.
mavsdk.subscribe_on_new_system(nullptr);
prom.set_value(system);
});

// We usually receive heartbeats at 1Hz, therefore we should find a
// system after around 3 seconds max, surely.
if (fut.wait_for(seconds(3)) == std::future_status::timeout) {
std::cerr << "No autopilot found.\n";
return {};
}

// Get discovered system now.
return fut.get();
}

int main(int argc, char** argv)
{
if (argc > 3) {
usage(argv[0]);
return 1;
}

/* parse arguments */
bool remove_log_files = false;

for (int i = 2; i < argc; ++i) {
if (argv[i] == "--rm") {
remove_log_files = true;
}
}

Mavsdk mavsdk;
ConnectionResult connection_result = mavsdk.add_any_connection(argv[1]);

if (connection_result != ConnectionResult::Success) {
std::cerr << "Connection failed: " << connection_result << std::endl;
return 1;
}

auto system = get_system(mavsdk);
if (!system) {
return 1;
}

// Instantiate plugins.

auto log_files = LogFiles{system};

auto get_entries_result = log_files.get_entries();
if (get_entries_result.first == LogFiles::Result::Success) {
bool download_failure = false;
for (auto entry : get_entries_result.second) {
std::cerr << "Got log file with ID " << entry.id << " and date " << entry.date
<< std::endl;
LogFiles::Result result =
log_files.download_log_file(entry, std::string("log-") + entry.date + ".ulg");
if (result != LogFiles::Result::Success) {
download_failure = true;
std::cerr << "LogFiles::download_log_file failed: " << result << std::endl;
}
}
if (!download_failure && remove_log_files) {
/*
* If you want to be sure the log has been deleted, call get_entries again
* that there are no log files present anymore
*
* TODO: provide a more reliable solution
*/
log_files.erase_log_files();
JonasVautherin marked this conversation as resolved.
Show resolved Hide resolved
}
} else {
std::cerr << "LogFiles::get_entries failed: " << get_entries_result.first << std::endl;
return 1;
}

return 0;
}
2 changes: 1 addition & 1 deletion proto
19 changes: 19 additions & 0 deletions src/mavsdk/plugins/log_files/include/plugins/log_files/log_files.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,25 @@ class LogFiles : public PluginBase {
*/
void download_log_file_async(Entry entry, std::string path, DownloadLogFileCallback callback);

/**
* @brief Download log file synchronously.
*
* This function is blocking.
*
* @return Result of request.
*/
std::pair<Result, LogFiles::ProgressData>
download_log_file(Entry entry, std::string path) const;

/**
* @brief Erase all log files.
*
* This function is blocking.
*
* @return Result of request.
*/
Result erase_all_log_files() const;

/**
* @brief Copy constructor.
*/
Expand Down
11 changes: 11 additions & 0 deletions src/mavsdk/plugins/log_files/log_files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ void LogFiles::download_log_file_async(
_impl->download_log_file_async(entry, path, callback);
}

std::pair<LogFiles::Result, LogFiles::ProgressData>
LogFiles::download_log_file(Entry entry, std::string path) const
{
return _impl->download_log_file(entry, path);
}

LogFiles::Result LogFiles::erase_all_log_files() const
{
return _impl->erase_all_log_files();
}

bool operator==(const LogFiles::ProgressData& lhs, const LogFiles::ProgressData& rhs)
{
return ((std::isnan(rhs.progress) && std::isnan(lhs.progress)) || rhs.progress == lhs.progress);
Expand Down
33 changes: 33 additions & 0 deletions src/mavsdk/plugins/log_files/log_files_impl.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "log_files_impl.h"
#include "mavsdk_impl.h"
#include "filesystem_include.h"
#include "unused.h"

#include <algorithm>
#include <cmath>
Expand Down Expand Up @@ -202,6 +203,23 @@ void LogFilesImpl::list_timeout()
}
}

std::pair<LogFiles::Result, LogFiles::ProgressData>
LogFilesImpl::download_log_file(LogFiles::Entry entry, const std::string& file_path)
{
auto prom =
std::make_shared<std::promise<std::pair<LogFiles::Result, LogFiles::ProgressData>>>();
auto future_result = prom->get_future();

download_log_file_async(
entry, file_path, [prom](LogFiles::Result result, LogFiles::ProgressData progress) {
UNUSED(progress);
if (result != LogFiles::Result::Next) {
prom->set_value(std::make_pair(result, progress));
}
});
return future_result.get();
}

void LogFilesImpl::download_log_file_async(
LogFiles::Entry entry, const std::string& file_path, LogFiles::DownloadLogFileCallback callback)
{
Expand Down Expand Up @@ -295,6 +313,21 @@ void LogFilesImpl::download_log_file_async(
}
}

LogFiles::Result LogFilesImpl::erase_all_log_files()
{
mavlink_message_t msg;
mavlink_msg_log_erase_pack(
_parent->get_own_system_id(),
_parent->get_own_component_id(),
&msg,
_parent->get_system_id(),
MAV_COMP_ID_AUTOPILOT1);
_parent->send_message(msg);

// TODO: find a good way to know about the success or failure of the operation
return LogFiles::Result::Success;
}

std::size_t LogFilesImpl::determine_part_end()
{
// Assumes to have the lock for _data.mutex.
Expand Down
4 changes: 4 additions & 0 deletions src/mavsdk/plugins/log_files/log_files_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ class LogFilesImpl : public PluginImplBase {
std::pair<LogFiles::Result, std::vector<LogFiles::Entry>> get_entries();
void get_entries_async(LogFiles::GetEntriesCallback callback);

std::pair<LogFiles::Result, LogFiles::ProgressData>
download_log_file(LogFiles::Entry entry, const std::string& file_path);
void download_log_file_async(
LogFiles::Entry entry,
const std::string& file_path,
LogFiles::DownloadLogFileCallback callback);

LogFiles::Result erase_all_log_files();

private:
void request_end();

Expand Down
84 changes: 84 additions & 0 deletions src/mavsdk_server/src/generated/log_files/log_files.grpc.pb.cc

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading