Skip to content

Commit

Permalink
Merge pull request #1649 from dayjaby/log_files_improvements
Browse files Browse the repository at this point in the history
log_files: add blocking download_file; add erase log file function
  • Loading branch information
julianoes authored Apr 13, 2022
2 parents 93e1f05 + 16e605f commit 9b1034f
Show file tree
Hide file tree
Showing 13 changed files with 2,224 additions and 185 deletions.
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ add_subdirectory(ftp_server)
add_subdirectory(geofence_inclusion)
add_subdirectory(gimbal)
add_subdirectory(gimbal_device_tester)
add_subdirectory(logfile_download)
add_subdirectory(manual_control)
add_subdirectory(mavshell)
add_subdirectory(multiple_drones)
Expand Down
22 changes: 22 additions & 0 deletions examples/logfile_download/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
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
)

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;
auto result =
log_files.download_log_file(entry, std::string("log-") + entry.date + ".ulg");
if (result.first != LogFiles::Result::Success) {
download_failure = true;
std::cerr << "LogFiles::download_log_file failed: " << result.first << 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_all_log_files();
}
} 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

0 comments on commit 9b1034f

Please sign in to comment.