diff --git a/firmware/application/apps/ble_rx_app.cpp b/firmware/application/apps/ble_rx_app.cpp index 45aac6f5..6be25a49 100644 --- a/firmware/application/apps/ble_rx_app.cpp +++ b/firmware/application/apps/ble_rx_app.cpp @@ -22,19 +22,22 @@ */ #include "ble_rx_app.hpp" - +#include "ble_rx_app.hpp" #include "ui_modemsetup.hpp" #include "modems.hpp" #include "audio.hpp" +#include "io_file.hpp" #include "rtc_time.hpp" #include "baseband_api.hpp" #include "string_format.hpp" #include "portapack_persistent_memory.hpp" +#include "ui_fileman.hpp" #include "ui_textentry.hpp" using namespace portapack; using namespace modems; +namespace fs = std::filesystem; void BLELogger::log_raw_data(const std::string& data) { log_file.write_entry(data); @@ -199,8 +202,6 @@ BleRecentEntryDetailView::BleRecentEntryDetailView(NavigationView& nav, const Bl } void BleRecentEntryDetailView::on_save_file(const std::string value, BLETxPacket packetToSave) { - std::filesystem::path packet_save_path{u"BLERX/Packets/????.TXT"}; - ensure_directory(packet_save_path); auto folder = packet_save_path.parent_path(); auto ext = packet_save_path.extension(); @@ -403,6 +404,10 @@ void BLERxView::focus() { options_channel.focus(); } +void BLERxView::file_error() { + nav_.display_modal("Error", "File read error."); +} + BLERxView::BLERxView(NavigationView& nav) : nav_{nav} { baseband::run_image(portapack::spi_flash::image_tag_btle_rx); @@ -415,9 +420,12 @@ BLERxView::BLERxView(NavigationView& nav) &options_channel, &field_frequency, &check_log, + &button_find, &check_name, &label_sort, &options_sort, + &label_found, + &text_found_count, &button_filter, &button_save_list, &button_clear_list, @@ -428,6 +436,10 @@ BLERxView::BLERxView(NavigationView& nav) nav_.push(entry); }; + ensure_directory(find_packet_path); + ensure_directory(log_packets_path); + ensure_directory(packet_save_path); + filterBuffer = filter; button_filter.on_select = [this](Button&) { @@ -440,6 +452,21 @@ BLERxView::BLERxView(NavigationView& nav) }); }; + logger = std::make_unique(); + + check_log.set_value(logging); + + check_log.on_select = [this](Checkbox&, bool v) { + str_log = ""; + logging = v; + + if (logger && logging) + logger->append( + "BLERX/Logs" + "/BLELOG_" + + to_string_timestamp(rtc_time::now()) + ".TXT"); + }; + button_save_list.on_select = [this, &nav](const ui::Button&) { listFileBuffer = ""; text_prompt( @@ -461,16 +488,6 @@ BLERxView::BLERxView(NavigationView& nav) field_frequency.set_step(0); - check_log.set_value(logging); - - check_log.on_select = [this](Checkbox&, bool v) { - str_log = ""; - logging = v; - - if (logger && logging) - logger->append(LOG_ROOT_DIR "/BLELOG_" + to_string_timestamp(rtc_time::now()) + ".TXT"); - }; - check_name.set_value(name_enable); check_name.on_select = [this](Checkbox&, bool v) { @@ -504,7 +521,14 @@ BLERxView::BLERxView(NavigationView& nav) options_channel.set_selected_index(channel_index, true); options_sort.set_selected_index(sort_index, true); - logger = std::make_unique(); + button_find.on_select = [this](Button&) { + auto open_view = nav_.push(".TXT"); + open_view->on_changed = [this](std::filesystem::path new_file_path) { + on_file_changed(new_file_path); + + // nav_.set_on_pop([this]() { button_play.focus(); }); + }; + }; // Auto-configure modem for LCR RX (will be removed later) baseband::set_btlerx(channel_number); @@ -529,9 +553,6 @@ std::string BLERxView::build_line_str(BleRecentEntry entry) { } void BLERxView::on_save_file(const std::string value) { - std::filesystem::path packet_save_path{u"BLERX/Lists/????.csv"}; - - ensure_directory(packet_save_path); auto folder = packet_save_path.parent_path(); auto ext = packet_save_path.extension(); auto new_path = folder / value + ext; @@ -709,6 +730,24 @@ void BLERxView::on_data(BlePacketData* packet) { if (logger && logging) { logger->log_raw_data(str_console); } + + if (!searchList.empty()) { + auto it = searchList.begin(); + + while (it != searchList.end()) { + std::string searchStr = (std::string)*it; + + if (entry.dataString.find(searchStr) != std::string::npos) { + searchList.erase(it); + found_count++; + break; + } + + it++; + } + + text_found_count.set(to_string_dec_uint(found_count) + "/" + to_string_dec_uint(total_count)); + } } void BLERxView::on_filter_change(std::string value) { @@ -722,6 +761,48 @@ void BLERxView::on_filter_change(std::string value) { filter = value; } +void BLERxView::on_file_changed(const std::filesystem::path& new_file_path) { + file_path = fs::path(u"/") + new_file_path; + found_count = 0; + total_count = 0; + searchList.clear(); + + { // Get the size of the data file. + File data_file; + auto error = data_file.open(file_path, true, false); + if (error) { + file_error(); + file_path = ""; + return; + } + + uint64_t bytesRead = 0; + uint64_t bytePos = 0; + char currentLine[maxLineLength]; + + do { + memset(currentLine, 0, maxLineLength); + + bytesRead = readUntil(data_file, currentLine, maxLineLength, '\n'); + + // Remove return if found. + if (currentLine[strlen(currentLine)] == '\r') { + currentLine[strlen(currentLine)] = '\0'; + } + + if (!bytesRead) { + break; + } + + searchList.push_back(currentLine); + total_count++; + + bytePos += bytesRead; + + } while (bytePos <= data_file.size()); + } +} + // called each 1/60th of second, so 6 = 100ms void BLERxView::on_timer() { if (++timer_count == timer_period) { diff --git a/firmware/application/apps/ble_rx_app.hpp b/firmware/application/apps/ble_rx_app.hpp index 4416e74d..3e84b2d8 100644 --- a/firmware/application/apps/ble_rx_app.hpp +++ b/firmware/application/apps/ble_rx_app.hpp @@ -132,6 +132,7 @@ class BleRecentEntryDetailView : public View { void on_save_file(const std::string value, BLETxPacket packetToSave); bool saveFile(const std::filesystem::path& path, BLETxPacket packetToSave); std::string packetFileBuffer{}; + std::filesystem::path packet_save_path{u"BLERX/Lists/????.csv"}; static constexpr uint8_t total_data_lines{5}; @@ -195,6 +196,8 @@ class BLERxView : public View { bool saveFile(const std::filesystem::path& path); void on_data(BlePacketData* packetData); void on_filter_change(std::string value); + void on_file_changed(const std::filesystem::path& new_file_path); + void file_error(); void on_timer(); void handle_entries_sort(uint8_t index); void updateEntry(const BlePacketData* packet, BleRecentEntry& entry, ADV_PDU_TYPE pdu_type); @@ -235,7 +238,16 @@ class BLERxView : public View { std::string headerStr = "Timestamp, MAC Address, Name, Packet Type, Data, Hits, dB, Channel"; uint16_t maxLineLength = 140; - static constexpr auto header_height = 3 * 16; + std::filesystem::path file_path{}; + uint64_t found_count = 0; + uint64_t total_count = 0; + std::vector searchList{}; + + std::filesystem::path find_packet_path{u"BLERX/Find/????.TXT"}; + std::filesystem::path log_packets_path{u"BLERX/Logs/????.TXT"}; + std::filesystem::path packet_save_path{u"BLERX/Lists/????.csv"}; + + static constexpr auto header_height = 4 * 16; static constexpr auto switch_button_height = 3 * 16; OptionsField options_channel{ @@ -293,6 +305,17 @@ class BLERxView : public View { "Name", true}; + Button button_find{ + {0 * 8, 6 * 8, 4 * 8, 16}, + "Find"}; + + Labels label_found{ + {{5 * 8, 6 * 8}, "Found:", Color::light_grey()}}; + + Text text_found_count{ + {11 * 8, 3 * 16, 20 * 8, 16}, + "0/0"}; + Console console{ {0, 4 * 16, 240, 240}}; @@ -309,7 +332,6 @@ class BLERxView : public View { "Tx"}; std::string str_log{""}; - std::unique_ptr logger{}; BleRecentEntries recent{};