BLE List improvements (#1595)

* WIP on add to save list

* Added rewriting existing lines and appending new to same file.

* format

* not looking on new file.

* Added temp list due to some issue of recent being updated during save

I was receiving a system halt and this seems to fix it. Needs more testing though.

* clang format

* Stored entries backward. Fix.

* Update file working, need to replace temp file though.
This commit is contained in:
Netro 2023-11-19 20:53:53 -05:00 committed by GitHub
parent 309f2fbd2c
commit 5a1676a0b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 163 additions and 58 deletions

View File

@ -506,6 +506,22 @@ BLERxView::BLERxView(NavigationView& nav)
receiver_model.enable();
}
std::string BLERxView::build_line_str(BleRecentEntry entry) {
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) + ",";
std::string lineStr = timestameStr + macAddressStr + nameStr + pduStr + dataStr + hitsStr + dbStr + channelStr;
lineStr += pad_string_with_spaces(maxLineLength - lineStr.length());
return lineStr;
}
void BLERxView::on_save_file(const std::string value) {
std::filesystem::path packet_save_path{u"BLERX/Lists/List_????.csv"};
@ -518,40 +534,119 @@ void BLERxView::on_save_file(const std::string value) {
}
bool BLERxView::saveFile(const std::filesystem::path& path) {
// Check to see if file was previously saved.
bool file_existed = file_exists(path);
// Attempt to open, if it can't be opened. Create new.
File f;
auto error = f.create(path);
if (error)
auto error = f.open(path, false, true);
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++;
}
for (const auto& entry : recent) {
tempList.emplace_back(entry);
}
if (!file_existed) {
f.write_line(headerStr.c_str());
auto it = tempList.begin();
while (it != tempList.end()) {
BleRecentEntry entry = (BleRecentEntry)*it;
f.write_line(build_line_str(entry).c_str());
it++;
}
} else {
// Check file for macAddressStr before adding.
char currentLine[maxLineLength];
uint64_t startPos = headerStr.length();
uint64_t bytesRead = 0;
uint64_t bytePos = 0;
File::Size currentSize = f.size();
File tempFile;
const std::filesystem::path tempFilePath = path + "~";
auto error = tempFile.open(tempFilePath, false, true);
if (error) {
return false;
}
tempFile.write_line(headerStr.c_str());
f.seek(startPos);
// Look for ones found and rewrite.
do {
memset(currentLine, 0, maxLineLength);
bytesRead = readUntil(f, currentLine, currentSize, '\n');
if (!bytesRead) {
break;
}
bytePos += bytesRead;
std::string lineStr = "";
std::string macAddressStr = "";
BleRecentEntry foundEntry;
char* token;
token = strtok(currentLine, ",");
while (token != NULL) {
auto it = tempList.begin();
while (it != tempList.end()) {
BleRecentEntry& entry = reinterpret_cast<BleRecentEntry&>(*it);
macAddressStr = to_string_mac_address(entry.packetData.macAddress, 6, false);
if (strstr(token, macAddressStr.c_str()) != NULL) {
entry.entryFound = true;
foundEntry = entry;
break;
}
it++;
}
if (foundEntry.entryFound) {
break;
}
token = strtok(NULL, ",");
}
if (foundEntry.entryFound) {
tempFile.write_line(build_line_str(foundEntry).c_str());
}
} while (bytePos <= currentSize);
// Write the ones not found.
auto it = tempList.begin();
while (it != tempList.end()) {
BleRecentEntry entry = (BleRecentEntry)*it;
if (!entry.entryFound) {
tempFile.write_line(build_line_str(entry).c_str());
}
it++;
}
// rename_file(tempFilePath, path);
}
tempList.clear();
return true;
}

View File

@ -85,6 +85,7 @@ struct BleRecentEntry {
uint16_t numHits;
ADV_PDU_TYPE pduType;
uint8_t channelNumber;
bool entryFound;
BleRecentEntry()
: BleRecentEntry{0} {
@ -101,7 +102,8 @@ struct BleRecentEntry {
include_name{},
numHits{},
pduType{},
channelNumber{} {
channelNumber{},
entryFound{} {
}
Key key() const {
@ -188,6 +190,7 @@ class BLERxView : public View {
std::string title() const override { return "BLE RX"; };
private:
std::string build_line_str(BleRecentEntry entry);
void on_save_file(const std::string value);
bool saveFile(const std::filesystem::path& path);
void on_data(BlePacketData* packetData);
@ -212,6 +215,8 @@ class BLERxView : public View {
std::string filterBuffer{};
std::string filter{};
std::string listFileBuffer{};
std::string headerStr = "Timestamp, MAC Address, Name, Packet Type, Data, Hits, dB, Channel";
uint16_t maxLineLength = 140;
static constexpr auto header_height = 3 * 16;
static constexpr auto switch_button_height = 3 * 16;
@ -292,6 +297,7 @@ class BLERxView : public View {
std::unique_ptr<BLELogger> logger{};
BleRecentEntries recent{};
BleRecentEntries tempList{};
const RecentEntriesColumns columns{{
{"Mac Address", 17},

View File

@ -94,33 +94,6 @@ uint32_t stringToUint32(const std::string& str) {
return result;
}
void readUntil(File& file, char* result, std::size_t maxBufferSize, char delimiter) {
std::size_t bytesRead = 0;
while (true) {
char ch;
File::Result<File::Size> readResult = file.read(&ch, 1);
if (readResult.is_ok() && readResult.value() > 0) {
if (ch == delimiter) {
// Found a space character, stop reading
break;
} else if (bytesRead < maxBufferSize) {
// Append the character to the result if there's space
result[bytesRead++] = ch;
} else {
// Buffer is full, break to prevent overflow
break;
}
} else {
break; // End of file or error
}
}
// Null-terminate the result string
result[bytesRead] = '\0';
}
static std::uint64_t get_freq_by_channel_number(uint8_t channel_number) {
uint64_t freq_hz;

View File

@ -348,6 +348,35 @@ void generateRandomMacAddress(char* macAddress) {
macAddress[12] = '\0'; // Null-terminate the string
}
uint64_t readUntil(File& file, char* result, std::size_t maxBufferSize, char delimiter) {
std::size_t bytesRead = 0;
while (true) {
char ch;
File::Result<File::Size> readResult = file.read(&ch, 1);
if (readResult.is_ok() && readResult.value() > 0) {
if (ch == delimiter) {
// Found a space character, stop reading
break;
} else if (bytesRead < maxBufferSize) {
// Append the character to the result if there's space
result[bytesRead++] = ch;
} else {
// Buffer is full, break to prevent overflow
break;
}
} else {
break; // End of file or error
}
}
// Null-terminate the result string
result[bytesRead] = '\0';
return bytesRead;
}
std::string unit_auto_scale(double n, const uint32_t base_unit, uint32_t precision) {
const uint32_t powers_of_ten[5] = {1, 10, 100, 1000, 10000};
std::string string{""};

View File

@ -81,6 +81,8 @@ std::string to_string_mac_address(const uint8_t* macAddress, uint8_t length, boo
std::string to_string_formatted_mac_address(const char* macAddress);
void generateRandomMacAddress(char* macAddress);
uint64_t readUntil(File& file, char* result, std::size_t maxBufferSize, char delimiter);
/* Scales 'n' to be a value less than 1000. 'base_unit' is the index of the unit from
* 'unit_prefix' that 'n' is in initially. 3 is the index of the '1s' unit. */
std::string unit_auto_scale(double n, const uint32_t base_unit, uint32_t precision);