From aeb607e73b574e3a63f4bd7fdc2a3c747ea370f9 Mon Sep 17 00:00:00 2001 From: Netro <146584182+iNetro@users.noreply.github.com> Date: Thu, 16 Nov 2023 14:00:52 -0500 Subject: [PATCH] BLE Rx Save List / Save packet from BLE Rx (#1582) * Added Tx Save from Rx Details View * Added saving of current list --- firmware/application/apps/ble_rx_app.cpp | 104 +++++++++++++++++++++++ firmware/application/apps/ble_rx_app.hpp | 23 ++++- 2 files changed, 123 insertions(+), 4 deletions(-) diff --git a/firmware/application/apps/ble_rx_app.cpp b/firmware/application/apps/ble_rx_app.cpp index 105b4222..0624d210 100644 --- a/firmware/application/apps/ble_rx_app.cpp +++ b/firmware/application/apps/ble_rx_app.cpp @@ -162,6 +162,7 @@ BleRecentEntryDetailView::BleRecentEntryDetailView(NavigationView& nav, const Bl entry_{entry} { add_children({&button_done, &button_send, + &button_save, &label_mac_address, &text_mac_address, &label_pdu_type, @@ -182,6 +183,47 @@ BleRecentEntryDetailView::BleRecentEntryDetailView(NavigationView& nav, const Bl }); nav.pop(); }; + + button_save.on_select = [this, &nav](const ui::Button&) { + auto packetToSave = build_packet(); + + packetFileBuffer = ""; + text_prompt( + nav, + packetFileBuffer, + 64, + [this, packetToSave](std::string& buffer) { + on_save_file(buffer, packetToSave); + }); + }; +} + +void BleRecentEntryDetailView::on_save_file(const std::string value, BLETxPacket packetToSave) { + std::filesystem::path packet_save_path{u"BLERX/Packets/Packet_????.TXT"}; + + ensure_directory(packet_save_path); + auto folder = packet_save_path.parent_path(); + auto ext = packet_save_path.extension(); + auto new_path = folder / value + ext; + + saveFile(new_path, packetToSave); +} + +bool BleRecentEntryDetailView::saveFile(const std::filesystem::path& path, BLETxPacket packetToSave) { + File f; + auto error = f.create(path); + if (error) + return false; + + std::string macAddressStr = packetToSave.macAddress; + std::string advertisementDataStr = packetToSave.advertisementData; + std::string packetCountStr = packetToSave.packetCount; + + std::string packetString = macAddressStr + ' ' + advertisementDataStr + ' ' + packetCountStr; + + f.write(packetString.c_str(), packetString.length()); + + return true; } void BleRecentEntryDetailView::update_data() { @@ -377,6 +419,7 @@ BLERxView::BLERxView(NavigationView& nav) &label_sort, &options_sort, &button_filter, + &button_save_list, &button_switch, &recent_entries_view}); @@ -394,6 +437,17 @@ BLERxView::BLERxView(NavigationView& nav) }); }; + button_save_list.on_select = [this, &nav](const ui::Button&) { + listFileBuffer = ""; + text_prompt( + nav, + listFileBuffer, + 64, + [this](std::string& buffer) { + on_save_file(buffer); + }); + }; + button_switch.on_select = [&nav](Button&) { nav.replace(); }; @@ -447,6 +501,55 @@ BLERxView::BLERxView(NavigationView& nav) receiver_model.enable(); } +void BLERxView::on_save_file(const std::string value) { + std::filesystem::path packet_save_path{u"BLERX/Lists/List_????.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; + + saveFile(new_path); +} + +bool BLERxView::saveFile(const std::filesystem::path& path) { + File f; + auto error = f.create(path); + if (error) + return false; + + auto it = recent.begin(); + + std::string headerStr = "Timestamp, MAC Address, Name, Packet Type, Data, Hits, dB, Channel \n"; + f.write(headerStr.c_str(), headerStr.length()); + + while (it != recent.end()) { + BleRecentEntry entry = (BleRecentEntry)*it; + + std::string macAddressStr = to_string_mac_address(entry.packetData.macAddress, 6, false) + ", "; + std::string timestameStr = entry.timestamp + ", "; + std::string nameStr = entry.nameString + ", "; + std::string pduStr = pdu_type_to_string(entry.pduType) + ", "; + std::string dataStr = "0x" + entry.dataString + ", "; + std::string hitsStr = to_string_dec_int(entry.numHits) + ", "; + std::string dbStr = to_string_dec_int(entry.dbValue) + ", "; + std::string channelStr = to_string_dec_int(entry.channelNumber) + "\n"; + + f.write(timestameStr.c_str(), timestameStr.length()); + f.write(macAddressStr.c_str(), macAddressStr.length()); + f.write(nameStr.c_str(), nameStr.length()); + f.write(pduStr.c_str(), pduStr.length()); + f.write(dataStr.c_str(), dataStr.length()); + f.write(hitsStr.c_str(), hitsStr.length()); + f.write(dbStr.c_str(), dbStr.length()); + f.write(channelStr.c_str(), channelStr.length()); + + it++; + } + + return true; +} + void BLERxView::on_data(BlePacketData* packet) { if (auto_channel) { int min = 37; @@ -584,6 +687,7 @@ void BLERxView::updateEntry(const BlePacketData* packet, BleRecentEntry& entry, entry.numHits++; entry.pduType = pdu_type; + entry.channelNumber = channel_number; // Parse Data Section into buffer to be interpretted later. for (int i = 0; i < packet->dataLen; i++) { diff --git a/firmware/application/apps/ble_rx_app.hpp b/firmware/application/apps/ble_rx_app.hpp index 6d6f9ec3..b536572a 100644 --- a/firmware/application/apps/ble_rx_app.hpp +++ b/firmware/application/apps/ble_rx_app.hpp @@ -84,6 +84,7 @@ struct BleRecentEntry { bool include_name; uint16_t numHits; ADV_PDU_TYPE pduType; + uint8_t channelNumber; BleRecentEntry() : BleRecentEntry{0} { @@ -99,7 +100,8 @@ struct BleRecentEntry { nameString{}, include_name{}, numHits{}, - pduType{} { + pduType{}, + channelNumber{} { } Key key() const { @@ -125,6 +127,9 @@ class BleRecentEntryDetailView : public View { NavigationView& nav_; BleRecentEntry entry_{}; BLETxPacket build_packet(); + void on_save_file(const std::string value, BLETxPacket packetToSave); + bool saveFile(const std::filesystem::path& path, BLETxPacket packetToSave); + std::string packetFileBuffer{}; static constexpr uint8_t total_data_lines{5}; @@ -156,6 +161,10 @@ class BleRecentEntryDetailView : public View { {125, 224, 96, 24}, "Done"}; + Button button_save{ + {72, 264, 96, 24}, + "Save"}; + bool send_updates{false}; Rect draw_field( @@ -179,6 +188,8 @@ class BLERxView : public View { std::string title() const override { return "BLE RX"; }; private: + void on_save_file(const std::string value); + bool saveFile(const std::filesystem::path& path); void on_data(BlePacketData* packetData); void on_filter_change(std::string value); void handle_entries_sort(uint8_t index); @@ -200,6 +211,7 @@ class BLERxView : public View { std::string filterBuffer{}; std::string filter{}; + std::string listFileBuffer{}; static constexpr auto header_height = 3 * 16; static constexpr auto switch_button_height = 3 * 16; @@ -262,9 +274,13 @@ class BLERxView : public View { Console console{ {0, 4 * 16, 240, 240}}; + Button button_save_list{ + {1 * 8, 16 * 16, 13 * 8, 2 * 16}, + "Save List"}; + Button button_switch{ - {8 * 8, 16 * 16, 14 * 8, 2 * 16}, - "Switch to Tx"}; + {16 * 8, 16 * 16, 13 * 8, 2 * 16}, + "Switch to Rx"}; std::string str_log{""}; bool logging{false}; @@ -272,7 +288,6 @@ class BLERxView : public View { std::unique_ptr logger{}; BleRecentEntries recent{}; - BleRecentEntries filterEntries{}; const RecentEntriesColumns columns{{ {"Mac Address", 17},