mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2024-12-13 03:34:35 +00:00
Logging Updates (#978)
* log_file ensures directory exists * Fix audio timestamp path * Fix auto inc, add subfolder for recordings * Fix auto inc and support subfolder
This commit is contained in:
parent
8b395239d2
commit
a8cdde7bea
@ -98,10 +98,9 @@ ACARSAppView::ACARSAppView(NavigationView& nav) {
|
||||
logging = v;
|
||||
};
|
||||
|
||||
make_new_directory(LOG_ROOT_DIR);
|
||||
logger = std::make_unique<ACARSLogger>();
|
||||
if (logger)
|
||||
logger->append( LOG_ROOT_DIR "/ACARS.TXT" );
|
||||
logger->append(LOG_ROOT_DIR "/ACARS.TXT");
|
||||
}
|
||||
|
||||
ACARSAppView::~ACARSAppView() {
|
||||
|
@ -397,7 +397,6 @@ AISAppView::AISAppView(NavigationView& nav) : nav_ { nav } {
|
||||
this->on_show_list();
|
||||
};
|
||||
|
||||
make_new_directory(LOG_ROOT_DIR);
|
||||
logger = std::make_unique<AISLogger>();
|
||||
if( logger ) {
|
||||
logger->append( LOG_ROOT_DIR "/AIS.TXT" );
|
||||
|
@ -232,7 +232,7 @@ private:
|
||||
|
||||
RecordView record_view {
|
||||
{ 0 * 8, 2 * 16, 30 * 8, 1 * 16 },
|
||||
u"AUD",
|
||||
u"AUD", u"AUDIO",
|
||||
RecordView::FileType::WAV,
|
||||
4096,
|
||||
4
|
||||
|
@ -108,7 +108,7 @@ private:
|
||||
|
||||
RecordView record_view {
|
||||
{ 0 * 8, 2 * 16, 30 * 8, 1 * 16 },
|
||||
u"BBD_????", RecordView::FileType::RawS16, 16384, 3
|
||||
u"BBD_????.*", u"CAPTURES", RecordView::FileType::RawS16, 16384, 3
|
||||
};
|
||||
|
||||
spectrum::WaterfallWidget waterfall { };
|
||||
|
@ -130,7 +130,6 @@ ERTAppView::ERTAppView(NavigationView&) {
|
||||
static_cast<int8_t>(receiver_model.vga()),
|
||||
}); */
|
||||
|
||||
make_new_directory(LOG_ROOT_DIR);
|
||||
logger = std::make_unique<ERTLogger>();
|
||||
if( logger ) {
|
||||
logger->append( LOG_ROOT_DIR "/ERT.TXT" );
|
||||
|
@ -129,10 +129,9 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav) {
|
||||
ignore_address /= 10;
|
||||
}
|
||||
|
||||
make_new_directory(LOG_ROOT_DIR);
|
||||
logger = std::make_unique<POCSAGLogger>();
|
||||
if (logger)
|
||||
logger->append( LOG_ROOT_DIR "/POCSAG.TXT" );
|
||||
logger->append(LOG_ROOT_DIR "/POCSAG.TXT");
|
||||
|
||||
audio::output::start();
|
||||
audio::output::unmute();
|
||||
|
@ -194,7 +194,6 @@ TPMSAppView::TPMSAppView(NavigationView&) {
|
||||
|
||||
options_temperature.set_selected_index(0, true);
|
||||
|
||||
make_new_directory(LOG_ROOT_DIR);
|
||||
logger = std::make_unique<TPMSLogger>();
|
||||
if( logger ) {
|
||||
logger->append( LOG_ROOT_DIR "/TPMS.TXT" );
|
||||
|
@ -117,8 +117,6 @@ ADSBRxAircraftDetailsView::ADSBRxAircraftDetailsView(
|
||||
|
||||
std::unique_ptr<ADSBLogger> logger { };
|
||||
|
||||
make_new_directory(LOG_ROOT_DIR);
|
||||
|
||||
icao_code = to_string_hex(entry_copy.ICAO_address, 6);
|
||||
text_icao_address.set(to_string_hex(entry_copy.ICAO_address, 6));
|
||||
|
||||
|
@ -107,10 +107,9 @@ AFSKRxView::AFSKRxView(NavigationView& nav) {
|
||||
nav.push<ModemSetupView>();
|
||||
};
|
||||
|
||||
make_new_directory(LOG_ROOT_DIR);
|
||||
logger = std::make_unique<AFSKLogger>();
|
||||
if (logger)
|
||||
logger->append( LOG_ROOT_DIR "/AFSK.TXT" );
|
||||
logger->append(LOG_ROOT_DIR "/AFSK.TXT");
|
||||
|
||||
// Auto-configure modem for LCR RX (will be removed later)
|
||||
baseband::set_afsk(persistent_memory::modem_baudrate(), 8, 0, false);
|
||||
|
@ -141,10 +141,9 @@ APRSRxView::APRSRxView(NavigationView& nav, Rect parent_rect) : View(parent_rect
|
||||
|
||||
options_region.set_selected_index(0, true);
|
||||
|
||||
make_new_directory(LOG_ROOT_DIR);
|
||||
logger = std::make_unique<APRSLogger>();
|
||||
if (logger)
|
||||
logger->append( LOG_ROOT_DIR "/APRS.TXT" );
|
||||
logger->append(LOG_ROOT_DIR "/APRS.TXT");
|
||||
|
||||
baseband::set_aprs(1200);
|
||||
|
||||
|
@ -235,7 +235,7 @@ private:
|
||||
// DEBUG
|
||||
RecordView record_view {
|
||||
{ 0 * 8, 1 * 16, 30 * 8, 1 * 16 },
|
||||
u"AFS_????", RecordView::FileType::WAV, 4096, 4
|
||||
u"AFS_????.WAV", u"APRS", RecordView::FileType::WAV, 4096, 4
|
||||
};
|
||||
|
||||
Console console {
|
||||
|
@ -42,8 +42,7 @@ bool is_hidden_file(const fs::path& path) {
|
||||
|
||||
// Gets a truncated name from a path for display.
|
||||
std::string truncate(const fs::path& path, size_t max_length) {
|
||||
auto name = path.string();
|
||||
return name.length() <= max_length ? name : name.substr(0, max_length);
|
||||
return ::truncate(path.string(), max_length);
|
||||
}
|
||||
|
||||
// Gets a human readable file size string.
|
||||
|
@ -133,7 +133,6 @@ SondeView::SondeView(NavigationView& nav) {
|
||||
999); //set a dummy heading out of range to draw a cross...probably not ideal?
|
||||
};
|
||||
|
||||
make_new_directory(LOG_ROOT_DIR);
|
||||
logger = std::make_unique<SondeLogger>();
|
||||
if (logger)
|
||||
logger->append( LOG_ROOT_DIR "/SONDE.TXT" );
|
||||
|
@ -79,7 +79,6 @@ TestView::TestView(NavigationView& nav) {
|
||||
cal_value = raw_alt - 0x80;
|
||||
};
|
||||
|
||||
|
||||
logger = std::make_unique<TestLogger>();
|
||||
if (logger)
|
||||
logger->append("saucepan.txt");
|
||||
|
@ -124,50 +124,85 @@ Optional<File::Error> File::sync() {
|
||||
}
|
||||
}
|
||||
|
||||
static std::filesystem::path find_last_file_matching_pattern(const std::filesystem::path& pattern) {
|
||||
std::filesystem::path last_match;
|
||||
for(const auto& entry : std::filesystem::directory_iterator(u"", pattern)) {
|
||||
if( std::filesystem::is_regular_file(entry.status()) ) {
|
||||
/* Range used for filename matching.
|
||||
* Start and end are inclusive positions of "???" */
|
||||
struct pattern_range {
|
||||
size_t start;
|
||||
size_t end;
|
||||
};
|
||||
|
||||
/* Finds the last file matching the specified pattern that
|
||||
* can be automatically incremented (digits in pattern).
|
||||
* NB: assumes a patten with contiguous '?' like "FOO_???.txt". */
|
||||
static std::filesystem::path find_last_ordinal_match(
|
||||
const std::filesystem::path& folder,
|
||||
const std::filesystem::path& pattern,
|
||||
pattern_range range
|
||||
) {
|
||||
auto last_match = std::filesystem::path();
|
||||
auto can_increment = [range](const auto& path) {
|
||||
for (auto i = range.start; i <= range.end; ++i)
|
||||
if (!isdigit(path.native()[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
for (const auto& entry : std::filesystem::directory_iterator(folder, pattern)) {
|
||||
if (std::filesystem::is_regular_file(entry.status()) && can_increment(entry.path())) {
|
||||
const auto& match = entry.path();
|
||||
if( match > last_match ) {
|
||||
last_match = match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return last_match;
|
||||
}
|
||||
|
||||
static std::filesystem::path increment_filename_stem_ordinal(std::filesystem::path path) {
|
||||
auto t = path.replace_extension().native();
|
||||
auto it = t.rbegin();
|
||||
/* Given a file path like "FOO_0001.txt" increment it to "FOO_0002.txt". */
|
||||
static std::filesystem::path increment_filename_ordinal(
|
||||
const std::filesystem::path& path, pattern_range range
|
||||
) {
|
||||
auto name = path.filename().native();
|
||||
|
||||
// Increment decimal number before the extension.
|
||||
for(; it != t.rend(); ++it) {
|
||||
const auto c = *it;
|
||||
if( c < '0' ) {
|
||||
for (auto i = range.end; i >= range.start; --i) {
|
||||
auto& c = name[i];
|
||||
|
||||
// Not a digit or would overflow the counter.
|
||||
if (c < u'0' || c > u'9' || (c == u'9' && i == range.start))
|
||||
return { };
|
||||
} else if( c < '9' ) {
|
||||
*it += 1;
|
||||
|
||||
if (c == u'9')
|
||||
c = '0';
|
||||
else {
|
||||
c++;
|
||||
break;
|
||||
} else if( c == '9' ) {
|
||||
*it = '0';
|
||||
} else {
|
||||
return { };
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
return { name };
|
||||
}
|
||||
|
||||
std::filesystem::path next_filename_stem_matching_pattern(std::filesystem::path filename_pattern) {
|
||||
const auto next_filename = find_last_file_matching_pattern(filename_pattern.replace_extension(u".*"));
|
||||
if( next_filename.empty() ) {
|
||||
auto pattern_s = filename_pattern.replace_extension().native();
|
||||
std::replace(std::begin(pattern_s), std::end(pattern_s), '?', '0');
|
||||
return pattern_s;
|
||||
} else {
|
||||
return increment_filename_stem_ordinal(next_filename);
|
||||
std::filesystem::path next_filename_matching_pattern(const std::filesystem::path& filename_pattern) {
|
||||
auto path = filename_pattern.parent_path();
|
||||
auto pattern = filename_pattern.filename();
|
||||
auto range = pattern_range {
|
||||
pattern.native().find_first_of(u'?'),
|
||||
pattern.native().find_last_of(u'?')
|
||||
};
|
||||
|
||||
const auto match = find_last_ordinal_match(path, pattern, range);
|
||||
|
||||
if (match.empty()) {
|
||||
auto pattern_str = pattern.native();
|
||||
for (auto i = range.start; i <= range.end; ++i)
|
||||
pattern_str[i] = u'0';
|
||||
return path / pattern_str;
|
||||
}
|
||||
|
||||
auto next_name = increment_filename_ordinal(match, range);
|
||||
return next_name.empty() ? next_name : path / next_name;
|
||||
}
|
||||
|
||||
std::vector<std::filesystem::path> scan_root_files(const std::filesystem::path& directory,
|
||||
@ -214,7 +249,7 @@ std::filesystem::filesystem_error copy_file(
|
||||
) {
|
||||
File src;
|
||||
File dst;
|
||||
constexpr size_t buffer_size = 512;
|
||||
constexpr size_t buffer_size = 128;
|
||||
uint8_t buffer[buffer_size];
|
||||
|
||||
auto error = src.open(file_path);
|
||||
@ -261,6 +296,19 @@ std::filesystem::filesystem_error make_new_directory(
|
||||
return { f_mkdir(reinterpret_cast<const TCHAR*>(dir_path.c_str())) };
|
||||
}
|
||||
|
||||
std::filesystem::filesystem_error ensure_directory(
|
||||
const std::filesystem::path& dir_path
|
||||
) {
|
||||
if (dir_path.empty() || std::filesystem::file_exists(dir_path))
|
||||
return { };
|
||||
|
||||
auto result = ensure_directory(dir_path.parent_path());
|
||||
if (result.code())
|
||||
return result;
|
||||
|
||||
return make_new_directory(dir_path);
|
||||
}
|
||||
|
||||
namespace std {
|
||||
namespace filesystem {
|
||||
|
||||
@ -383,8 +431,10 @@ directory_iterator::directory_iterator(
|
||||
) : pattern { wild }
|
||||
{
|
||||
impl = std::make_shared<Impl>();
|
||||
const auto result = f_findfirst(&impl->dir, &impl->filinfo, reinterpret_cast<const TCHAR*>(path.c_str()), reinterpret_cast<const TCHAR*>(pattern.c_str()));
|
||||
if( result != FR_OK || impl->filinfo.fname[0] == (TCHAR)'\0') {
|
||||
const auto result = f_findfirst(&impl->dir, &impl->filinfo,
|
||||
reinterpret_cast<const TCHAR*>(path.c_str()),
|
||||
reinterpret_cast<const TCHAR*>(pattern.c_str()));
|
||||
if (result != FR_OK || impl->filinfo.fname[0] == (TCHAR)'\0') {
|
||||
impl.reset();
|
||||
// TODO: Throw exception if/when I enable exceptions...
|
||||
}
|
||||
|
@ -59,6 +59,10 @@ struct filesystem_error {
|
||||
|
||||
std::string what() const;
|
||||
|
||||
bool ok() const {
|
||||
return err == FR_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t err { FR_OK };
|
||||
};
|
||||
@ -258,12 +262,17 @@ std::filesystem::filesystem_error copy_file(const std::filesystem::path& file_pa
|
||||
FATTimestamp file_created_date(const std::filesystem::path& file_path);
|
||||
std::filesystem::filesystem_error make_new_file(const std::filesystem::path& file_path);
|
||||
std::filesystem::filesystem_error make_new_directory(const std::filesystem::path& dir_path);
|
||||
std::filesystem::filesystem_error ensure_directory(const std::filesystem::path& dir_path);
|
||||
|
||||
std::vector<std::filesystem::path> scan_root_files(const std::filesystem::path& directory, const std::filesystem::path& extension);
|
||||
std::vector<std::filesystem::path> scan_root_directories(const std::filesystem::path& directory);
|
||||
|
||||
/* Gets an auto incrementing filename. */
|
||||
std::filesystem::path next_filename_stem_matching_pattern(std::filesystem::path filename_stem_pattern);
|
||||
/* Gets an auto incrementing filename stem.
|
||||
* Pattern should be like "FOO_???.txt" where ??? will be replaced by digits.
|
||||
* Pattern may also contain a folder path like "LOGS/FOO_???.txt".
|
||||
* Pattern '?' must be contiguous (bad: "FOO?_??")
|
||||
* Returns empty path if a filename could not be created. */
|
||||
std::filesystem::path next_filename_matching_pattern(const std::filesystem::path& pattern);
|
||||
|
||||
/* Values added to FatFs FRESULT enum, values outside the FRESULT data type */
|
||||
static_assert(sizeof(FIL::err) == 1, "FatFs FIL::err size not expected.");
|
||||
|
@ -35,6 +35,10 @@ using namespace lpc43xx;
|
||||
class LogFile {
|
||||
public:
|
||||
Optional<File::Error> append(const std::filesystem::path& filename) {
|
||||
auto result = ensure_directory(filename.parent_path());
|
||||
if (result.code())
|
||||
return { result };
|
||||
|
||||
return file.append(filename);
|
||||
}
|
||||
|
||||
|
@ -256,8 +256,17 @@ double get_decimals(double num, int16_t mult, bool round) {
|
||||
return intnum;
|
||||
}
|
||||
|
||||
std::string trimr(std::string str)
|
||||
{
|
||||
std::string trim(const std::string& str) {
|
||||
auto first = str.find_first_not_of(' ');
|
||||
auto last = str.find_last_not_of(' ');
|
||||
return str.substr(first, last - first);
|
||||
}
|
||||
|
||||
std::string trimr(std::string str) {
|
||||
size_t last = str.find_last_not_of(' ');
|
||||
return (last!=std::string::npos) ? str.substr(0, last+1) : ""; // Remove the trailing spaces
|
||||
}
|
||||
|
||||
std::string truncate(const std::string& str, size_t length) {
|
||||
return str.length() <= length ? str : str.substr(0, length);
|
||||
}
|
@ -59,6 +59,8 @@ std::string to_string_FAT_timestamp(const FATTimestamp& timestamp);
|
||||
std::string unit_auto_scale(double n, const uint32_t base_nano, uint32_t precision);
|
||||
double get_decimals(double num, int16_t mult, bool round = false); //euquiq added
|
||||
|
||||
std::string trim(const std::string& str); // Remove whitespace at ends.
|
||||
std::string trimr(std::string str); // Remove trailing spaces
|
||||
std::string truncate(const std::string& str, size_t length);
|
||||
|
||||
#endif/*__STRING_FORMAT_H__*/
|
||||
|
@ -367,13 +367,15 @@ void SystemStatusView::on_bias_tee() {
|
||||
}*/
|
||||
|
||||
void SystemStatusView::on_camera() {
|
||||
auto path = next_filename_stem_matching_pattern(u"SCR_????");
|
||||
ensure_directory("SCREENSHOTS");
|
||||
auto path = next_filename_matching_pattern(u"SCREENSHOTS/SCR_????.PNG");
|
||||
|
||||
if( path.empty() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
PNGWriter png;
|
||||
auto create_error = png.create(path.replace_extension(u".PNG"));
|
||||
auto create_error = png.create(path);
|
||||
if( create_error.is_valid() ) {
|
||||
return;
|
||||
}
|
||||
|
@ -55,16 +55,19 @@ namespace ui {
|
||||
|
||||
RecordView::RecordView(
|
||||
const Rect parent_rect,
|
||||
std::filesystem::path filename_stem_pattern,
|
||||
const std::filesystem::path& filename_stem_pattern,
|
||||
const std::filesystem::path& folder,
|
||||
const FileType file_type,
|
||||
const size_t write_size,
|
||||
const size_t buffer_count
|
||||
) : View { parent_rect },
|
||||
filename_stem_pattern { filename_stem_pattern },
|
||||
folder { folder },
|
||||
file_type { file_type },
|
||||
write_size { write_size },
|
||||
buffer_count { buffer_count }
|
||||
{
|
||||
ensure_directory(folder);
|
||||
add_children({
|
||||
&rect_background,
|
||||
//&button_pitch_rssi,
|
||||
@ -154,7 +157,6 @@ void RecordView::start() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::filesystem::path base_path;
|
||||
if(filename_date_frequency) {
|
||||
rtcGetTime(&RTCD1, &datetime);
|
||||
@ -167,9 +169,11 @@ void RecordView::start() {
|
||||
to_string_dec_uint(datetime.minute()) +
|
||||
to_string_dec_uint(datetime.second());
|
||||
|
||||
base_path = filename_stem_pattern.string() + "_" + date_time + "_" + to_string_freq(receiver_model.tuning_frequency()) + "Hz";
|
||||
base_path = filename_stem_pattern.string() + "_" + date_time + "_" +
|
||||
trim(to_string_freq(receiver_model.tuning_frequency())) + "Hz";
|
||||
base_path = folder / base_path;
|
||||
} else {
|
||||
base_path = next_filename_stem_matching_pattern(filename_stem_pattern);
|
||||
base_path = next_filename_matching_pattern(folder / filename_stem_pattern);
|
||||
}
|
||||
|
||||
if( base_path.empty() ) {
|
||||
@ -217,7 +221,7 @@ void RecordView::start() {
|
||||
};
|
||||
|
||||
if( writer ) {
|
||||
text_record_filename.set(base_path.replace_extension().string());
|
||||
text_record_filename.set(truncate(base_path.filename().string(), 8));
|
||||
button_record.set_bitmap(&bitmap_stop);
|
||||
capture_thread = std::make_unique<CaptureThread>(
|
||||
std::move(writer),
|
||||
@ -275,7 +279,7 @@ void RecordView::on_tick_second() {
|
||||
void RecordView::update_status_display() {
|
||||
if( is_active() ) {
|
||||
const auto dropped_percent = std::min(99U, capture_thread->state().dropped_percent());
|
||||
const auto s = to_string_dec_uint(dropped_percent, 2, ' ') + "\%";
|
||||
const auto s = to_string_dec_uint(dropped_percent, 2, ' ') + "%";
|
||||
text_record_dropped.set(s);
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,8 @@ public:
|
||||
|
||||
RecordView(
|
||||
const Rect parent_rect,
|
||||
std::filesystem::path filename_stem_pattern,
|
||||
const std::filesystem::path& filename_stem_pattern,
|
||||
const std::filesystem::path& folder,
|
||||
FileType file_type,
|
||||
const size_t write_size,
|
||||
const size_t buffer_count
|
||||
@ -83,6 +84,7 @@ private:
|
||||
rtc::RTC datetime { };
|
||||
|
||||
const std::filesystem::path filename_stem_pattern;
|
||||
const std::filesystem::path folder;
|
||||
const FileType file_type;
|
||||
const size_t write_size;
|
||||
const size_t buffer_count;
|
||||
|
Loading…
Reference in New Issue
Block a user