Added Sorting to BLE app (#1527)

* First BLE work

* Adding new fsk proc WIP

* Reverting ble stuff

* Initial compile working

* more work.

* Adding waterfall for debug

* more edits to debug

* Work to get widgets to show.

* cleanup before attempting diff fsk modulation method

* Temporary debug to learn how decimation scales.

* Tab view for console and spectrum. Spectrum still not working right.

* Fixed spectrum offset.

* Added audio sampling rate increments to freqman

* Added overriding range for frequency field and working off  deviation

* BLE cleanup. Got PDU parsing.

* Parsing CRC

* forgot :

* Removing AA again because cluttering UI

* fix compile

* attempt at throttling.

* WIP changes.

* Decimating by 4 to handle issue with overloading.

* Attempt to parse MAC still needs work.

* Small fixes. MAC still wrong.

* Fixed invalid indexing on Symbols.

* List view of BLE Mac Addresses

* Added Channel Option and improved GUI header.

* renaming to dB and fixing some warnings.

* Advertisements only.

* Initial cut of BLE Advertisement scan app.

* Copyrights

* formatting correctly in association to clang13

* Fixing warning and hiding fsk rx.

* spacing

* Removing some cmake install files that weren't suppose to be there.

* missed some.

* Added name to about.

* Edits for PR review pt.1

* Refactor ORing with 0 doesn't make sense.

* remove  parenthesis

* More PR Review changes.

* Fix compiler error.

* PR Review edits.

* PR review changes.

* Fixes.

* Unneeded ;

* Update ui_about_simple.cpp

* Disabling frequency stepping.

* removing unused label

* Fixing something that got messed up in merge?

* removing file that got added.

* editing labels.

* Added sort functionality.

* removed unused code.

---------

Co-authored-by: jLynx <admin@jlynx.net>
This commit is contained in:
Netro 2023-10-24 18:08:45 -04:00 committed by GitHub
parent 80bfcd5eb1
commit 15c338e5b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 114 additions and 45 deletions

View File

@ -43,6 +43,17 @@ std::string pad_string_with_spaces(int snakes) {
return paddedStr;
}
uint64_t copy_mac_address_to_uint64(const uint8_t* macAddress) {
uint64_t result = 0;
// Copy each byte of the MAC address to the corresponding byte in the uint64_t.
for (int i = 0; i < 6; ++i) {
result |= static_cast<uint64_t>(macAddress[i]) << ((5 - i) * 8);
}
return result;
}
namespace ui {
template <>
void RecentEntriesTable<BleRecentEntries>::draw(
@ -50,13 +61,7 @@ void RecentEntriesTable<BleRecentEntries>::draw(
const Rect& target_rect,
Painter& painter,
const Style& style) {
std::string line = to_string_hex(entry.macAddress & 0xFF, 2);
line += ":" + to_string_hex((entry.macAddress >> 8) & 0xFF, 2);
line += ":" + to_string_hex((entry.macAddress >> 16) & 0xFF, 2);
line += ":" + to_string_hex((entry.macAddress >> 24) & 0xFF, 2);
line += ":" + to_string_hex((entry.macAddress >> 32) & 0xFF, 2);
line += ":" + to_string_hex((entry.macAddress >> 40), 2);
std::string line = to_string_mac_address(entry.packetData.macAddress, 6);
// Handle spacing for negative sign.
uint8_t db_spacing = entry.dbValue > 0 ? 7 : 6;
@ -126,13 +131,6 @@ void BleRecentEntryDetailView::paint(Painter& painter) {
length[currentPacket] = entry_.packetData.data[currentByte++];
type[currentPacket] = entry_.packetData.data[currentByte++];
// This should never happen, but in here just in case.
// Break because we can't trust rest of data.
// if (length[currentPacket] > entry_.packetData.dataLen)
// {
// break;
// }
// Subtract 1 because type is part of the length.
for (i = 0; i < length[currentPacket] - 1; i++) {
data[currentPacket][i] = entry_.packetData.data[currentByte++];
@ -211,9 +209,11 @@ BLERxView::BLERxView(NavigationView& nav)
&field_rf_amp,
&field_lna,
&field_vga,
&options_region,
&options_channel,
&field_frequency,
&check_log,
&label_sort,
&options_sort,
&recent_entries_view,
&recent_entry_detail_view});
@ -232,14 +232,36 @@ BLERxView::BLERxView(NavigationView& nav)
logging = v;
};
options_region.on_change = [this](size_t, int32_t i) {
options_channel.on_change = [this](size_t, int32_t i) {
field_frequency.set_value(get_freq_by_channel_number(i));
channel_number = i;
baseband::set_btle(channel_number);
};
options_region.set_selected_index(0, true);
options_sort.on_change = [this](size_t, int32_t i) {
switch (i) {
case 0:
sortEntriesBy(
recent, [](const BleRecentEntry& entry) { return entry.macAddress; }, true);
break;
case 1:
sortEntriesBy(
recent, [](const BleRecentEntry& entry) { return entry.dbValue; }, true);
break;
case 2:
sortEntriesBy(
recent, [](const BleRecentEntry& entry) { return entry.timestamp; }, false);
break;
default:
break;
}
recent_entries_view.set_dirty();
};
options_channel.set_selected_index(0, true);
options_sort.set_selected_index(0, true);
logger = std::make_unique<BLELogger>();
@ -299,18 +321,13 @@ void BLERxView::on_data(BlePacketData* packet) {
// str_console += to_string_dec_uint(value);
str_console += " Len: ";
str_console += " Len:";
str_console += to_string_dec_uint(packet->size);
str_console += "\n";
str_console += "Mac";
str_console += ":" + to_string_hex(packet->macAddress[0], 2);
str_console += ":" + to_string_hex(packet->macAddress[1], 2);
str_console += ":" + to_string_hex(packet->macAddress[2], 2);
str_console += ":" + to_string_hex(packet->macAddress[3], 2);
str_console += ":" + to_string_hex(packet->macAddress[4], 2);
str_console += ":" + to_string_hex(packet->macAddress[5], 2);
str_console += "Mac:";
str_console += to_string_mac_address(packet->macAddress, 6);
str_console += "\n";
str_console += "Data:";
@ -323,15 +340,15 @@ void BLERxView::on_data(BlePacketData* packet) {
str_console += "\n";
uint64_t macAddressEncoded = copy_mac_address_to_uint64(packet->macAddress);
// Start of Packet stuffing.
uint64_t macAddressEncoded = 0;
memcpy(&macAddressEncoded, packet->macAddress, sizeof(uint64_t));
// Masking off the top 2 bytes to avoid invalid keys.
auto& entry = ::on_packet(recent, macAddressEncoded & 0xFFFFFFFFFFFF);
entry.dbValue = packet->max_dB;
entry.timestamp = to_string_timestamp(rtc_time::now());
entry.packetData.type = packet->type;
entry.packetData.size = packet->size;
entry.packetData.dataLen = packet->dataLen;
@ -348,6 +365,24 @@ void BLERxView::on_data(BlePacketData* packet) {
}
// entry.update(packet);
switch (options_sort.selected_index()) {
case 0:
sortEntriesBy(
recent, [](const BleRecentEntry& entry) { return entry.macAddress; }, true);
break;
case 1:
sortEntriesBy(
recent, [](const BleRecentEntry& entry) { return entry.dbValue; }, true);
break;
case 2:
sortEntriesBy(
recent, [](const BleRecentEntry& entry) { return entry.timestamp; }, false);
break;
default:
break;
}
recent_entries_view.set_dirty();
// TODO: Crude hack, should be a more formal listener arrangement...

View File

@ -76,6 +76,7 @@ struct BleRecentEntry {
uint64_t macAddress;
int dbValue;
BlePacketData packetData;
std::string timestamp;
BleRecentEntry()
: BleRecentEntry{0} {
@ -85,7 +86,8 @@ struct BleRecentEntry {
const uint64_t macAddress)
: macAddress{macAddress},
dbValue{},
packetData{} {
packetData{},
timestamp{} {
}
Key key() const {
@ -165,6 +167,17 @@ class BLERxView : public View {
static constexpr auto header_height = 12 + 2 * 16;
OptionsField options_channel{
{0 * 8, 0 * 8},
5,
{{"Ch.37 ", 37},
{"Ch.38", 38},
{"Ch.39", 39}}};
RxFrequencyField field_frequency{
{6 * 8, 0 * 16},
nav_};
RFAmpField field_rf_amp{
{16 * 8, 0 * 16}};
@ -180,26 +193,25 @@ class BLERxView : public View {
Channel channel{
{24 * 8, 5, 6 * 8, 4}};
RxFrequencyField field_frequency{
{6 * 8, 0 * 16},
nav_};
Checkbox check_log{
{0 * 8, 3 * 8},
3,
"Log",
true};
OptionsField options_region{
{0 * 8, 0 * 8},
5,
{{"Ch.37 ", 37},
{"Ch.38", 38},
{"Ch.39", 39}}};
Labels label_sort{
{{6 * 8, 3 * 8}, "Sort:", Color::light_grey()}};
OptionsField options_sort{
{12 * 8, 3 * 8},
6,
{{"MAC", 0},
{"dB", 1},
{"Recent", 2}}};
Console console{
{0, 4 * 16, 240, 240}};
Checkbox check_log{
{0 * 8, 1 * 16},
3,
"LOG",
false};
std::string str_log{""};
bool logging{false};

View File

@ -88,6 +88,13 @@ static std::pair<typename ContainerType::const_iterator, typename ContainerType:
return {start, end};
}
template <typename ContainerType, typename KeySelector, typename SortOrder>
void sortEntriesBy(ContainerType& entries, KeySelector keySelector, SortOrder ascending) {
entries.sort([keySelector, ascending](const auto& a, const auto& b) {
return ascending ? keySelector(a) < keySelector(b) : keySelector(a) > keySelector(b);
});
}
namespace ui {
using RecentEntriesColumn = std::pair<std::string, size_t>;

View File

@ -311,6 +311,18 @@ std::string to_string_file_size(uint32_t file_size) {
return to_string_dec_uint(file_size) + suffix[suffix_index];
}
std::string to_string_mac_address(const uint8_t* macAddress, uint8_t length) {
std::string string;
string += to_string_hex(macAddress[0], 2);
for (int i = 1; i < length; i++) {
string += ":" + to_string_hex(macAddress[i], 2);
}
return string;
}
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

@ -76,6 +76,9 @@ std::string to_string_FAT_timestamp(const FATTimestamp& timestamp);
// Gets a human readable file size string.
std::string to_string_file_size(uint32_t file_size);
// Converts Mac Address to string.
std::string to_string_mac_address(const uint8_t* macAddress, uint8_t length);
/* 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);