You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
209 lines
7.9 KiB
209 lines
7.9 KiB
2 months ago
|
// License: Apache 2.0. See LICENSE file in root directory.
|
||
|
// Copyright(c) 2015 Intel Corporation. All Rights Reserved.
|
||
|
|
||
|
#include <librealsense2/rs.hpp>
|
||
|
#include <librealsense2/hpp/rs_internal.hpp>
|
||
|
#include <rsutils/string/string-utilities.h>
|
||
|
#include <fstream>
|
||
|
#include <thread>
|
||
|
#include "tclap/CmdLine.h"
|
||
|
|
||
|
|
||
|
using namespace std;
|
||
|
using namespace TCLAP;
|
||
|
using namespace rs2;
|
||
|
|
||
|
|
||
|
string datetime_string()
|
||
|
{
|
||
|
auto t = time(nullptr);
|
||
|
char buffer[20] = {};
|
||
|
const tm* time = localtime(&t);
|
||
|
if (nullptr != time)
|
||
|
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time);
|
||
|
|
||
|
return string(buffer);
|
||
|
}
|
||
|
|
||
|
int main(int argc, char* argv[]) try
|
||
|
{
|
||
|
int default_polling_interval_ms = 100;
|
||
|
CmdLine cmd("librealsense rs-fw-logger example tool", ' ', RS2_API_FULL_VERSION_STR);
|
||
|
ValueArg<string> sn_arg("s", "sn", "camera serial number", false, "", "camera serial number");
|
||
|
ValueArg<string> xml_arg("l", "load", "Full file path of HW Logger Events XML file", false, "", "Load HW Logger Events XML file");
|
||
|
ValueArg<string> out_arg("o", "out", "Full file path of output file", false, "", "Print Fw logs to output file");
|
||
|
ValueArg<int> polling_interval_arg("p", "polling_interval", "Time Interval between each log messages polling (in milliseconds)", false, default_polling_interval_ms, "");
|
||
|
SwitchArg flash_logs_arg("f", "flash", "Flash Logs Request", false);
|
||
|
cmd.add(sn_arg);
|
||
|
cmd.add(xml_arg);
|
||
|
cmd.add(out_arg);
|
||
|
cmd.add(polling_interval_arg);
|
||
|
cmd.add(flash_logs_arg);
|
||
|
cmd.parse(argc, argv);
|
||
|
|
||
|
log_to_file(RS2_LOG_SEVERITY_WARN, "librealsense.log");
|
||
|
|
||
|
auto use_xml_file = false;
|
||
|
auto output_file_path = out_arg.getValue();
|
||
|
std::ofstream output_file(output_file_path);
|
||
|
// write to file if it is open, else write to console
|
||
|
std::ostream& out = (!output_file.is_open() ? std::cout : output_file);
|
||
|
|
||
|
auto sn = sn_arg.getValue();
|
||
|
auto xml_full_file_path = xml_arg.getValue();
|
||
|
auto polling_interval_ms = polling_interval_arg.getValue();
|
||
|
if (polling_interval_ms < 25 || polling_interval_ms > 300)
|
||
|
{
|
||
|
out << "Polling interval time provided: " << polling_interval_ms << "ms, is not in the valid range [25,300]. Default value " << default_polling_interval_ms << "ms is used." << std::endl;
|
||
|
polling_interval_ms = default_polling_interval_ms;
|
||
|
}
|
||
|
|
||
|
bool are_flash_logs_requested = flash_logs_arg.isSet();
|
||
|
|
||
|
context ctx;
|
||
|
device_hub hub(ctx);
|
||
|
|
||
|
bool should_loop_end = false;
|
||
|
|
||
|
while (!should_loop_end)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
rs2::device dev;
|
||
|
bool found = false;
|
||
|
|
||
|
while(!found)
|
||
|
{
|
||
|
auto devs = ctx.query_devices();
|
||
|
out << "\n" << devs.size() << " realSense devices detected.";
|
||
|
|
||
|
for (rs2::device d : devs)
|
||
|
{
|
||
|
string serial = d.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
|
||
|
|
||
|
if (sn.empty() || (!sn.empty() && serial.compare(sn) == 0))
|
||
|
{
|
||
|
dev = d;
|
||
|
found = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
out << "\nWaiting for RealSense device " << sn << (!sn.empty() ? " " : "") << "to connect ...";
|
||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||
|
}
|
||
|
|
||
|
string serial = dev.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
|
||
|
out << "\nRealSense device " << serial << " was connected for logging.\n";
|
||
|
|
||
|
setvbuf(stdout, NULL, _IONBF, 0); // unbuffering stdout
|
||
|
|
||
|
auto fw_log_device = dev.as<rs2::firmware_logger>();
|
||
|
|
||
|
bool using_parser = false;
|
||
|
if (!xml_full_file_path.empty())
|
||
|
{
|
||
|
ifstream f(xml_full_file_path);
|
||
|
if (f.good())
|
||
|
{
|
||
|
std::string xml_content((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
|
||
|
bool parser_initialized = fw_log_device.init_parser(xml_content);
|
||
|
if (parser_initialized)
|
||
|
using_parser = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool are_there_remaining_flash_logs_to_pull = true;
|
||
|
auto time_of_previous_polling_ms = std::chrono::high_resolution_clock::now();
|
||
|
|
||
|
while (hub.is_connected(dev))
|
||
|
{
|
||
|
if (are_flash_logs_requested && !are_there_remaining_flash_logs_to_pull)
|
||
|
{
|
||
|
should_loop_end = true;
|
||
|
break;
|
||
|
}
|
||
|
auto log_message = fw_log_device.create_message();
|
||
|
bool result = false;
|
||
|
if (are_flash_logs_requested)
|
||
|
{
|
||
|
result = fw_log_device.get_flash_log(log_message);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
result = fw_log_device.get_firmware_log(log_message);
|
||
|
}
|
||
|
if (result)
|
||
|
{
|
||
|
std::vector<string> fw_log_lines;
|
||
|
if (using_parser)
|
||
|
{
|
||
|
auto parsed_log = fw_log_device.create_parsed_message();
|
||
|
bool parsing_result = fw_log_device.parse_log(log_message, parsed_log);
|
||
|
|
||
|
stringstream sstr;
|
||
|
sstr << datetime_string() << " " << parsed_log.timestamp() << " " << parsed_log.sequence_id()
|
||
|
<< " " << parsed_log.severity() << " " << parsed_log.thread_name()
|
||
|
<< " " << parsed_log.file_name() << " " << parsed_log.line()
|
||
|
<< " " << parsed_log.message();
|
||
|
|
||
|
fw_log_lines.push_back(sstr.str());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
stringstream sstr;
|
||
|
sstr << datetime_string() << " FW_Log_Data:";
|
||
|
std::vector<uint8_t> msg_data = log_message.data();
|
||
|
for (int i = 0; i < msg_data.size(); ++i)
|
||
|
{
|
||
|
sstr << rsutils::string::hexify(msg_data[i]) << " ";
|
||
|
}
|
||
|
fw_log_lines.push_back(sstr.str());
|
||
|
}
|
||
|
for (auto& line : fw_log_lines)
|
||
|
out << line << endl;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (are_flash_logs_requested)
|
||
|
{
|
||
|
are_there_remaining_flash_logs_to_pull = false;
|
||
|
}
|
||
|
}
|
||
|
auto num_of_messages = fw_log_device.get_number_of_fw_logs();
|
||
|
if (num_of_messages == 0)
|
||
|
{
|
||
|
auto current_time = std::chrono::high_resolution_clock::now();
|
||
|
auto time_since_previous_polling_ms = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - time_of_previous_polling_ms).count();
|
||
|
if (time_since_previous_polling_ms < polling_interval_ms)
|
||
|
{
|
||
|
std::this_thread::sleep_for(chrono::milliseconds(polling_interval_ms - time_since_previous_polling_ms));
|
||
|
}
|
||
|
time_of_previous_polling_ms = std::chrono::high_resolution_clock::now();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
catch (const error & e)
|
||
|
{
|
||
|
cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n " << e.what() << endl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
catch( const rs2::error & e )
|
||
|
{
|
||
|
cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n " << e.what() << endl;
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
catch( const exception & e )
|
||
|
{
|
||
|
cerr << e.what() << endl;
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
catch( ... )
|
||
|
{
|
||
|
cerr << "some error" << endl;
|
||
|
return EXIT_FAILURE;
|
||
|
}
|